rc-stack.c 2.77 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*
 * Copyright (C) 2014 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
 */

#include <assert.h>
#include <ross.h>
#include "codes/rc-stack.h"
#include "codes/quicklist.h"

12 13 14 15 16 17
enum rc_stack_mode {
    RC_NONOPT, // not in optimistic mode
    RC_OPT, // optimistic mode
    RC_OPT_DBG // optimistic *debug* mode (requires special handling)
};

18 19 20
typedef struct rc_entry_s {
    tw_stime time;
    void * data;
21
    void (*free_fn)(void*);
22 23 24 25 26
    struct qlist_head ql;
} rc_entry;

struct rc_stack {
    int count;
27
    enum rc_stack_mode mode;
28 29 30 31
    struct qlist_head head;
};

void rc_stack_create(struct rc_stack **s){
32
    struct rc_stack *ss = (struct rc_stack*)malloc(sizeof(*ss));
33 34 35 36
    if (ss) {
        INIT_QLIST_HEAD(&ss->head);
        ss->count = 0;
    }
37 38 39 40
    switch (g_tw_synchronization_protocol) {
        case OPTIMISTIC:
            ss->mode = RC_OPT;
            break;
41 42 43
        case OPTIMISTIC_REALTIME:
            ss->mode = RC_OPT;
            break;
44 45 46 47 48 49
        case OPTIMISTIC_DEBUG:
            ss->mode = RC_OPT_DBG;
            break;
        default:
            ss->mode = RC_NONOPT;
    }
50 51 52
    *s = ss;
}

53 54
void rc_stack_destroy(struct rc_stack *s) {
    rc_stack_gc(NULL, s);
55 56 57 58
    free(s);
}

void rc_stack_push(
59
        tw_lp const *lp,
60
        void * data,
61
        void (*free_fn)(void*),
62
        struct rc_stack *s){
63
    if (s->mode != RC_NONOPT || free_fn == NULL) {
64 65 66 67 68 69 70 71 72 73
        rc_entry * ent = (rc_entry*)malloc(sizeof(*ent));
        assert(ent);
        ent->time = tw_now(lp);
        ent->data = data;
        ent->free_fn = free_fn;
        qlist_add_tail(&ent->ql, &s->head);
        s->count++;
    }
    else
        free_fn(data);
74 75 76
}

void* rc_stack_pop(struct rc_stack *s){
77 78
    void * ret = NULL;
    rc_entry *ent = NULL;
79 80 81 82 83
    struct qlist_head *item = qlist_pop_back(&s->head);
    if (item == NULL)
        tw_error(TW_LOC,
                "could not pop item from rc stack (stack likely empty)\n");
    s->count--;
84 85 86 87
    ent = qlist_entry(item, rc_entry, ql);
    ret = ent->data;
    free(ent);
    return ret;
88 89
}

90
int rc_stack_count(struct rc_stack const *s) { return s->count; }
91

92
void rc_stack_gc(tw_lp const *lp, struct rc_stack *s) {
93 94 95 96 97
    // in optimistic debug mode, we can't gc anything, because we'll be rolling
    // back to the beginning
    if (s->mode == RC_OPT_DBG)
        return;

98 99 100
    struct qlist_head *ent = s->head.next;
    while (ent != &s->head) {
        rc_entry *r = qlist_entry(ent, rc_entry, ql);
101
        if (lp == NULL || r->time < lp->pe->GVT){
102
            qlist_del(ent);
103
            if (r->free_fn) r->free_fn(r->data);
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
            free(r);
            s->count--;
            ent = s->head.next;
        }
        else
            break;
    }
}

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 *
 * vim: ts=8 sts=4 sw=4 expandtab
 */