rc-stack.c 2.69 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 41 42 43 44 45 46
    switch (g_tw_synchronization_protocol) {
        case OPTIMISTIC:
            ss->mode = RC_OPT;
            break;
        case OPTIMISTIC_DEBUG:
            ss->mode = RC_OPT_DBG;
            break;
        default:
            ss->mode = RC_NONOPT;
    }
47 48 49
    *s = ss;
}

50 51
void rc_stack_destroy(struct rc_stack *s) {
    rc_stack_gc(NULL, s);
52 53 54 55
    free(s);
}

void rc_stack_push(
56
        tw_lp const *lp,
57
        void * data,
58
        void (*free_fn)(void*),
59
        struct rc_stack *s){
60
    if (s->mode != RC_NONOPT || free_fn == NULL) {
61 62 63 64 65 66 67 68 69 70
        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);
71 72 73
}

void* rc_stack_pop(struct rc_stack *s){
74 75
    void * ret = NULL;
    rc_entry *ent = NULL;
76 77 78 79 80
    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--;
81 82 83 84
    ent = qlist_entry(item, rc_entry, ql);
    ret = ent->data;
    free(ent);
    return ret;
85 86
}

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

89
void rc_stack_gc(tw_lp const *lp, struct rc_stack *s) {
90 91 92 93 94
    // 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;

95 96 97
    struct qlist_head *ent = s->head.next;
    while (ent != &s->head) {
        rc_entry *r = qlist_entry(ent, rc_entry, ql);
98
        if (lp == NULL || r->time < lp->pe->GVT){
99
            qlist_del(ent);
100
            if (r->free_fn) r->free_fn(r->data);
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
            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
 */