From: Peizhao Ou Date: Wed, 18 Nov 2015 13:59:31 +0000 (-0800) Subject: edits X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=dddb190f43cd31d29dd0ce06739fc9cd22f25f73;p=cdsspec-compiler.git edits --- diff --git a/benchmark/ms-queue/my_queue.c b/benchmark/ms-queue/my_queue.c index d5e889d..b942be5 100644 --- a/benchmark/ms-queue/my_queue.c +++ b/benchmark/ms-queue/my_queue.c @@ -140,11 +140,11 @@ void enqueue(queue_t *q, unsigned int val) unsigned int ptr = get_ptr(atomic_load_explicit(&q->nodes[get_ptr(tail)].next, acquire)); pointer value = MAKE_POINTER(ptr, get_count(tail) + 1); - /****FIXME: miss ****/ + /**** SPEC (sequential, testcase2.c) ****/ // Second release can be just relaxed bool succ = false; succ = atomic_compare_exchange_strong_explicit(&q->tail, - &tail, value, release, relaxed); + &tail, value, relaxed, relaxed); if (succ) { //printf("miss2_enqueue CAS succ\n"); } @@ -214,13 +214,13 @@ bool dequeue(queue_t *q, int *retVal) if (get_ptr(next) == 0) { // NULL return false; // NULL } - /**** FIXME: miss ****/ + /**** SPEC (sequential testcase3.c) ****/ // Second release can be just relaxed bool succ = false; succ = atomic_compare_exchange_strong_explicit(&q->tail, &tail, MAKE_POINTER(get_ptr(next), get_count(tail) + 1), - release, relaxed); + release, relaxed); if (succ) { //printf("miss4_dequeue CAS succ\n"); } diff --git a/benchmark/ms-queue/testcase2.c b/benchmark/ms-queue/testcase2.c index 8ab6dbf..4da629e 100644 --- a/benchmark/ms-queue/testcase2.c +++ b/benchmark/ms-queue/testcase2.c @@ -5,7 +5,7 @@ #include "my_queue.h" #include "model-assert.h" -static int procs = 2; +static int procs = 3; static queue_t *queue; static thrd_t *threads; static unsigned int *input; @@ -39,13 +39,9 @@ static void main_task(void *param) else printf("Thrd 1: Dequeue NULL.\n"); } else if (pid % 4 == 1) { + enqueue(queue, 1); + } else if (pid % 4 == 2) { enqueue(queue, 2); - output2 = 1; - succ2 = dequeue(queue, &output2); - if (succ2) - printf("Thrd 2: Dequeue %d.\n", output2); - else - printf("Thrd 2: Dequeue NULL.\n"); } } diff --git a/benchmark/ms-queue/testcase3.c b/benchmark/ms-queue/testcase3.c index 8ab6dbf..526593c 100644 --- a/benchmark/ms-queue/testcase3.c +++ b/benchmark/ms-queue/testcase3.c @@ -5,7 +5,7 @@ #include "my_queue.h" #include "model-assert.h" -static int procs = 2; +static int procs = 3; static queue_t *queue; static thrd_t *threads; static unsigned int *input; @@ -39,13 +39,17 @@ static void main_task(void *param) else printf("Thrd 1: Dequeue NULL.\n"); } else if (pid % 4 == 1) { - enqueue(queue, 2); - output2 = 1; - succ2 = dequeue(queue, &output2); - if (succ2) - printf("Thrd 2: Dequeue %d.\n", output2); + enqueue(queue, 1); + printf("Thrd 2: Enqueue %d.\n", 1); + } else if (pid % 4 == 2) { + //enqueue(queue, 2); + + output1 = 1; + succ1 = dequeue(queue, &output1); + if (succ1) + printf("Thrd 3: Dequeue %d.\n", output1); else - printf("Thrd 2: Dequeue NULL.\n"); + printf("Thrd 3: Dequeue NULL.\n"); } } diff --git a/output/chase-lev-deque-bugfix/deque.c b/output/chase-lev-deque-bugfix/deque.c new file mode 100644 index 0000000..15ffe0f --- /dev/null +++ b/output/chase-lev-deque-bugfix/deque.c @@ -0,0 +1,270 @@ +#include +#include +#include "deque.h" +#include +#include + +Deque * create() { + Deque * q = (Deque *) calloc(1, sizeof(Deque)); + Array * a = (Array *) calloc(1, sizeof(Array)+2*sizeof(atomic_int)); + atomic_store_explicit(&q->array, a, memory_order_relaxed); + atomic_store_explicit(&q->top, 0, memory_order_relaxed); + atomic_store_explicit(&q->bottom, 0, memory_order_relaxed); + atomic_store_explicit(&a->size, 2, memory_order_relaxed); + return q; +} + + + +int take(Deque * q) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 0; // Take + interface_begin->interface_name = "Take"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + int __RET__ = __wrapper__take(q); + Take_info* info = (Take_info*) malloc(sizeof(Take_info)); + info->__RET__ = __RET__; + info->q = q; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 0; // Take + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +int __wrapper__take(Deque * q) { + size_t b = atomic_load_explicit(&q->bottom, memory_order_relaxed) - 1; + /* Automatically generated code for commit point define check: Take_Read_Bottom */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 0; + cp_define_check->label_name = "Take_Read_Bottom"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed); + + atomic_store_explicit(&q->bottom, b, memory_order_relaxed); + + atomic_thread_fence(memory_order_seq_cst); + size_t t = atomic_load_explicit(&q->top, memory_order_relaxed); + + int x; + if (t <= b) { + + int size = atomic_load_explicit(&a->size,memory_order_relaxed); + x = atomic_load_explicit(&a->buffer[b % size], memory_order_relaxed); + + if (t == b) { + + bool succ = atomic_compare_exchange_strong_explicit(&q->top, &t, t + + 1, memory_order_seq_cst, memory_order_relaxed); + + + /* Automatically generated code for commit point define check: Take_Additional_Point */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 1; + cp_define_check->label_name = "Take_Additional_Point"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + if (!succ) { + + x = EMPTY; + } + atomic_store_explicit(&q->bottom, b + 1, memory_order_relaxed); + } + } else { + x = EMPTY; + atomic_store_explicit(&q->bottom, b + 1, memory_order_relaxed); + } + return x; +} + +void resize(Deque *q) { + Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed); + size_t size=atomic_load_explicit(&a->size, memory_order_relaxed); + size_t new_size=size << 1; + Array *new_a = (Array *) calloc(1, new_size * sizeof(atomic_int) + sizeof(Array)); + size_t top=atomic_load_explicit(&q->top, memory_order_relaxed); + size_t bottom=atomic_load_explicit(&q->bottom, memory_order_relaxed); + atomic_store_explicit(&new_a->size, new_size, memory_order_relaxed); + size_t i; + for(i=top; i < bottom; i++) { + atomic_store_explicit(&new_a->buffer[i % new_size], atomic_load_explicit(&a->buffer[i % size], memory_order_relaxed), memory_order_relaxed); + } + + atomic_store_explicit(&q->array, new_a, memory_order_release); + } + + +void push(Deque * q, int x) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 1; // Push + interface_begin->interface_name = "Push"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__push(q, x); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 1; // Push + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Push_info* info = (Push_info*) malloc(sizeof(Push_info)); + info->q = q; + info->x = x; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 1; // Push + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__push(Deque * q, int x) { + size_t b = atomic_load_explicit(&q->bottom, memory_order_relaxed); + + size_t t = atomic_load_explicit(&q->top, memory_order_acquire); + Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed); + if (b - t > atomic_load_explicit(&a->size, memory_order_relaxed) - 1) { + resize(q); + + } + int size = atomic_load_explicit(&a->size, memory_order_relaxed); + + atomic_store_explicit(&a->buffer[b % size], x, memory_order_relaxed); + + + atomic_thread_fence(memory_order_release); + /* Automatically generated code for commit point define check: Push_Update_Bottom */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 2; + cp_define_check->label_name = "Push_Update_Bottom"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + atomic_store_explicit(&q->bottom, b + 1, memory_order_relaxed); + +} + + +int steal(Deque * q) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 2; // Steal + interface_begin->interface_name = "Steal"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + int __RET__ = __wrapper__steal(q); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 2; // Steal + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Steal_info* info = (Steal_info*) malloc(sizeof(Steal_info)); + info->__RET__ = __RET__; + info->q = q; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 2; // Steal + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +int __wrapper__steal(Deque * q) { + size_t t = atomic_load_explicit(&q->top, memory_order_acquire); + + atomic_thread_fence(memory_order_seq_cst); + + size_t b = atomic_load_explicit(&q->bottom, memory_order_acquire); + /* Automatically generated code for commit point define check: Steal_Read_Bottom */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 3; + cp_define_check->label_name = "Steal_Read_Bottom"; + cp_define_check->interface_num = 2; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + + + int x = EMPTY; + if (t < b) { + + + Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_acquire); + + int size = atomic_load_explicit(&a->size, memory_order_relaxed); + x = atomic_load_explicit(&a->buffer[t % size], memory_order_relaxed); + + + bool succ = atomic_compare_exchange_strong_explicit(&q->top, &t, t + 1, + memory_order_seq_cst, memory_order_relaxed); + + + /* Automatically generated code for commit point define check: Steal_Additional_Point */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 4; + cp_define_check->label_name = "Steal_Additional_Point"; + cp_define_check->interface_num = 2; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + + + if (!succ) { + + return ABORT; + } + } + return x; +} + diff --git a/output/chase-lev-deque-bugfix/deque.h b/output/chase-lev-deque-bugfix/deque.h new file mode 100644 index 0000000..3a3a869 --- /dev/null +++ b/output/chase-lev-deque-bugfix/deque.h @@ -0,0 +1,233 @@ +#ifndef DEQUE_H +#define DEQUE_H + +#include +#include +#include +#include +#include +#include "common.h" + +typedef struct { + atomic_size_t size; + atomic_int buffer[]; +} Array; + +typedef struct { + atomic_size_t top, bottom; + atomic_uintptr_t array; +} Deque; + +#define EMPTY 0xffffffff +#define ABORT 0xfffffffe + +/* All other user-defined structs */ +static IntegerList * __deque; +/* All other user-defined functions */ +inline static bool succ ( int res ) { +return res != EMPTY && res != ABORT ; +} + +/* Definition of interface info struct: Steal */ +typedef struct Steal_info { +int __RET__; +Deque * q; +} Steal_info; +/* End of info struct definition: Steal */ + +/* ID function of interface: Steal */ +inline static call_id_t Steal_id(void *info, thread_id_t __TID__) { + Steal_info* theInfo = (Steal_info*)info; + int __RET__ = theInfo->__RET__; + Deque * q = theInfo->q; + + call_id_t __ID__ = succ ( __RET__ ) ? __RET__ : DEFAULT_CALL_ID; + return __ID__; +} +/* End of ID function: Steal */ + +/* Check action function of interface: Steal */ +inline static bool Steal_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Steal_info* theInfo = (Steal_info*)info; + int __RET__ = theInfo->__RET__; + Deque * q = theInfo->q; + + int elem = 0 ; + if ( succ ( __RET__ ) ) { + elem = front ( __deque ) ; + pop_front ( __deque ) ; + } + check_passed = succ ( __RET__ ) ? __RET__ == elem : true; + if (!check_passed) + return false; + return true; +} +/* End of check action function: Steal */ + +/* Definition of interface info struct: Take */ +typedef struct Take_info { +int __RET__; +Deque * q; +} Take_info; +/* End of info struct definition: Take */ + +/* ID function of interface: Take */ +inline static call_id_t Take_id(void *info, thread_id_t __TID__) { + Take_info* theInfo = (Take_info*)info; + int __RET__ = theInfo->__RET__; + Deque * q = theInfo->q; + + call_id_t __ID__ = succ ( __RET__ ) ? __RET__ : DEFAULT_CALL_ID; + return __ID__; +} +/* End of ID function: Take */ + +/* Check action function of interface: Take */ +inline static bool Take_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Take_info* theInfo = (Take_info*)info; + int __RET__ = theInfo->__RET__; + Deque * q = theInfo->q; + + int elem = 0 ; + if ( succ ( __RET__ ) ) { + elem = back ( __deque ) ; + pop_back ( __deque ) ; + } + check_passed = succ ( __RET__ ) ? __RET__ == elem : true; + if (!check_passed) + return false; + return true; +} +/* End of check action function: Take */ + +/* Definition of interface info struct: Push */ +typedef struct Push_info { +Deque * q; +int x; +} Push_info; +/* End of info struct definition: Push */ + +/* ID function of interface: Push */ +inline static call_id_t Push_id(void *info, thread_id_t __TID__) { + Push_info* theInfo = (Push_info*)info; + Deque * q = theInfo->q; + int x = theInfo->x; + + call_id_t __ID__ = x; + return __ID__; +} +/* End of ID function: Push */ + +/* Check action function of interface: Push */ +inline static bool Push_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Push_info* theInfo = (Push_info*)info; + Deque * q = theInfo->q; + int x = theInfo->x; + + push_back ( __deque , x ) ; + return true; +} +/* End of check action function: Push */ + +#define INTERFACE_SIZE 3 +static void** func_ptr_table; +static hb_rule** hb_rule_table; +static commutativity_rule** commutativity_rule_table; +inline static bool CommutativityCondition0(void *info1, void *info2) { + Push_info *_info1 = (Push_info*) info1; + Steal_info *_info2 = (Steal_info*) info2; + return true; +} +inline static bool CommutativityCondition1(void *info1, void *info2) { + Take_info *_info1 = (Take_info*) info1; + Steal_info *_info2 = (Steal_info*) info2; + return true; +} + +/* Initialization of sequential varialbes */ +static void __SPEC_INIT__() { + __deque = createIntegerList ( ) ; +} + +/* Cleanup routine of sequential variables */ +static bool __SPEC_CLEANUP__() { + if ( __deque ) destroyIntegerList ( __deque ) ; + return true ; +} + +/* Define function for sequential code initialization */ +inline static void __sequential_init() { + /* Init func_ptr_table */ + func_ptr_table = (void**) malloc(sizeof(void*) * 3 * 2); + func_ptr_table[2 * 2] = (void*) &Steal_id; + func_ptr_table[2 * 2 + 1] = (void*) &Steal_check_action; + func_ptr_table[2 * 0] = (void*) &Take_id; + func_ptr_table[2 * 0 + 1] = (void*) &Take_check_action; + func_ptr_table[2 * 1] = (void*) &Push_id; + func_ptr_table[2 * 1 + 1] = (void*) &Push_check_action; + /* Push(true) -> Steal(true) */ + struct hb_rule *hbConditionInit0 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit0->interface_num_before = 1; // Push + hbConditionInit0->hb_condition_num_before = 0; // + hbConditionInit0->interface_num_after = 2; // Steal + hbConditionInit0->hb_condition_num_after = 0; // + /* Init hb_rule_table */ + hb_rule_table = (hb_rule**) malloc(sizeof(hb_rule*) * 1); + #define HB_RULE_TABLE_SIZE 1 + hb_rule_table[0] = hbConditionInit0; + /* Init commutativity_rule_table */ + commutativity_rule_table = (commutativity_rule**) malloc(sizeof(commutativity_rule*) * 2); + commutativity_rule* rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 1; + rule->interface_num_after = 2; + rule->rule = "true"; + rule->condition = CommutativityCondition0; + commutativity_rule_table[0] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 2; + rule->rule = "true"; + rule->condition = CommutativityCondition1; + commutativity_rule_table[1] = rule; + /* Pass init info, including function table info & HB rules & Commutativity Rules */ + struct anno_init *anno_init = (struct anno_init*) malloc(sizeof(struct anno_init)); + anno_init->init_func = (void_func_t) __SPEC_INIT__; + anno_init->cleanup_func = (cleanup_func_t) __SPEC_CLEANUP__; + anno_init->func_table = func_ptr_table; + anno_init->func_table_size = INTERFACE_SIZE; + anno_init->hb_rule_table = hb_rule_table; + anno_init->hb_rule_table_size = HB_RULE_TABLE_SIZE; + anno_init->commutativity_rule_table = commutativity_rule_table; + anno_init->commutativity_rule_table_size = 2; + struct spec_annotation *init = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + init->type = INIT; + init->annotation = anno_init; + cdsannotate(SPEC_ANALYSIS, init); + +} + +/* End of Global construct generation in class */ + + + +Deque * create(); +void resize(Deque *q); + +int __wrapper__take(Deque * q); + +int __wrapper__take(Deque * q) ; + +void __wrapper__push(Deque * q, int x); + +void __wrapper__push(Deque * q, int x) ; + +int __wrapper__steal(Deque * q); + +int __wrapper__steal(Deque * q) ; + +#endif + diff --git a/output/chase-lev-deque-bugfix/deque.o b/output/chase-lev-deque-bugfix/deque.o new file mode 100644 index 0000000..9314807 Binary files /dev/null and b/output/chase-lev-deque-bugfix/deque.o differ diff --git a/output/chase-lev-deque-bugfix/main b/output/chase-lev-deque-bugfix/main new file mode 100755 index 0000000..a7e3297 Binary files /dev/null and b/output/chase-lev-deque-bugfix/main differ diff --git a/output/chase-lev-deque-bugfix/main.c b/output/chase-lev-deque-bugfix/main.c new file mode 100644 index 0000000..edd09ba --- /dev/null +++ b/output/chase-lev-deque-bugfix/main.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include + +#include "model-assert.h" + +#include "deque.h" + +Deque *q; +int a; +int b; +int c; + +static void task(void * param) { + a=steal(q); + if (a == ABORT) { + printf("Steal NULL\n"); + } else { + printf("Steal %d\n", a); + } +} + +int user_main(int argc, char **argv) +{ + __sequential_init(); + + thrd_t t; + q=create(); + thrd_create(&t, task, 0); + push(q, 1); + printf("Push 1\n"); + push(q, 2); + printf("Push 2\n"); + push(q, 4); + printf("Push 4\n"); + b=take(q); + if (b == EMPTY) { + printf("Take NULL\n"); + } else { + printf("Take %d\n", b); + } + c=take(q); + if (c == EMPTY) { + printf("Take NULL\n"); + } else { + printf("Take %d\n", c); + } + thrd_join(t); + + + return 0; +} + diff --git a/output/chase-lev-deque-bugfix/testcase.c b/output/chase-lev-deque-bugfix/testcase.c new file mode 100644 index 0000000..5723259 --- /dev/null +++ b/output/chase-lev-deque-bugfix/testcase.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include + +#include "model-assert.h" + +#include "deque.h" + +Deque *q; +int a; +int b; +int c; +int x; + +static void task(void * param) { + a=steal(q); + if (a == ABORT) { + printf("Steal NULL\n"); + } else { + printf("Steal %d\n", a); + } + x=steal(q); + if (x == ABORT) { + printf("Steal NULL\n"); + } else { + printf("Steal %d\n", x); + } +} + +int user_main(int argc, char **argv) +{ + __sequential_init(); + + thrd_t t; + q=create(); + thrd_create(&t, task, 0); + push(q, 1); + printf("Push 1\n"); + push(q, 2); + printf("Push 2\n"); + push(q, 4); + printf("Push 4\n"); + b=take(q); + if (b == EMPTY) { + printf("Take NULL\n"); + } else { + printf("Take %d\n", b); + } + c=take(q); + if (c == EMPTY) { + printf("Take NULL\n"); + } else { + printf("Take %d\n", c); + } + thrd_join(t); + + + return 0; +} + diff --git a/output/chase-lev-deque-bugfix/testcase1 b/output/chase-lev-deque-bugfix/testcase1 new file mode 100755 index 0000000..c419a11 Binary files /dev/null and b/output/chase-lev-deque-bugfix/testcase1 differ diff --git a/output/chase-lev-deque-bugfix/testcase1.c b/output/chase-lev-deque-bugfix/testcase1.c new file mode 100644 index 0000000..91550f2 --- /dev/null +++ b/output/chase-lev-deque-bugfix/testcase1.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include + +#include "model-assert.h" + +#include "deque.h" + +Deque *q; +int a; +int b; +int c; +int x; + +static void task(void * param) { + a=steal(q); + if (a == ABORT) { + printf("Steal NULL\n"); + } else { + printf("Steal %d\n", a); + } + + x=steal(q); + if (x == ABORT) { + printf("Steal NULL\n"); + } else { + printf("Steal %d\n", x); + } +} + +int user_main(int argc, char **argv) +{ + __sequential_init(); + + thrd_t t; + q=create(); + thrd_create(&t, task, 0); + push(q, 1); + printf("Push 1\n"); + push(q, 2); + printf("Push 2\n"); + push(q, 4); + printf("Push 4\n"); + b=take(q); + if (b == EMPTY) { + printf("Take NULL\n"); + } else { + printf("Take %d\n", b); + } + c=take(q); + if (c == EMPTY) { + printf("Take NULL\n"); + } else { + printf("Take %d\n", c); + } + thrd_join(t); + + + return 0; +} + diff --git a/output/chase-lev-deque-bugfix/testcase2 b/output/chase-lev-deque-bugfix/testcase2 new file mode 100755 index 0000000..41500c3 Binary files /dev/null and b/output/chase-lev-deque-bugfix/testcase2 differ diff --git a/output/chase-lev-deque-bugfix/testcase2.c b/output/chase-lev-deque-bugfix/testcase2.c new file mode 100644 index 0000000..dc28d1b --- /dev/null +++ b/output/chase-lev-deque-bugfix/testcase2.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include + +#include "model-assert.h" + +#include "deque.h" + +Deque *q; +int a; +int b; +int c; +int x; + +static void task(void * param) { + a=steal(q); + if (a == ABORT) { + printf("Steal NULL\n"); + } else { + printf("Steal %d\n", a); + } + +} + +int user_main(int argc, char **argv) +{ + __sequential_init(); + + thrd_t t; + q=create(); + push(q, 1); + printf("Push 1\n"); + push(q, 2); + printf("Push 2\n"); + push(q, 4); + printf("Push 4\n"); + push(q, 5); + printf("Push 5\n"); + thrd_create(&t, task, 0); + + b=take(q); + if (b == EMPTY) { + printf("Take NULL\n"); + } else { + printf("Take %d\n", b); + } + c=take(q); + if (c == EMPTY) { + printf("Take NULL\n"); + } else { + printf("Take %d\n", c); + } + thrd_join(t); + + + return 0; +} + diff --git a/output/cliffc-hashtable/cliffc_hashtable.h b/output/cliffc-hashtable/cliffc_hashtable.h new file mode 100644 index 0000000..d102f2f --- /dev/null +++ b/output/cliffc-hashtable/cliffc_hashtable.h @@ -0,0 +1,911 @@ +#ifndef CLIFFC_HASHTABLE_H +#define CLIFFC_HASHTABLE_H + +#include +#include +#include "stdio.h" +#ifdef STANDALONE +#include +#define MODEL_ASSERT assert +#else +#include +#endif + +#include +#include +#include +#include +#include +#include "common.h" + +using namespace std; + + + +template +class cliffc_hashtable; + + +struct kvs_data { + int _size; + atomic *_data; + + kvs_data(int sz) { + _size = sz; + int real_size = sz * 2 + 2; + _data = new atomic[real_size]; + int *hashes = new int[_size]; + int i; + for (i = 0; i < _size; i++) { + hashes[i] = 0; + } + for (i = 2; i < real_size; i++) { + _data[i].store(NULL, memory_order_relaxed); + } + _data[1].store(hashes, memory_order_relaxed); + } + + ~kvs_data() { + int *hashes = (int*) _data[1].load(memory_order_relaxed); + delete hashes; + delete[] _data; + } +}; + +struct slot { + bool _prime; + void *_ptr; + + slot(bool prime, void *ptr) { + _prime = prime; + _ptr = ptr; + } +}; + + + + +template +class cliffc_hashtable { +/* All other user-defined structs */ +static spec_table * map; +static spec_table * id_map; +static id_tag_t * tag; +/* All other user-defined functions */ +inline static bool equals_key ( void * ptr1 , void * ptr2 ) { +TypeK * key1 = ( TypeK * ) ptr1 , * key2 = ( TypeK * ) ptr2 ; +if ( key1 == NULL || key2 == NULL ) return false ; +return key1 -> equals ( key2 ) ; +} + +inline static bool equals_val ( void * ptr1 , void * ptr2 ) { +if ( ptr1 == ptr2 ) return true ; +TypeV * val1 = ( TypeV * ) ptr1 , * val2 = ( TypeV * ) ptr2 ; +if ( val1 == NULL || val2 == NULL ) return false ; +return val1 -> equals ( val2 ) ; +} + +inline static bool equals_id ( void * ptr1 , void * ptr2 ) { +id_tag_t * id1 = ( id_tag_t * ) ptr1 , * id2 = ( id_tag_t * ) ptr2 ; +if ( id1 == NULL || id2 == NULL ) return false ; +return ( * id1 ) . tag == ( * id2 ) . tag ; +} + +inline static call_id_t getKeyTag ( TypeK * key ) { +if ( ! spec_table_contains ( id_map , key ) ) { +call_id_t cur_id = current ( tag ) ; +spec_table_put ( id_map , key , ( void * ) cur_id ) ; +next ( tag ) ; +return cur_id ; +} +else { +call_id_t res = ( call_id_t ) spec_table_get ( id_map , key ) ; +return res ; +} +} + +/* Definition of interface info struct: Put */ +typedef struct Put_info { +TypeV * __RET__; +TypeK * key; +TypeV * val; +} Put_info; +/* End of info struct definition: Put */ + +/* ID function of interface: Put */ +inline static call_id_t Put_id(void *info, thread_id_t __TID__) { + Put_info* theInfo = (Put_info*)info; + TypeV * __RET__ = theInfo->__RET__; + TypeK * key = theInfo->key; + TypeV * val = theInfo->val; + + call_id_t __ID__ = getKeyTag ( key ); + return __ID__; +} +/* End of ID function: Put */ + +/* Check action function of interface: Put */ +inline static bool Put_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Put_info* theInfo = (Put_info*)info; + TypeV * __RET__ = theInfo->__RET__; + TypeK * key = theInfo->key; + TypeV * val = theInfo->val; + + TypeV * _Old_Val = ( TypeV * ) spec_table_get ( map , key ) ; + spec_table_put ( map , key , val ) ; + bool passed = false ; + if ( ! passed ) { + int old = _Old_Val == NULL ? 0 : _Old_Val -> _val ; + int ret = __RET__ == NULL ? 0 : __RET__ -> _val ; + } + check_passed = equals_val ( __RET__ , _Old_Val ); + if (!check_passed) + return false; + return true; +} +/* End of check action function: Put */ + +/* Definition of interface info struct: Get */ +typedef struct Get_info { +TypeV * __RET__; +TypeK * key; +} Get_info; +/* End of info struct definition: Get */ + +/* ID function of interface: Get */ +inline static call_id_t Get_id(void *info, thread_id_t __TID__) { + Get_info* theInfo = (Get_info*)info; + TypeV * __RET__ = theInfo->__RET__; + TypeK * key = theInfo->key; + + call_id_t __ID__ = getKeyTag ( key ); + return __ID__; +} +/* End of ID function: Get */ + +/* Check action function of interface: Get */ +inline static bool Get_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Get_info* theInfo = (Get_info*)info; + TypeV * __RET__ = theInfo->__RET__; + TypeK * key = theInfo->key; + + TypeV * _Old_Val = ( TypeV * ) spec_table_get ( map , key ) ; + bool passed = false ; + if ( ! passed ) { + int old = _Old_Val == NULL ? 0 : _Old_Val -> _val ; + int ret = __RET__ == NULL ? 0 : __RET__ -> _val ; + } + check_passed = equals_val ( _Old_Val , __RET__ ); + if (!check_passed) + return false; + return true; +} +/* End of check action function: Get */ + +#define INTERFACE_SIZE 2 +static void** func_ptr_table; +static anno_hb_init** hb_init_table; + +/* Initialization of sequential varialbes */ +static void __SPEC_INIT__() { + map = new_spec_table_default ( equals_key ) ; + id_map = new_spec_table_default ( equals_id ) ; + tag = new_id_tag ( ) ; +} + +/* Cleanup routine of sequential variables */ +static void __SPEC_CLEANUP__() { +} + +/* Define function for sequential code initialization */ +inline static void __sequential_init() { + /* Init func_ptr_table */ + func_ptr_table = (void**) malloc(sizeof(void*) * 2 * 2); + func_ptr_table[2 * 1] = (void*) &Put_id; + func_ptr_table[2 * 1 + 1] = (void*) &Put_check_action; + func_ptr_table[2 * 0] = (void*) &Get_id; + func_ptr_table[2 * 0 + 1] = (void*) &Get_check_action; + /* Put(true) -> Put(true) */ + struct anno_hb_init *hbConditionInit0 = (struct anno_hb_init*) malloc(sizeof(struct anno_hb_init)); + hbConditionInit0->interface_num_before = 1; // Put + hbConditionInit0->hb_condition_num_before = 0; // + hbConditionInit0->interface_num_after = 1; // Put + hbConditionInit0->hb_condition_num_after = 0; // + /* Put(true) -> Get(true) */ + struct anno_hb_init *hbConditionInit1 = (struct anno_hb_init*) malloc(sizeof(struct anno_hb_init)); + hbConditionInit1->interface_num_before = 1; // Put + hbConditionInit1->hb_condition_num_before = 0; // + hbConditionInit1->interface_num_after = 0; // Get + hbConditionInit1->hb_condition_num_after = 0; // + /* Init hb_init_table */ + hb_init_table = (anno_hb_init**) malloc(sizeof(anno_hb_init*) * 2); + #define HB_INIT_TABLE_SIZE 2 + hb_init_table[0] = hbConditionInit0; + hb_init_table[1] = hbConditionInit1; + /* Pass init info, including function table info & HB rules */ + struct anno_init *anno_init = (struct anno_init*) malloc(sizeof(struct anno_init)); + anno_init->init_func = (void*) __SPEC_INIT__; + anno_init->cleanup_func = (void*) __SPEC_CLEANUP__; + anno_init->func_table = func_ptr_table; + anno_init->func_table_size = INTERFACE_SIZE; + anno_init->hb_init_table = hb_init_table; + anno_init->hb_init_table_size = HB_INIT_TABLE_SIZE; + struct spec_annotation *init = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + init->type = INIT; + init->annotation = anno_init; + cdsannotate(SPEC_ANALYSIS, init); + +} + +/* End of Global construct generation in class */ + + +friend class CHM; + + private: + class CHM { + friend class cliffc_hashtable; + private: + atomic _newkvs; + + atomic_int _size; + + atomic_int _slots; + + atomic_int _copy_idx; + + atomic_int _copy_done; + + public: + CHM(int size) { + _newkvs.store(NULL, memory_order_relaxed); + _size.store(size, memory_order_relaxed); + _slots.store(0, memory_order_relaxed); + + _copy_idx.store(0, memory_order_relaxed); + _copy_done.store(0, memory_order_relaxed); + } + + ~CHM() {} + + private: + + bool table_full(int reprobe_cnt, int len) { + return + reprobe_cnt >= REPROBE_LIMIT && + _slots.load(memory_order_relaxed) >= reprobe_limit(len); + } + + kvs_data* resize(cliffc_hashtable *topmap, kvs_data *kvs) { + + kvs_data *newkvs = _newkvs.load(memory_order_acquire); + if (newkvs != NULL) + return newkvs; + + int oldlen = kvs->_size; + int sz = _size.load(memory_order_relaxed); + int newsz = sz; + + if (sz >= (oldlen >> 2)) { newsz = oldlen << 1; if (sz >= (oldlen >> 1)) + newsz = oldlen << 2; } + + if (newsz <= oldlen) newsz = oldlen << 1; + if (newsz < oldlen) newsz = oldlen; + + + newkvs = _newkvs.load(memory_order_acquire); + if (newkvs != NULL) return newkvs; + + newkvs = new kvs_data(newsz); + void *chm = (void*) new CHM(sz); + newkvs->_data[0].store(chm, memory_order_relaxed); + + kvs_data *cur_newkvs; + + if ((cur_newkvs = _newkvs.load(memory_order_acquire)) != NULL) + return cur_newkvs; + kvs_data *desired = (kvs_data*) NULL; + kvs_data *expected = (kvs_data*) newkvs; + + if (!_newkvs.compare_exchange_strong(desired, expected, memory_order_release, + memory_order_relaxed)) { + delete newkvs; + + newkvs = _newkvs.load(memory_order_acquire); + } + return newkvs; + } + + void help_copy_impl(cliffc_hashtable *topmap, kvs_data *oldkvs, + bool copy_all) { + MODEL_ASSERT (get_chm(oldkvs) == this); + + kvs_data *newkvs = _newkvs.load(memory_order_acquire); + int oldlen = oldkvs->_size; + int min_copy_work = oldlen > 1024 ? 1024 : oldlen; + + int panic_start = -1; + int copyidx; + while (_copy_done.load(memory_order_relaxed) < oldlen) { + copyidx = _copy_idx.load(memory_order_relaxed); + if (panic_start == -1) { copyidx = _copy_idx.load(memory_order_relaxed); + while (copyidx < (oldlen << 1) && + !_copy_idx.compare_exchange_strong(copyidx, copyidx + + min_copy_work, memory_order_relaxed, memory_order_relaxed)) + copyidx = _copy_idx.load(memory_order_relaxed); + if (!(copyidx < (oldlen << 1))) + panic_start = copyidx; + } + + int workdone = 0; + for (int i = 0; i < min_copy_work; i++) + if (copy_slot(topmap, (copyidx + i) & (oldlen - 1), oldkvs, + newkvs)) + workdone++; + if (workdone > 0) + copy_check_and_promote(topmap, oldkvs, workdone); + + copyidx += min_copy_work; + if (!copy_all && panic_start == -1) + return; } + copy_check_and_promote(topmap, oldkvs, 0); } + + kvs_data* copy_slot_and_check(cliffc_hashtable *topmap, kvs_data + *oldkvs, int idx, void *should_help) { + + kvs_data *newkvs = _newkvs.load(memory_order_acquire); + if (copy_slot(topmap, idx, oldkvs, newkvs)) + copy_check_and_promote(topmap, oldkvs, 1); return (should_help == NULL) ? newkvs : topmap->help_copy(newkvs); + } + + void copy_check_and_promote(cliffc_hashtable *topmap, kvs_data* + oldkvs, int workdone) { + int oldlen = oldkvs->_size; + int copyDone = _copy_done.load(memory_order_relaxed); + if (workdone > 0) { + while (true) { + copyDone = _copy_done.load(memory_order_relaxed); + if (_copy_done.compare_exchange_weak(copyDone, copyDone + + workdone, memory_order_relaxed, memory_order_relaxed)) + break; + } + } + + if (copyDone + workdone == oldlen && + topmap->_kvs.load(memory_order_relaxed) == oldkvs) { + + kvs_data *newkvs = _newkvs.load(memory_order_acquire); + + topmap->_kvs.compare_exchange_strong(oldkvs, newkvs, memory_order_release, + memory_order_relaxed); + } + } + + bool copy_slot(cliffc_hashtable *topmap, int idx, kvs_data *oldkvs, + kvs_data *newkvs) { + slot *key_slot; + while ((key_slot = key(oldkvs, idx)) == NULL) + CAS_key(oldkvs, idx, NULL, TOMBSTONE); + + slot *oldval = val(oldkvs, idx); + while (!is_prime(oldval)) { + slot *box = (oldval == NULL || oldval == TOMBSTONE) + ? TOMBPRIME : new slot(true, oldval->_ptr); + if (CAS_val(oldkvs, idx, oldval, box)) { + if (box == TOMBPRIME) + return 1; oldval = box; break; + } + oldval = val(oldkvs, idx); } + + if (oldval == TOMBPRIME) return false; + slot *old_unboxed = new slot(false, oldval->_ptr); + int copied_into_new = (putIfMatch(topmap, newkvs, key_slot, old_unboxed, + NULL) == NULL); + + while (!CAS_val(oldkvs, idx, oldval, TOMBPRIME)) + oldval = val(oldkvs, idx); + + return copied_into_new; + } + }; + + + + private: + static const int Default_Init_Size = 4; + static slot* const MATCH_ANY; + static slot* const NO_MATCH_OLD; + + static slot* const TOMBPRIME; + static slot* const TOMBSTONE; + + static const int REPROBE_LIMIT = 10; + atomic _kvs; + + public: + cliffc_hashtable() { + __sequential_init(); + + kvs_data *kvs = new kvs_data(Default_Init_Size); + void *chm = (void*) new CHM(0); + kvs->_data[0].store(chm, memory_order_relaxed); + _kvs.store(kvs, memory_order_relaxed); + } + + cliffc_hashtable(int init_size) { + + __sequential_init(); + + kvs_data *kvs = new kvs_data(init_size); + void *chm = (void*) new CHM(0); + kvs->_data[0].store(chm, memory_order_relaxed); + _kvs.store(kvs, memory_order_relaxed); + } + + +TypeV * get(TypeK * key) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 0; // Get + interface_begin->interface_name = "Get"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + TypeV * __RET__ = __wrapper__get(key); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 0; // Get + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Get_info* info = (Get_info*) malloc(sizeof(Get_info)); + info->__RET__ = __RET__; + info->key = key; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 0; // Get + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +TypeV * __wrapper__get(TypeK * key) { + slot *key_slot = new slot(false, key); + int fullhash = hash(key_slot); + + kvs_data *kvs = _kvs.load(memory_order_acquire); + + slot *V = get_impl(this, kvs, key_slot, fullhash); + if (V == NULL) return NULL; + MODEL_ASSERT (!is_prime(V)); + return (TypeV*) V->_ptr; + } + + +TypeV * put(TypeK * key, TypeV * val) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 1; // Put + interface_begin->interface_name = "Put"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + TypeV * __RET__ = __wrapper__put(key, val); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 1; // Put + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Put_info* info = (Put_info*) malloc(sizeof(Put_info)); + info->__RET__ = __RET__; + info->key = key; + info->val = val; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 1; // Put + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +TypeV * __wrapper__put(TypeK * key, TypeV * val) { + return putIfMatch(key, val, NO_MATCH_OLD); + } + + + TypeV* putIfAbsent(TypeK *key, TypeV *value) { + return putIfMatch(key, val, TOMBSTONE); + } + + + TypeV* remove(TypeK *key) { + return putIfMatch(key, TOMBSTONE, NO_MATCH_OLD); + } + + + bool remove(TypeK *key, TypeV *val) { + slot *val_slot = val == NULL ? NULL : new slot(false, val); + return putIfMatch(key, TOMBSTONE, val) == val; + + } + + + TypeV* replace(TypeK *key, TypeV *val) { + return putIfMatch(key, val, MATCH_ANY); + } + + + bool replace(TypeK *key, TypeV *oldval, TypeV *newval) { + return putIfMatch(key, newval, oldval) == oldval; + } + + private: + static CHM* get_chm(kvs_data* kvs) { + CHM *res = (CHM*) kvs->_data[0].load(memory_order_relaxed); + return res; + } + + static int* get_hashes(kvs_data *kvs) { + return (int *) kvs->_data[1].load(memory_order_relaxed); + } + + static inline slot* key(kvs_data *kvs, int idx) { + MODEL_ASSERT (idx >= 0 && idx < kvs->_size); + slot *res = (slot*) kvs->_data[idx * 2 + 2].load(memory_order_relaxed); + /* Automatically generated code for potential commit point: Read_Key_Point */ + + if (true) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 0; + potential_cp_define->label_name = "Read_Key_Point"; + potential_cp_define->is_additional_point = false; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + return res; + } + + + static inline slot* val(kvs_data *kvs, int idx) { + MODEL_ASSERT (idx >= 0 && idx < kvs->_size); + + slot *res = (slot*) kvs->_data[idx * 2 + 3].load(memory_order_acquire); + /* Automatically generated code for potential commit point: Read_Val_Point */ + + if (true) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 1; + potential_cp_define->label_name = "Read_Val_Point"; + potential_cp_define->is_additional_point = false; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + return res; + + + } + + static int hash(slot *key_slot) { + MODEL_ASSERT(key_slot != NULL && key_slot->_ptr != NULL); + TypeK* key = (TypeK*) key_slot->_ptr; + int h = key->hashCode(); + h += (h << 15) ^ 0xffffcd7d; + h ^= (h >> 10); + h += (h << 3); + h ^= (h >> 6); + h += (h << 2) + (h << 14); + return h ^ (h >> 16); + } + + static int reprobe_limit(int len) { + return REPROBE_LIMIT + (len >> 2); + } + + static inline bool is_prime(slot *val) { + return (val != NULL) && val->_prime; + } + + static bool keyeq(slot *K, slot *key_slot, int *hashes, int hash, + int fullhash) { + MODEL_ASSERT (K != NULL); + TypeK* key_ptr = (TypeK*) key_slot->_ptr; + return + K == key_slot || + ((hashes[hash] == 0 || hashes[hash] == fullhash) && + K != TOMBSTONE && + key_ptr->equals(K->_ptr)); + } + + static bool valeq(slot *val_slot1, slot *val_slot2) { + MODEL_ASSERT (val_slot1 != NULL); + TypeK* ptr1 = (TypeV*) val_slot1->_ptr; + if (val_slot2 == NULL || ptr1 == NULL) return false; + return ptr1->equals(val_slot2->_ptr); + } + + static inline bool CAS_key(kvs_data *kvs, int idx, void *expected, void *desired) { + bool res = kvs->_data[2 * idx + 2].compare_exchange_strong(expected, + desired, memory_order_relaxed, memory_order_relaxed); + /* Automatically generated code for potential commit point: Write_Key_Point */ + + if (res) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 2; + potential_cp_define->label_name = "Write_Key_Point"; + potential_cp_define->is_additional_point = false; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + return res; + } + + + static inline bool CAS_val(kvs_data *kvs, int idx, void *expected, void + *desired) { + + bool res = kvs->_data[2 * idx + 3].compare_exchange_strong(expected, + desired, memory_order_acq_rel, memory_order_relaxed); + /* Automatically generated code for potential commit point: Write_Val_Point */ + + if (res) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 3; + potential_cp_define->label_name = "Write_Val_Point"; + potential_cp_define->is_additional_point = false; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + return res; + } + + slot* get_impl(cliffc_hashtable *topmap, kvs_data *kvs, slot* key_slot, int + fullhash) { + int len = kvs->_size; + CHM *chm = get_chm(kvs); + int *hashes = get_hashes(kvs); + + int idx = fullhash & (len - 1); + int reprobe_cnt = 0; + while (true) { + slot *K = key(kvs, idx); + /* Automatically generated code for commit point define: Get_Point1 */ + + if (K == NULL) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 4; + cp_define->label_name = "Get_Point1"; + cp_define->potential_cp_label_num = 0; + cp_define->potential_label_name = "Read_Key_Point"; + cp_define->interface_num = 0; + cp_define->is_additional_point = false; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + slot *V = val(kvs, idx); + + if (K == NULL) { + return NULL; } + + if (keyeq(K, key_slot, hashes, idx, fullhash)) { + if (!is_prime(V)) { + /* Automatically generated code for commit point clear: Get_Clear */ + + if (true) { + struct anno_cp_clear *cp_clear = (struct anno_cp_clear*) malloc(sizeof(struct anno_cp_clear)); + struct spec_annotation *annotation_cp_clear = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_clear->type = CP_CLEAR; + annotation_cp_clear->annotation = cp_clear; + cdsannotate(SPEC_ANALYSIS, annotation_cp_clear); + } + + + /* Automatically generated code for commit point define: Get_Point2 */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 6; + cp_define->label_name = "Get_Point2"; + cp_define->potential_cp_label_num = 1; + cp_define->potential_label_name = "Read_Val_Point"; + cp_define->interface_num = 0; + cp_define->is_additional_point = false; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + return (V == TOMBSTONE) ? NULL : V; } + return get_impl(topmap, chm->copy_slot_and_check(topmap, kvs, + idx, key_slot), key_slot, fullhash); + } + + if (++reprobe_cnt >= REPROBE_LIMIT || + key_slot == TOMBSTONE) { + + kvs_data *newkvs = chm->_newkvs.load(memory_order_acquire); + + return newkvs == NULL ? NULL : get_impl(topmap, + topmap->help_copy(newkvs), key_slot, fullhash); + } + + idx = (idx + 1) & (len - 1); } + } + + TypeV* putIfMatch(TypeK *key, TypeV *value, slot *old_val) { + if (old_val == NULL) { + return NULL; + } + slot *key_slot = new slot(false, key); + + slot *value_slot = new slot(false, value); + + kvs_data *kvs = _kvs.load(memory_order_acquire); + + slot *res = putIfMatch(this, kvs, key_slot, value_slot, old_val); + MODEL_ASSERT (res != NULL); + MODEL_ASSERT (!is_prime(res)); + return res == TOMBSTONE ? NULL : (TypeV*) res->_ptr; + } + + + static slot* putIfMatch(cliffc_hashtable *topmap, kvs_data *kvs, slot + *key_slot, slot *val_slot, slot *expVal) { + MODEL_ASSERT (val_slot != NULL); + MODEL_ASSERT (!is_prime(val_slot)); + MODEL_ASSERT (!is_prime(expVal)); + + int fullhash = hash(key_slot); + int len = kvs->_size; + CHM *chm = get_chm(kvs); + int *hashes = get_hashes(kvs); + int idx = fullhash & (len - 1); + + int reprobe_cnt = 0; + slot *K; + slot *V; + kvs_data *newkvs; + + while (true) { K = key(kvs, idx); + V = val(kvs, idx); + if (K == NULL) { if (val_slot == TOMBSTONE) return val_slot; + if (CAS_key(kvs, idx, NULL, key_slot)) { + /* Automatically generated code for commit point define: Put_WriteKey */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 7; + cp_define->label_name = "Put_WriteKey"; + cp_define->potential_cp_label_num = 2; + cp_define->potential_label_name = "Write_Key_Point"; + cp_define->interface_num = 1; + cp_define->is_additional_point = false; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + chm->_slots.fetch_add(1, memory_order_relaxed); hashes[idx] = fullhash; break; + } + K = key(kvs, idx); MODEL_ASSERT (K != NULL); + } + + if (keyeq(K, key_slot, hashes, idx, fullhash)) + break; + if (++reprobe_cnt >= reprobe_limit(len) || + K == TOMBSTONE) { newkvs = chm->resize(topmap, kvs); + if (expVal != NULL) topmap->help_copy(newkvs); + return putIfMatch(topmap, newkvs, key_slot, val_slot, expVal); + } + + idx = (idx + 1) & (len - 1); } + if (val_slot == V) return V; + + newkvs = chm->_newkvs.load(memory_order_acquire); + + if (newkvs == NULL && + ((V == NULL && chm->table_full(reprobe_cnt, len)) || is_prime(V))) { + newkvs = chm->resize(topmap, kvs); } + + if (newkvs != NULL) + return putIfMatch(topmap, chm->copy_slot_and_check(topmap, kvs, idx, + expVal), key_slot, val_slot, expVal); + + while (true) { + MODEL_ASSERT (!is_prime(V)); + + if (expVal != NO_MATCH_OLD && + V != expVal && + (expVal != MATCH_ANY || V == TOMBSTONE || V == NULL) && + !(V == NULL && expVal == TOMBSTONE) && + (expVal == NULL || !valeq(expVal, V))) { + + + + return V; } + + if (CAS_val(kvs, idx, V, val_slot)) { + /* Automatically generated code for commit point define: Put_Point */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 8; + cp_define->label_name = "Put_Point"; + cp_define->potential_cp_label_num = 3; + cp_define->potential_label_name = "Write_Val_Point"; + cp_define->interface_num = 1; + cp_define->is_additional_point = false; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + if (expVal != NULL) { if ((V == NULL || V == TOMBSTONE) && + val_slot != TOMBSTONE) + chm->_size.fetch_add(1, memory_order_relaxed); + if (!(V == NULL || V == TOMBSTONE) && + val_slot == TOMBSTONE) + chm->_size.fetch_add(-1, memory_order_relaxed); + } + return (V == NULL && expVal != NULL) ? TOMBSTONE : V; + } + V = val(kvs, idx); + if (is_prime(V)) + return putIfMatch(topmap, chm->copy_slot_and_check(topmap, kvs, + idx, expVal), key_slot, val_slot, expVal); + } + } + + kvs_data* help_copy(kvs_data *helper) { + + kvs_data *topkvs = _kvs.load(memory_order_acquire); + CHM *topchm = get_chm(topkvs); + if (topchm->_newkvs.load(memory_order_relaxed) == NULL) return helper; + topchm->help_copy_impl(this, topkvs, false); + return helper; + } +}; +template +void** cliffc_hashtable::func_ptr_table; +template +anno_hb_init** cliffc_hashtable::hb_init_table; +template +spec_table * cliffc_hashtable::map; +template +spec_table * cliffc_hashtable::id_map; +template +id_tag_t * cliffc_hashtable::tag; + + +#endif + diff --git a/output/cliffc-hashtable/main.cc b/output/cliffc-hashtable/main.cc new file mode 100644 index 0000000..8b6f75e --- /dev/null +++ b/output/cliffc-hashtable/main.cc @@ -0,0 +1,111 @@ +#include +#include +#include "cliffc_hashtable.h" + +using namespace std; + +template +slot* const cliffc_hashtable::MATCH_ANY = new slot(false, NULL); + +template +slot* const cliffc_hashtable::NO_MATCH_OLD = new slot(false, NULL); + +template +slot* const cliffc_hashtable::TOMBPRIME = new slot(true, NULL); + +template +slot* const cliffc_hashtable::TOMBSTONE = new slot(false, NULL); + + +class IntWrapper { + private: + public: + int _val; + + IntWrapper(int val) : _val(val) {} + + IntWrapper() : _val(0) {} + + IntWrapper(IntWrapper& copy) : _val(copy._val) {} + + int get() { + return _val; + } + + int hashCode() { + return _val; + } + + bool operator==(const IntWrapper& rhs) { + return false; + } + + bool equals(const void *another) { + if (another == NULL) + return false; + IntWrapper *ptr = + (IntWrapper*) another; + return ptr->_val == _val; + } +}; + +cliffc_hashtable *table; +IntWrapper *val1, *val2; +IntWrapper *k0, *k1, *k2, *k3, *k4, *k5; +IntWrapper *v0, *v1, *v2, *v3, *v4, *v5; + +void threadA(void *arg) { + IntWrapper *Res; + int res; + Res = table->put(k3, v3); + res = Res == NULL ? 0 : Res->_val; + printf("Put1: key_%d, val_%d, res_%d\n", k3->_val, v3->_val, res); + + Res = table->get(k2); + res = Res == NULL ? 0 : Res->_val; + printf("Get2: key_%d, res_%d\n", k2->_val, res); +} + +void threadB(void *arg) { + IntWrapper *Res; + int res; + Res = table->put(k2, v2); + res = Res == NULL ? 0 : Res->_val; + printf("Put3: key_%d, val_%d, res_%d\n", k2->_val, v2->_val, res); + + Res = table->get(k3); + res = Res == NULL ? 0 : Res->_val; + printf("Get4: key_%d, res_%d\n", k3->_val, res); +} + +void threadC(void *arg) { +} + +int user_main(int argc, char *argv[]) { + thrd_t t1, t2, t3; + table = new cliffc_hashtable(32); + k1 = new IntWrapper(3); + k2 = new IntWrapper(5); + k3 = new IntWrapper(11); + k4 = new IntWrapper(7); + k5 = new IntWrapper(13); + + v0 = new IntWrapper(2048); + v1 = new IntWrapper(1024); + v2 = new IntWrapper(47); + v3 = new IntWrapper(73); + v4 = new IntWrapper(81); + v5 = new IntWrapper(99); + + thrd_create(&t1, threadA, NULL); + thrd_create(&t2, threadB, NULL); + thrd_create(&t3, threadC, NULL); + thrd_join(t1); + thrd_join(t2); + thrd_join(t3); + + return 0; +} + + + diff --git a/output/concurrent-hashmap/hashmap.h b/output/concurrent-hashmap/hashmap.h new file mode 100644 index 0000000..5a05cd3 --- /dev/null +++ b/output/concurrent-hashmap/hashmap.h @@ -0,0 +1,471 @@ +#ifndef _HASHMAP_H +#define _HASHMAP_H + +#include +#include +#include "stdio.h" +#include +#include + +#include +#include +#include +#include +#include "common.h" + + +#include "common.h" + +#define relaxed memory_order_relaxed +#define release memory_order_release +#define acquire memory_order_acquire +#define acq_rel memory_order_acq_rel +#define seq_cst memory_order_seq_cst + +using namespace std; + + + +class Entry { + public: + int key; + atomic_int value; + int hash; + atomic next; + + Entry(int h, int k, int v, Entry *n) { + this->hash = h; + this->key = k; + this->value.store(v, relaxed); + this->next.store(n, relaxed); + } +}; + +class Segment { + public: + int count; + mutex segMutex; + + void lock() { + segMutex.lock(); + } + + void unlock() { + segMutex.unlock(); + } + + Segment() { + this->count = 0; + } +}; + + +class HashMap { + public: + +/* All other user-defined structs */ +static IntegerMap * __map; +/* All other user-defined functions */ +/* Definition of interface info struct: Put */ +typedef struct Put_info { +int __RET__; +int key; +int value; +} Put_info; +/* End of info struct definition: Put */ + +/* ID function of interface: Put */ +inline static call_id_t Put_id(void *info, thread_id_t __TID__) { + Put_info* theInfo = (Put_info*)info; + int __RET__ = theInfo->__RET__; + int key = theInfo->key; + int value = theInfo->value; + + call_id_t __ID__ = value; + return __ID__; +} +/* End of ID function: Put */ + +/* Check action function of interface: Put */ +inline static bool Put_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Put_info* theInfo = (Put_info*)info; + int __RET__ = theInfo->__RET__; + int key = theInfo->key; + int value = theInfo->value; + + putIntegerMap ( __map , key , value ) ; + return true; +} +/* End of check action function: Put */ + +/* Definition of interface info struct: Get */ +typedef struct Get_info { +int __RET__; +int key; +} Get_info; +/* End of info struct definition: Get */ + +/* ID function of interface: Get */ +inline static call_id_t Get_id(void *info, thread_id_t __TID__) { + Get_info* theInfo = (Get_info*)info; + int __RET__ = theInfo->__RET__; + int key = theInfo->key; + + call_id_t __ID__ = __RET__; + return __ID__; +} +/* End of ID function: Get */ + +/* Check action function of interface: Get */ +inline static bool Get_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Get_info* theInfo = (Get_info*)info; + int __RET__ = theInfo->__RET__; + int key = theInfo->key; + + int res = getIntegerMap ( __map , key ) ; + check_passed = __RET__ ? res == __RET__ : true; + if (!check_passed) + return false; + return true; +} +/* End of check action function: Get */ + +#define INTERFACE_SIZE 2 +static void** func_ptr_table; +static hb_rule** hb_rule_table; +static commutativity_rule** commutativity_rule_table; +inline static bool CommutativityCondition0(void *info1, void *info2) { + Put_info *_info1 = (Put_info*) info1; + Put_info *_info2 = (Put_info*) info2; + return _info1-> key != _info2-> key; +} +inline static bool CommutativityCondition1(void *info1, void *info2) { + Put_info *_info1 = (Put_info*) info1; + Get_info *_info2 = (Get_info*) info2; + return _info1-> key != _info2-> key; +} +inline static bool CommutativityCondition2(void *info1, void *info2) { + Get_info *_info1 = (Get_info*) info1; + Get_info *_info2 = (Get_info*) info2; + return true; +} + +/* Initialization of sequential varialbes */ +static void __SPEC_INIT__() { + __map = createIntegerMap ( ) ; +} + +/* Cleanup routine of sequential variables */ +static bool __SPEC_CLEANUP__() { + if ( __map ) destroyIntegerMap ( __map ) ; + return true ; +} + +/* Define function for sequential code initialization */ +inline static void __sequential_init() { + /* Init func_ptr_table */ + func_ptr_table = (void**) malloc(sizeof(void*) * 2 * 2); + func_ptr_table[2 * 1] = (void*) &Put_id; + func_ptr_table[2 * 1 + 1] = (void*) &Put_check_action; + func_ptr_table[2 * 0] = (void*) &Get_id; + func_ptr_table[2 * 0 + 1] = (void*) &Get_check_action; + /* Put(true) -> Get(true) */ + struct hb_rule *hbConditionInit0 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit0->interface_num_before = 1; // Put + hbConditionInit0->hb_condition_num_before = 0; // + hbConditionInit0->interface_num_after = 0; // Get + hbConditionInit0->hb_condition_num_after = 0; // + /* Init hb_rule_table */ + hb_rule_table = (hb_rule**) malloc(sizeof(hb_rule*) * 1); + #define HB_RULE_TABLE_SIZE 1 + hb_rule_table[0] = hbConditionInit0; + /* Init commutativity_rule_table */ + commutativity_rule_table = (commutativity_rule**) malloc(sizeof(commutativity_rule*) * 3); + commutativity_rule* rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 1; + rule->interface_num_after = 1; + rule->rule = "_Method1 . key != _Method2 . key"; + rule->condition = CommutativityCondition0; + commutativity_rule_table[0] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 1; + rule->interface_num_after = 0; + rule->rule = "_Method1 . key != _Method2 . key"; + rule->condition = CommutativityCondition1; + commutativity_rule_table[1] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 0; + rule->rule = "true"; + rule->condition = CommutativityCondition2; + commutativity_rule_table[2] = rule; + /* Pass init info, including function table info & HB rules & Commutativity Rules */ + struct anno_init *anno_init = (struct anno_init*) malloc(sizeof(struct anno_init)); + anno_init->init_func = (void_func_t) __SPEC_INIT__; + anno_init->cleanup_func = (cleanup_func_t) __SPEC_CLEANUP__; + anno_init->func_table = func_ptr_table; + anno_init->func_table_size = INTERFACE_SIZE; + anno_init->hb_rule_table = hb_rule_table; + anno_init->hb_rule_table_size = HB_RULE_TABLE_SIZE; + anno_init->commutativity_rule_table = commutativity_rule_table; + anno_init->commutativity_rule_table_size = 3; + struct spec_annotation *init = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + init->type = INIT; + init->annotation = anno_init; + cdsannotate(SPEC_ANALYSIS, init); + +} + +/* End of Global construct generation in class */ + + + atomic *table; + + int capacity; + int size; + + static const int CONCURRENCY_LEVEL = 4; + + static const int SEGMENT_MASK = CONCURRENCY_LEVEL - 1; + + Segment *segments[CONCURRENCY_LEVEL]; + + static const int DEFAULT_INITIAL_CAPACITY = 16; + + + HashMap() { + __sequential_init(); + + this->size = 0; + this->capacity = DEFAULT_INITIAL_CAPACITY; + this->table = new atomic[capacity]; + for (int i = 0; i < capacity; i++) { + atomic_init(&table[i], NULL); + } + for (int i = 0; i < CONCURRENCY_LEVEL; i++) { + segments[i] = new Segment; + } + } + + int hashKey(int key) { + return key; + } + + + +int get(int key) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 0; // Get + interface_begin->interface_name = "Get"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + int __RET__ = __wrapper__get(key); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 0; // Get + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Get_info* info = (Get_info*) malloc(sizeof(Get_info)); + info->__RET__ = __RET__; + info->key = key; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 0; // Get + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +int __wrapper__get(int key) { + ASSERT (key); + int hash = hashKey(key); + + atomic *tab = table; + int index = hash & (capacity - 1); + atomic *first = &tab[index]; + Entry *e; + int res = 0; + + + + Entry *firstPtr = first->load(acquire); + + e = firstPtr; + while (e != NULL) { + if (key, e->key) { + + res = e->value.load(seq_cst); + /* Automatically generated code for commit point define check: GetReadValue1 */ + + if (res != 0) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 0; + cp_define_check->label_name = "GetReadValue1"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + if (res != 0) + return res; + else + break; + } + e = e->next.load(relaxed); + } + + Segment *seg = segments[hash & SEGMENT_MASK]; + seg->lock(); + Entry *newFirstPtr = first->load(relaxed); + /* Automatically generated code for commit point define check: GetReadEntry */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 1; + cp_define_check->label_name = "GetReadEntry"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + if (e != NULL || firstPtr != newFirstPtr) { + e = newFirstPtr; + while (e != NULL) { + if (key == e->key) { + res = e->value.load(relaxed); + /* Automatically generated code for commit point define check: GetReadValue2 */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 2; + cp_define_check->label_name = "GetReadValue2"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + seg->unlock(); return res; + } + e = e->next.load(relaxed); + } + } + seg->unlock(); return 0; + } + + +int put(int key, int value) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 1; // Put + interface_begin->interface_name = "Put"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + int __RET__ = __wrapper__put(key, value); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 1; // Put + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Put_info* info = (Put_info*) malloc(sizeof(Put_info)); + info->__RET__ = __RET__; + info->key = key; + info->value = value; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 1; // Put + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +int __wrapper__put(int key, int value) { + ASSERT (key && value); + int hash = hashKey(key); + Segment *seg = segments[hash & SEGMENT_MASK]; + atomic *tab; + + seg->lock(); tab = table; + int index = hash & (capacity - 1); + + atomic *first = &tab[index]; + Entry *e; + int oldValue = 0; + + Entry *firstPtr = first->load(relaxed); + e = firstPtr; + while (e != NULL) { + if (key == e->key) { + oldValue = e->value.load(relaxed); + + + e->value.store(value, seq_cst); + /* Automatically generated code for commit point define check: PutUpdateValue */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 3; + cp_define_check->label_name = "PutUpdateValue"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + seg->unlock(); return oldValue; + } + e = e->next.load(relaxed); + } + + Entry *newEntry = new Entry(hash, key, value, firstPtr); + + + first->store(newEntry, release); + /* Automatically generated code for commit point define check: PutInsertValue */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 4; + cp_define_check->label_name = "PutInsertValue"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + seg->unlock(); return 0; + } +}; +void** HashMap::func_ptr_table; +hb_rule** HashMap::hb_rule_table; +commutativity_rule** HashMap::commutativity_rule_table; +IntegerMap * HashMap::__map; + + +#endif + diff --git a/output/concurrent-hashmap/hashmap.o b/output/concurrent-hashmap/hashmap.o new file mode 100644 index 0000000..268350d Binary files /dev/null and b/output/concurrent-hashmap/hashmap.o differ diff --git a/output/concurrent-hashmap/main b/output/concurrent-hashmap/main new file mode 100755 index 0000000..a9b7a82 Binary files /dev/null and b/output/concurrent-hashmap/main differ diff --git a/output/concurrent-hashmap/main.cc b/output/concurrent-hashmap/main.cc new file mode 100644 index 0000000..f39f3b6 --- /dev/null +++ b/output/concurrent-hashmap/main.cc @@ -0,0 +1,35 @@ +#include +#include +#include "hashmap.h" + +HashMap *table; + +void threadA(void *arg) { + table->put(1, 1); + printf("Thrd A: Put %d -> %d\n", 1, 1); + int r1 = table->get(2); + printf("Thrd A: Get %d\n", r1); +} + +void threadB(void *arg) { + table->put(2, 2); + printf("Thrd B: Put %d -> %d\n", 2, 2); + int r2 = table->get(1); + printf("Thrd B: Get %d\n", r2); +} + +int user_main(int argc, char *argv[]) { + thrd_t t1, t2; + + table = new HashMap; + + thrd_create(&t1, threadA, NULL); + thrd_create(&t2, threadB, NULL); + thrd_join(t1); + thrd_join(t2); + + return 0; +} + + + diff --git a/output/concurrent-hashmap/testcase1 b/output/concurrent-hashmap/testcase1 new file mode 100755 index 0000000..54701c1 Binary files /dev/null and b/output/concurrent-hashmap/testcase1 differ diff --git a/output/concurrent-hashmap/testcase1.cc b/output/concurrent-hashmap/testcase1.cc new file mode 100644 index 0000000..059718e --- /dev/null +++ b/output/concurrent-hashmap/testcase1.cc @@ -0,0 +1,37 @@ +#include +#include +#include "hashmap.h" + +HashMap *table; + +void threadA(void *arg) { + table->put(1, 11); + printf("Thrd A: Put %d -> %d\n", 1, 11); + int r1 = table->get(2); + printf("Thrd A: Get %d\n", r1); +} + +void threadB(void *arg) { + table->put(2, 22); + printf("Thrd B: Put %d -> %d\n", 2, 22); + int r2 = table->get(1); + printf("Thrd B: Get %d\n", r2); +} + +int user_main(int argc, char *argv[]) { + thrd_t t1, t2; + + table = new HashMap; + table->put(1, 1); + table->put(2, 2); + + thrd_create(&t1, threadA, NULL); + thrd_create(&t2, threadB, NULL); + thrd_join(t1); + thrd_join(t2); + + return 0; +} + + + diff --git a/output/linuxrwlocks/linuxrwlocks b/output/linuxrwlocks/linuxrwlocks new file mode 100755 index 0000000..ecd7511 Binary files /dev/null and b/output/linuxrwlocks/linuxrwlocks differ diff --git a/output/linuxrwlocks/linuxrwlocks.c b/output/linuxrwlocks/linuxrwlocks.c new file mode 100644 index 0000000..5929374 --- /dev/null +++ b/output/linuxrwlocks/linuxrwlocks.c @@ -0,0 +1,940 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include "common.h" + +#include "librace.h" + +#define RW_LOCK_BIAS 0x00100000 +#define WRITE_LOCK_CMP RW_LOCK_BIAS + +typedef union { + atomic_int lock; +} rwlock_t; + + + + + + + +/* All other user-defined structs */ +static bool writer_lock_acquired; +static int reader_lock_cnt; +/* All other user-defined functions */ +/* Definition of interface info struct: Write_Trylock */ +typedef struct Write_Trylock_info { +int __RET__; +rwlock_t * rw; +} Write_Trylock_info; +/* End of info struct definition: Write_Trylock */ + +/* ID function of interface: Write_Trylock */ +inline static call_id_t Write_Trylock_id(void *info, thread_id_t __TID__) { + Write_Trylock_info* theInfo = (Write_Trylock_info*)info; + int __RET__ = theInfo->__RET__; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Write_Trylock */ + +/* Check action function of interface: Write_Trylock */ +inline static bool Write_Trylock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Write_Trylock_info* theInfo = (Write_Trylock_info*)info; + int __RET__ = theInfo->__RET__; + rwlock_t * rw = theInfo->rw; + + if ( __RET__ == 1 ) writer_lock_acquired = true ; + return true; +} +/* End of check action function: Write_Trylock */ + +/* Definition of interface info struct: Read_Trylock */ +typedef struct Read_Trylock_info { +int __RET__; +rwlock_t * rw; +} Read_Trylock_info; +/* End of info struct definition: Read_Trylock */ + +/* ID function of interface: Read_Trylock */ +inline static call_id_t Read_Trylock_id(void *info, thread_id_t __TID__) { + Read_Trylock_info* theInfo = (Read_Trylock_info*)info; + int __RET__ = theInfo->__RET__; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Read_Trylock */ + +/* Check action function of interface: Read_Trylock */ +inline static bool Read_Trylock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Read_Trylock_info* theInfo = (Read_Trylock_info*)info; + int __RET__ = theInfo->__RET__; + rwlock_t * rw = theInfo->rw; + + if ( __RET__ ) reader_lock_cnt ++ ; + check_passed = __RET__ == ! writer_lock_acquired || ! __RET__; + if (!check_passed) + return false; + return true; +} +/* End of check action function: Read_Trylock */ + +/* Definition of interface info struct: Write_Lock */ +typedef struct Write_Lock_info { +rwlock_t * rw; +} Write_Lock_info; +/* End of info struct definition: Write_Lock */ + +/* ID function of interface: Write_Lock */ +inline static call_id_t Write_Lock_id(void *info, thread_id_t __TID__) { + Write_Lock_info* theInfo = (Write_Lock_info*)info; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Write_Lock */ + +/* Check action function of interface: Write_Lock */ +inline static bool Write_Lock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Write_Lock_info* theInfo = (Write_Lock_info*)info; + rwlock_t * rw = theInfo->rw; + + check_passed = ! writer_lock_acquired && reader_lock_cnt == 0; + if (!check_passed) + return false; + writer_lock_acquired = true ; + return true; +} +/* End of check action function: Write_Lock */ + +/* Definition of interface info struct: Write_Unlock */ +typedef struct Write_Unlock_info { +rwlock_t * rw; +} Write_Unlock_info; +/* End of info struct definition: Write_Unlock */ + +/* ID function of interface: Write_Unlock */ +inline static call_id_t Write_Unlock_id(void *info, thread_id_t __TID__) { + Write_Unlock_info* theInfo = (Write_Unlock_info*)info; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Write_Unlock */ + +/* Check action function of interface: Write_Unlock */ +inline static bool Write_Unlock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Write_Unlock_info* theInfo = (Write_Unlock_info*)info; + rwlock_t * rw = theInfo->rw; + + check_passed = reader_lock_cnt == 0 && writer_lock_acquired; + if (!check_passed) + return false; + writer_lock_acquired = false ; + return true; +} +/* End of check action function: Write_Unlock */ + +/* Definition of interface info struct: Read_Unlock */ +typedef struct Read_Unlock_info { +rwlock_t * rw; +} Read_Unlock_info; +/* End of info struct definition: Read_Unlock */ + +/* ID function of interface: Read_Unlock */ +inline static call_id_t Read_Unlock_id(void *info, thread_id_t __TID__) { + Read_Unlock_info* theInfo = (Read_Unlock_info*)info; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Read_Unlock */ + +/* Check action function of interface: Read_Unlock */ +inline static bool Read_Unlock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Read_Unlock_info* theInfo = (Read_Unlock_info*)info; + rwlock_t * rw = theInfo->rw; + + check_passed = reader_lock_cnt > 0 && ! writer_lock_acquired; + if (!check_passed) + return false; + reader_lock_cnt -- ; + return true; +} +/* End of check action function: Read_Unlock */ + +/* Definition of interface info struct: Read_Lock */ +typedef struct Read_Lock_info { +rwlock_t * rw; +} Read_Lock_info; +/* End of info struct definition: Read_Lock */ + +/* ID function of interface: Read_Lock */ +inline static call_id_t Read_Lock_id(void *info, thread_id_t __TID__) { + Read_Lock_info* theInfo = (Read_Lock_info*)info; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Read_Lock */ + +/* Check action function of interface: Read_Lock */ +inline static bool Read_Lock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Read_Lock_info* theInfo = (Read_Lock_info*)info; + rwlock_t * rw = theInfo->rw; + + check_passed = ! writer_lock_acquired; + if (!check_passed) + return false; + reader_lock_cnt ++ ; + return true; +} +/* End of check action function: Read_Lock */ + +#define INTERFACE_SIZE 6 +static void** func_ptr_table; +static hb_rule** hb_rule_table; +static commutativity_rule** commutativity_rule_table; +inline static bool CommutativityCondition0(void *info1, void *info2) { + Read_Lock_info *_info1 = (Read_Lock_info*) info1; + Read_Lock_info *_info2 = (Read_Lock_info*) info2; + return true; +} +inline static bool CommutativityCondition1(void *info1, void *info2) { + Read_Lock_info *_info1 = (Read_Lock_info*) info1; + Read_Unlock_info *_info2 = (Read_Unlock_info*) info2; + return true; +} +inline static bool CommutativityCondition2(void *info1, void *info2) { + Read_Lock_info *_info1 = (Read_Lock_info*) info1; + Read_Trylock_info *_info2 = (Read_Trylock_info*) info2; + return true; +} +inline static bool CommutativityCondition3(void *info1, void *info2) { + Read_Lock_info *_info1 = (Read_Lock_info*) info1; + Write_Trylock_info *_info2 = (Write_Trylock_info*) info2; + return ! _info2-> __RET__; +} +inline static bool CommutativityCondition4(void *info1, void *info2) { + Read_Unlock_info *_info1 = (Read_Unlock_info*) info1; + Read_Unlock_info *_info2 = (Read_Unlock_info*) info2; + return true; +} +inline static bool CommutativityCondition5(void *info1, void *info2) { + Read_Unlock_info *_info1 = (Read_Unlock_info*) info1; + Read_Trylock_info *_info2 = (Read_Trylock_info*) info2; + return true; +} +inline static bool CommutativityCondition6(void *info1, void *info2) { + Read_Unlock_info *_info1 = (Read_Unlock_info*) info1; + Write_Trylock_info *_info2 = (Write_Trylock_info*) info2; + return ! _info2-> __RET__; +} +inline static bool CommutativityCondition7(void *info1, void *info2) { + Read_Trylock_info *_info1 = (Read_Trylock_info*) info1; + Read_Trylock_info *_info2 = (Read_Trylock_info*) info2; + return true; +} +inline static bool CommutativityCondition8(void *info1, void *info2) { + Read_Trylock_info *_info1 = (Read_Trylock_info*) info1; + Write_Trylock_info *_info2 = (Write_Trylock_info*) info2; + return ! _info1-> __RET__ || ! _info2-> __RET__; +} +inline static bool CommutativityCondition9(void *info1, void *info2) { + Read_Trylock_info *_info1 = (Read_Trylock_info*) info1; + Write_Lock_info *_info2 = (Write_Lock_info*) info2; + return ! _info1-> __RET__; +} +inline static bool CommutativityCondition10(void *info1, void *info2) { + Read_Trylock_info *_info1 = (Read_Trylock_info*) info1; + Write_Unlock_info *_info2 = (Write_Unlock_info*) info2; + return ! _info1-> __RET__; +} +inline static bool CommutativityCondition11(void *info1, void *info2) { + Write_Trylock_info *_info1 = (Write_Trylock_info*) info1; + Write_Trylock_info *_info2 = (Write_Trylock_info*) info2; + return ! _info1-> __RET__ || ! _info2-> __RET__; +} +inline static bool CommutativityCondition12(void *info1, void *info2) { + Write_Trylock_info *_info1 = (Write_Trylock_info*) info1; + Write_Unlock_info *_info2 = (Write_Unlock_info*) info2; + return ! _info1-> __RET__; +} +inline static bool CommutativityCondition13(void *info1, void *info2) { + Write_Trylock_info *_info1 = (Write_Trylock_info*) info1; + Write_Lock_info *_info2 = (Write_Lock_info*) info2; + return ! _info1-> __RET__; +} + +/* Initialization of sequential varialbes */ +static void __SPEC_INIT__() { + writer_lock_acquired = false ; + reader_lock_cnt = 0 ; +} + +/* Cleanup routine of sequential variables */ +static bool __SPEC_CLEANUP__() { + return true; +} + +/* Define function for sequential code initialization */ +inline static void __sequential_init() { + /* Init func_ptr_table */ + func_ptr_table = (void**) malloc(sizeof(void*) * 6 * 2); + func_ptr_table[2 * 3] = (void*) &Write_Trylock_id; + func_ptr_table[2 * 3 + 1] = (void*) &Write_Trylock_check_action; + func_ptr_table[2 * 2] = (void*) &Read_Trylock_id; + func_ptr_table[2 * 2 + 1] = (void*) &Read_Trylock_check_action; + func_ptr_table[2 * 1] = (void*) &Write_Lock_id; + func_ptr_table[2 * 1 + 1] = (void*) &Write_Lock_check_action; + func_ptr_table[2 * 5] = (void*) &Write_Unlock_id; + func_ptr_table[2 * 5 + 1] = (void*) &Write_Unlock_check_action; + func_ptr_table[2 * 4] = (void*) &Read_Unlock_id; + func_ptr_table[2 * 4 + 1] = (void*) &Read_Unlock_check_action; + func_ptr_table[2 * 0] = (void*) &Read_Lock_id; + func_ptr_table[2 * 0 + 1] = (void*) &Read_Lock_check_action; + /* Read_Unlock(true) -> Write_Lock(true) */ + struct hb_rule *hbConditionInit0 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit0->interface_num_before = 4; // Read_Unlock + hbConditionInit0->hb_condition_num_before = 0; // + hbConditionInit0->interface_num_after = 1; // Write_Lock + hbConditionInit0->hb_condition_num_after = 0; // + /* Read_Unlock(true) -> Write_Trylock(HB_Write_Trylock_Succ) */ + struct hb_rule *hbConditionInit1 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit1->interface_num_before = 4; // Read_Unlock + hbConditionInit1->hb_condition_num_before = 0; // + hbConditionInit1->interface_num_after = 3; // Write_Trylock + hbConditionInit1->hb_condition_num_after = 1; // HB_Write_Trylock_Succ + /* Write_Unlock(true) -> Write_Lock(true) */ + struct hb_rule *hbConditionInit2 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit2->interface_num_before = 5; // Write_Unlock + hbConditionInit2->hb_condition_num_before = 0; // + hbConditionInit2->interface_num_after = 1; // Write_Lock + hbConditionInit2->hb_condition_num_after = 0; // + /* Write_Unlock(true) -> Write_Trylock(HB_Write_Trylock_Succ) */ + struct hb_rule *hbConditionInit3 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit3->interface_num_before = 5; // Write_Unlock + hbConditionInit3->hb_condition_num_before = 0; // + hbConditionInit3->interface_num_after = 3; // Write_Trylock + hbConditionInit3->hb_condition_num_after = 1; // HB_Write_Trylock_Succ + /* Write_Unlock(true) -> Read_Lock(true) */ + struct hb_rule *hbConditionInit4 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit4->interface_num_before = 5; // Write_Unlock + hbConditionInit4->hb_condition_num_before = 0; // + hbConditionInit4->interface_num_after = 0; // Read_Lock + hbConditionInit4->hb_condition_num_after = 0; // + /* Write_Unlock(true) -> Read_Trylock(HB_Read_Trylock_Succ) */ + struct hb_rule *hbConditionInit5 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit5->interface_num_before = 5; // Write_Unlock + hbConditionInit5->hb_condition_num_before = 0; // + hbConditionInit5->interface_num_after = 2; // Read_Trylock + hbConditionInit5->hb_condition_num_after = 2; // HB_Read_Trylock_Succ + /* Init hb_rule_table */ + hb_rule_table = (hb_rule**) malloc(sizeof(hb_rule*) * 6); + #define HB_RULE_TABLE_SIZE 6 + hb_rule_table[0] = hbConditionInit0; + hb_rule_table[1] = hbConditionInit1; + hb_rule_table[2] = hbConditionInit2; + hb_rule_table[3] = hbConditionInit3; + hb_rule_table[4] = hbConditionInit4; + hb_rule_table[5] = hbConditionInit5; + /* Init commutativity_rule_table */ + commutativity_rule_table = (commutativity_rule**) malloc(sizeof(commutativity_rule*) * 14); + commutativity_rule* rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 0; + rule->rule = "true"; + rule->condition = CommutativityCondition0; + commutativity_rule_table[0] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 4; + rule->rule = "true"; + rule->condition = CommutativityCondition1; + commutativity_rule_table[1] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 2; + rule->rule = "true"; + rule->condition = CommutativityCondition2; + commutativity_rule_table[2] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 3; + rule->rule = "! _Method2 . __RET__"; + rule->condition = CommutativityCondition3; + commutativity_rule_table[3] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 4; + rule->interface_num_after = 4; + rule->rule = "true"; + rule->condition = CommutativityCondition4; + commutativity_rule_table[4] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 4; + rule->interface_num_after = 2; + rule->rule = "true"; + rule->condition = CommutativityCondition5; + commutativity_rule_table[5] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 4; + rule->interface_num_after = 3; + rule->rule = "! _Method2 . __RET__"; + rule->condition = CommutativityCondition6; + commutativity_rule_table[6] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 2; + rule->rule = "true"; + rule->condition = CommutativityCondition7; + commutativity_rule_table[7] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 3; + rule->rule = "! _Method1 . __RET__ || ! _Method2 . __RET__"; + rule->condition = CommutativityCondition8; + commutativity_rule_table[8] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 1; + rule->rule = "! _Method1 . __RET__"; + rule->condition = CommutativityCondition9; + commutativity_rule_table[9] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 5; + rule->rule = "! _Method1 . __RET__"; + rule->condition = CommutativityCondition10; + commutativity_rule_table[10] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 3; + rule->interface_num_after = 3; + rule->rule = "! _Method1 . __RET__ || ! _Method2 . __RET__"; + rule->condition = CommutativityCondition11; + commutativity_rule_table[11] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 3; + rule->interface_num_after = 5; + rule->rule = "! _Method1 . __RET__"; + rule->condition = CommutativityCondition12; + commutativity_rule_table[12] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 3; + rule->interface_num_after = 1; + rule->rule = "! _Method1 . __RET__"; + rule->condition = CommutativityCondition13; + commutativity_rule_table[13] = rule; + /* Pass init info, including function table info & HB rules & Commutativity Rules */ + struct anno_init *anno_init = (struct anno_init*) malloc(sizeof(struct anno_init)); + anno_init->init_func = (void_func_t) __SPEC_INIT__; + anno_init->cleanup_func = (cleanup_func_t) __SPEC_CLEANUP__; + anno_init->func_table = func_ptr_table; + anno_init->func_table_size = INTERFACE_SIZE; + anno_init->hb_rule_table = hb_rule_table; + anno_init->hb_rule_table_size = HB_RULE_TABLE_SIZE; + anno_init->commutativity_rule_table = commutativity_rule_table; + anno_init->commutativity_rule_table_size = 14; + struct spec_annotation *init = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + init->type = INIT; + init->annotation = anno_init; + cdsannotate(SPEC_ANALYSIS, init); + +} + +/* End of Global construct generation in class */ + + +static inline int read_can_lock(rwlock_t *lock) +{ + return atomic_load_explicit(&lock->lock, memory_order_relaxed) > 0; +} + +static inline int write_can_lock(rwlock_t *lock) +{ + return atomic_load_explicit(&lock->lock, memory_order_relaxed) == RW_LOCK_BIAS; +} + + +void __wrapper__read_lock(rwlock_t * rw); + +void read_lock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 0; // Read_Lock + interface_begin->interface_name = "Read_Lock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__read_lock(rw); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 0; // Read_Lock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Read_Lock_info* info = (Read_Lock_info*) malloc(sizeof(Read_Lock_info)); + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 0; // Read_Lock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__read_lock(rwlock_t * rw) +{ + + + int priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire); + /* Automatically generated code for commit point define check: Read_Lock_Success_1 */ + + if (priorvalue > 0) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 0; + cp_define_check->label_name = "Read_Lock_Success_1"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + while (priorvalue <= 0) { + atomic_fetch_add_explicit(&rw->lock, 1, memory_order_relaxed); + while (atomic_load_explicit(&rw->lock, memory_order_relaxed) <= 0) { + thrd_yield(); + } + + priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire); + /* Automatically generated code for commit point define check: Read_Lock_Success_2 */ + + if (priorvalue > 0) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 1; + cp_define_check->label_name = "Read_Lock_Success_2"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + } +} + + +void __wrapper__write_lock(rwlock_t * rw); + +void write_lock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 1; // Write_Lock + interface_begin->interface_name = "Write_Lock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__write_lock(rw); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 1; // Write_Lock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Write_Lock_info* info = (Write_Lock_info*) malloc(sizeof(Write_Lock_info)); + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 1; // Write_Lock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__write_lock(rwlock_t * rw) +{ + + int priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire); + /* Automatically generated code for commit point define check: Write_Lock_Success_1 */ + + if (priorvalue == RW_LOCK_BIAS) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 2; + cp_define_check->label_name = "Write_Lock_Success_1"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + while (priorvalue != RW_LOCK_BIAS) { + atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_relaxed); + while (atomic_load_explicit(&rw->lock, memory_order_relaxed) != RW_LOCK_BIAS) { + thrd_yield(); + } + + priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire); + /* Automatically generated code for commit point define check: Write_Lock_Success_2 */ + + if (priorvalue == RW_LOCK_BIAS) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 3; + cp_define_check->label_name = "Write_Lock_Success_2"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + } +} + +int __wrapper__read_trylock(rwlock_t * rw); + +int read_trylock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 2; // Read_Trylock + interface_begin->interface_name = "Read_Trylock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + int __RET__ = __wrapper__read_trylock(rw); + if (__RET__ == 1) { + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 2; // Read_Trylock + hb_condition->hb_condition_num = 2; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + } + + Read_Trylock_info* info = (Read_Trylock_info*) malloc(sizeof(Read_Trylock_info)); + info->__RET__ = __RET__; + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 2; // Read_Trylock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +int __wrapper__read_trylock(rwlock_t * rw) +{ + + int priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire); + /* Automatically generated code for potential commit point: Potential_Read_Trylock_Point */ + + if (true) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 4; + potential_cp_define->label_name = "Potential_Read_Trylock_Point"; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + if (priorvalue > 0) { + /* Automatically generated code for commit point define: Read_Trylock_Succ_Point */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 5; + cp_define->label_name = "Read_Trylock_Succ_Point"; + cp_define->potential_cp_label_num = 4; + cp_define->potential_label_name = "Potential_Read_Trylock_Point"; + cp_define->interface_num = 2; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + return 1; + } + /* Automatically generated code for commit point define: Read_Trylock_Fail_Point */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 6; + cp_define->label_name = "Read_Trylock_Fail_Point"; + cp_define->potential_cp_label_num = 4; + cp_define->potential_label_name = "Potential_Read_Trylock_Point"; + cp_define->interface_num = 2; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + atomic_fetch_add_explicit(&rw->lock, 1, memory_order_relaxed); + return 0; +} + +int __wrapper__write_trylock(rwlock_t * rw); + +int write_trylock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 3; // Write_Trylock + interface_begin->interface_name = "Write_Trylock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + int __RET__ = __wrapper__write_trylock(rw); + if (__RET__ == 1) { + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 3; // Write_Trylock + hb_condition->hb_condition_num = 1; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + } + + Write_Trylock_info* info = (Write_Trylock_info*) malloc(sizeof(Write_Trylock_info)); + info->__RET__ = __RET__; + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 3; // Write_Trylock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +int __wrapper__write_trylock(rwlock_t * rw) +{ + + int priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire); + /* Automatically generated code for potential commit point: Potential_Write_Trylock_Point */ + + if (true) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 7; + potential_cp_define->label_name = "Potential_Write_Trylock_Point"; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + if (priorvalue == RW_LOCK_BIAS) { + /* Automatically generated code for commit point define: Write_Trylock_Succ_Point */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 8; + cp_define->label_name = "Write_Trylock_Succ_Point"; + cp_define->potential_cp_label_num = 7; + cp_define->potential_label_name = "Potential_Write_Trylock_Point"; + cp_define->interface_num = 3; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + return 1; + } + /* Automatically generated code for commit point define: Write_Trylock_Fail_Point */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 9; + cp_define->label_name = "Write_Trylock_Fail_Point"; + cp_define->potential_cp_label_num = 7; + cp_define->potential_label_name = "Potential_Write_Trylock_Point"; + cp_define->interface_num = 3; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_relaxed); + return 0; +} + +void __wrapper__read_unlock(rwlock_t * rw); + +void read_unlock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 4; // Read_Unlock + interface_begin->interface_name = "Read_Unlock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__read_unlock(rw); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 4; // Read_Unlock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Read_Unlock_info* info = (Read_Unlock_info*) malloc(sizeof(Read_Unlock_info)); + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 4; // Read_Unlock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__read_unlock(rwlock_t * rw) +{ + + atomic_fetch_add_explicit(&rw->lock, 1, memory_order_release); + /* Automatically generated code for commit point define check: Read_Unlock_Point */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 10; + cp_define_check->label_name = "Read_Unlock_Point"; + cp_define_check->interface_num = 4; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + +} + +void __wrapper__write_unlock(rwlock_t * rw); + +void write_unlock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 5; // Write_Unlock + interface_begin->interface_name = "Write_Unlock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__write_unlock(rw); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 5; // Write_Unlock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Write_Unlock_info* info = (Write_Unlock_info*) malloc(sizeof(Write_Unlock_info)); + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 5; // Write_Unlock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__write_unlock(rwlock_t * rw) +{ + + atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_release); + /* Automatically generated code for commit point define check: Write_Unlock_Point */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 11; + cp_define_check->label_name = "Write_Unlock_Point"; + cp_define_check->interface_num = 5; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + + +} + +rwlock_t mylock; +int shareddata; + +static void a(void *obj) +{ + read_lock(&mylock); + read_unlock(&mylock); + + write_lock(&mylock); + shareddata = 47; + write_unlock(&mylock); +} + +static void b(void *obj) +{ + if (read_trylock(&mylock) == 1) { + read_unlock(&mylock); + } + + if (write_trylock(&mylock) == 1) { + write_unlock(&mylock); + } +} + +int user_main(int argc, char **argv) +{ + __sequential_init(); + + thrd_t t1, t2; + atomic_init(&mylock.lock, RW_LOCK_BIAS); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&b, NULL); + + thrd_join(t1); + thrd_join(t2); + + return 0; +} + diff --git a/output/linuxrwlocks/testcase1 b/output/linuxrwlocks/testcase1 new file mode 100755 index 0000000..b92d0b9 Binary files /dev/null and b/output/linuxrwlocks/testcase1 differ diff --git a/output/linuxrwlocks/testcase1.c b/output/linuxrwlocks/testcase1.c new file mode 100644 index 0000000..f47527c --- /dev/null +++ b/output/linuxrwlocks/testcase1.c @@ -0,0 +1,926 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include "common.h" + +#include "librace.h" + +#define RW_LOCK_BIAS 0x00100000 +#define WRITE_LOCK_CMP RW_LOCK_BIAS + +typedef union { + atomic_int lock; +} rwlock_t; + + + + + + + +/* All other user-defined structs */ +static bool writer_lock_acquired; +static int reader_lock_cnt; +/* All other user-defined functions */ +/* Definition of interface info struct: Write_Trylock */ +typedef struct Write_Trylock_info { +int __RET__; +rwlock_t * rw; +} Write_Trylock_info; +/* End of info struct definition: Write_Trylock */ + +/* ID function of interface: Write_Trylock */ +inline static call_id_t Write_Trylock_id(void *info, thread_id_t __TID__) { + Write_Trylock_info* theInfo = (Write_Trylock_info*)info; + int __RET__ = theInfo->__RET__; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Write_Trylock */ + +/* Check action function of interface: Write_Trylock */ +inline static bool Write_Trylock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Write_Trylock_info* theInfo = (Write_Trylock_info*)info; + int __RET__ = theInfo->__RET__; + rwlock_t * rw = theInfo->rw; + + if ( __RET__ == 1 ) writer_lock_acquired = true ; + return true; +} +/* End of check action function: Write_Trylock */ + +/* Definition of interface info struct: Read_Trylock */ +typedef struct Read_Trylock_info { +int __RET__; +rwlock_t * rw; +} Read_Trylock_info; +/* End of info struct definition: Read_Trylock */ + +/* ID function of interface: Read_Trylock */ +inline static call_id_t Read_Trylock_id(void *info, thread_id_t __TID__) { + Read_Trylock_info* theInfo = (Read_Trylock_info*)info; + int __RET__ = theInfo->__RET__; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Read_Trylock */ + +/* Check action function of interface: Read_Trylock */ +inline static bool Read_Trylock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Read_Trylock_info* theInfo = (Read_Trylock_info*)info; + int __RET__ = theInfo->__RET__; + rwlock_t * rw = theInfo->rw; + + if ( __RET__ ) reader_lock_cnt ++ ; + check_passed = __RET__ == ! writer_lock_acquired || ! __RET__; + if (!check_passed) + return false; + return true; +} +/* End of check action function: Read_Trylock */ + +/* Definition of interface info struct: Write_Lock */ +typedef struct Write_Lock_info { +rwlock_t * rw; +} Write_Lock_info; +/* End of info struct definition: Write_Lock */ + +/* ID function of interface: Write_Lock */ +inline static call_id_t Write_Lock_id(void *info, thread_id_t __TID__) { + Write_Lock_info* theInfo = (Write_Lock_info*)info; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Write_Lock */ + +/* Check action function of interface: Write_Lock */ +inline static bool Write_Lock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Write_Lock_info* theInfo = (Write_Lock_info*)info; + rwlock_t * rw = theInfo->rw; + + check_passed = ! writer_lock_acquired && reader_lock_cnt == 0; + if (!check_passed) + return false; + writer_lock_acquired = true ; + return true; +} +/* End of check action function: Write_Lock */ + +/* Definition of interface info struct: Write_Unlock */ +typedef struct Write_Unlock_info { +rwlock_t * rw; +} Write_Unlock_info; +/* End of info struct definition: Write_Unlock */ + +/* ID function of interface: Write_Unlock */ +inline static call_id_t Write_Unlock_id(void *info, thread_id_t __TID__) { + Write_Unlock_info* theInfo = (Write_Unlock_info*)info; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Write_Unlock */ + +/* Check action function of interface: Write_Unlock */ +inline static bool Write_Unlock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Write_Unlock_info* theInfo = (Write_Unlock_info*)info; + rwlock_t * rw = theInfo->rw; + + check_passed = reader_lock_cnt == 0 && writer_lock_acquired; + if (!check_passed) + return false; + writer_lock_acquired = false ; + return true; +} +/* End of check action function: Write_Unlock */ + +/* Definition of interface info struct: Read_Unlock */ +typedef struct Read_Unlock_info { +rwlock_t * rw; +} Read_Unlock_info; +/* End of info struct definition: Read_Unlock */ + +/* ID function of interface: Read_Unlock */ +inline static call_id_t Read_Unlock_id(void *info, thread_id_t __TID__) { + Read_Unlock_info* theInfo = (Read_Unlock_info*)info; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Read_Unlock */ + +/* Check action function of interface: Read_Unlock */ +inline static bool Read_Unlock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Read_Unlock_info* theInfo = (Read_Unlock_info*)info; + rwlock_t * rw = theInfo->rw; + + check_passed = reader_lock_cnt > 0 && ! writer_lock_acquired; + if (!check_passed) + return false; + reader_lock_cnt -- ; + return true; +} +/* End of check action function: Read_Unlock */ + +/* Definition of interface info struct: Read_Lock */ +typedef struct Read_Lock_info { +rwlock_t * rw; +} Read_Lock_info; +/* End of info struct definition: Read_Lock */ + +/* ID function of interface: Read_Lock */ +inline static call_id_t Read_Lock_id(void *info, thread_id_t __TID__) { + Read_Lock_info* theInfo = (Read_Lock_info*)info; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Read_Lock */ + +/* Check action function of interface: Read_Lock */ +inline static bool Read_Lock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Read_Lock_info* theInfo = (Read_Lock_info*)info; + rwlock_t * rw = theInfo->rw; + + check_passed = ! writer_lock_acquired; + if (!check_passed) + return false; + reader_lock_cnt ++ ; + return true; +} +/* End of check action function: Read_Lock */ + +#define INTERFACE_SIZE 6 +static void** func_ptr_table; +static hb_rule** hb_rule_table; +static commutativity_rule** commutativity_rule_table; +inline static bool CommutativityCondition0(void *info1, void *info2) { + Read_Lock_info *_info1 = (Read_Lock_info*) info1; + Read_Lock_info *_info2 = (Read_Lock_info*) info2; + return true; +} +inline static bool CommutativityCondition1(void *info1, void *info2) { + Read_Lock_info *_info1 = (Read_Lock_info*) info1; + Read_Unlock_info *_info2 = (Read_Unlock_info*) info2; + return true; +} +inline static bool CommutativityCondition2(void *info1, void *info2) { + Read_Lock_info *_info1 = (Read_Lock_info*) info1; + Read_Trylock_info *_info2 = (Read_Trylock_info*) info2; + return true; +} +inline static bool CommutativityCondition3(void *info1, void *info2) { + Read_Lock_info *_info1 = (Read_Lock_info*) info1; + Write_Trylock_info *_info2 = (Write_Trylock_info*) info2; + return ! _info2-> __RET__; +} +inline static bool CommutativityCondition4(void *info1, void *info2) { + Read_Unlock_info *_info1 = (Read_Unlock_info*) info1; + Read_Unlock_info *_info2 = (Read_Unlock_info*) info2; + return true; +} +inline static bool CommutativityCondition5(void *info1, void *info2) { + Read_Unlock_info *_info1 = (Read_Unlock_info*) info1; + Read_Trylock_info *_info2 = (Read_Trylock_info*) info2; + return true; +} +inline static bool CommutativityCondition6(void *info1, void *info2) { + Read_Unlock_info *_info1 = (Read_Unlock_info*) info1; + Write_Trylock_info *_info2 = (Write_Trylock_info*) info2; + return ! _info2-> __RET__; +} +inline static bool CommutativityCondition7(void *info1, void *info2) { + Read_Trylock_info *_info1 = (Read_Trylock_info*) info1; + Read_Trylock_info *_info2 = (Read_Trylock_info*) info2; + return true; +} +inline static bool CommutativityCondition8(void *info1, void *info2) { + Read_Trylock_info *_info1 = (Read_Trylock_info*) info1; + Write_Trylock_info *_info2 = (Write_Trylock_info*) info2; + return ! _info1-> __RET__ || ! _info2-> __RET__; +} +inline static bool CommutativityCondition9(void *info1, void *info2) { + Read_Trylock_info *_info1 = (Read_Trylock_info*) info1; + Write_Lock_info *_info2 = (Write_Lock_info*) info2; + return ! _info1-> __RET__; +} +inline static bool CommutativityCondition10(void *info1, void *info2) { + Read_Trylock_info *_info1 = (Read_Trylock_info*) info1; + Write_Unlock_info *_info2 = (Write_Unlock_info*) info2; + return ! _info1-> __RET__; +} +inline static bool CommutativityCondition11(void *info1, void *info2) { + Write_Trylock_info *_info1 = (Write_Trylock_info*) info1; + Write_Trylock_info *_info2 = (Write_Trylock_info*) info2; + return ! _info1-> __RET__ || ! _info2-> __RET__; +} +inline static bool CommutativityCondition12(void *info1, void *info2) { + Write_Trylock_info *_info1 = (Write_Trylock_info*) info1; + Write_Unlock_info *_info2 = (Write_Unlock_info*) info2; + return ! _info1-> __RET__; +} +inline static bool CommutativityCondition13(void *info1, void *info2) { + Write_Trylock_info *_info1 = (Write_Trylock_info*) info1; + Write_Lock_info *_info2 = (Write_Lock_info*) info2; + return ! _info1-> __RET__; +} + +/* Initialization of sequential varialbes */ +static void __SPEC_INIT__() { + writer_lock_acquired = false ; + reader_lock_cnt = 0 ; +} + +/* Cleanup routine of sequential variables */ +static bool __SPEC_CLEANUP__() { + return true; +} + +/* Define function for sequential code initialization */ +inline static void __sequential_init() { + /* Init func_ptr_table */ + func_ptr_table = (void**) malloc(sizeof(void*) * 6 * 2); + func_ptr_table[2 * 3] = (void*) &Write_Trylock_id; + func_ptr_table[2 * 3 + 1] = (void*) &Write_Trylock_check_action; + func_ptr_table[2 * 2] = (void*) &Read_Trylock_id; + func_ptr_table[2 * 2 + 1] = (void*) &Read_Trylock_check_action; + func_ptr_table[2 * 1] = (void*) &Write_Lock_id; + func_ptr_table[2 * 1 + 1] = (void*) &Write_Lock_check_action; + func_ptr_table[2 * 5] = (void*) &Write_Unlock_id; + func_ptr_table[2 * 5 + 1] = (void*) &Write_Unlock_check_action; + func_ptr_table[2 * 4] = (void*) &Read_Unlock_id; + func_ptr_table[2 * 4 + 1] = (void*) &Read_Unlock_check_action; + func_ptr_table[2 * 0] = (void*) &Read_Lock_id; + func_ptr_table[2 * 0 + 1] = (void*) &Read_Lock_check_action; + /* Read_Unlock(true) -> Write_Lock(true) */ + struct hb_rule *hbConditionInit0 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit0->interface_num_before = 4; // Read_Unlock + hbConditionInit0->hb_condition_num_before = 0; // + hbConditionInit0->interface_num_after = 1; // Write_Lock + hbConditionInit0->hb_condition_num_after = 0; // + /* Read_Unlock(true) -> Write_Trylock(HB_Write_Trylock_Succ) */ + struct hb_rule *hbConditionInit1 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit1->interface_num_before = 4; // Read_Unlock + hbConditionInit1->hb_condition_num_before = 0; // + hbConditionInit1->interface_num_after = 3; // Write_Trylock + hbConditionInit1->hb_condition_num_after = 1; // HB_Write_Trylock_Succ + /* Write_Unlock(true) -> Write_Lock(true) */ + struct hb_rule *hbConditionInit2 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit2->interface_num_before = 5; // Write_Unlock + hbConditionInit2->hb_condition_num_before = 0; // + hbConditionInit2->interface_num_after = 1; // Write_Lock + hbConditionInit2->hb_condition_num_after = 0; // + /* Write_Unlock(true) -> Write_Trylock(HB_Write_Trylock_Succ) */ + struct hb_rule *hbConditionInit3 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit3->interface_num_before = 5; // Write_Unlock + hbConditionInit3->hb_condition_num_before = 0; // + hbConditionInit3->interface_num_after = 3; // Write_Trylock + hbConditionInit3->hb_condition_num_after = 1; // HB_Write_Trylock_Succ + /* Write_Unlock(true) -> Read_Lock(true) */ + struct hb_rule *hbConditionInit4 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit4->interface_num_before = 5; // Write_Unlock + hbConditionInit4->hb_condition_num_before = 0; // + hbConditionInit4->interface_num_after = 0; // Read_Lock + hbConditionInit4->hb_condition_num_after = 0; // + /* Write_Unlock(true) -> Read_Trylock(HB_Read_Trylock_Succ) */ + struct hb_rule *hbConditionInit5 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit5->interface_num_before = 5; // Write_Unlock + hbConditionInit5->hb_condition_num_before = 0; // + hbConditionInit5->interface_num_after = 2; // Read_Trylock + hbConditionInit5->hb_condition_num_after = 2; // HB_Read_Trylock_Succ + /* Init hb_rule_table */ + hb_rule_table = (hb_rule**) malloc(sizeof(hb_rule*) * 6); + #define HB_RULE_TABLE_SIZE 6 + hb_rule_table[0] = hbConditionInit0; + hb_rule_table[1] = hbConditionInit1; + hb_rule_table[2] = hbConditionInit2; + hb_rule_table[3] = hbConditionInit3; + hb_rule_table[4] = hbConditionInit4; + hb_rule_table[5] = hbConditionInit5; + /* Init commutativity_rule_table */ + commutativity_rule_table = (commutativity_rule**) malloc(sizeof(commutativity_rule*) * 14); + commutativity_rule* rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 0; + rule->rule = "true"; + rule->condition = CommutativityCondition0; + commutativity_rule_table[0] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 4; + rule->rule = "true"; + rule->condition = CommutativityCondition1; + commutativity_rule_table[1] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 2; + rule->rule = "true"; + rule->condition = CommutativityCondition2; + commutativity_rule_table[2] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 3; + rule->rule = "! _Method2 . __RET__"; + rule->condition = CommutativityCondition3; + commutativity_rule_table[3] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 4; + rule->interface_num_after = 4; + rule->rule = "true"; + rule->condition = CommutativityCondition4; + commutativity_rule_table[4] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 4; + rule->interface_num_after = 2; + rule->rule = "true"; + rule->condition = CommutativityCondition5; + commutativity_rule_table[5] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 4; + rule->interface_num_after = 3; + rule->rule = "! _Method2 . __RET__"; + rule->condition = CommutativityCondition6; + commutativity_rule_table[6] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 2; + rule->rule = "true"; + rule->condition = CommutativityCondition7; + commutativity_rule_table[7] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 3; + rule->rule = "! _Method1 . __RET__ || ! _Method2 . __RET__"; + rule->condition = CommutativityCondition8; + commutativity_rule_table[8] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 1; + rule->rule = "! _Method1 . __RET__"; + rule->condition = CommutativityCondition9; + commutativity_rule_table[9] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 5; + rule->rule = "! _Method1 . __RET__"; + rule->condition = CommutativityCondition10; + commutativity_rule_table[10] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 3; + rule->interface_num_after = 3; + rule->rule = "! _Method1 . __RET__ || ! _Method2 . __RET__"; + rule->condition = CommutativityCondition11; + commutativity_rule_table[11] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 3; + rule->interface_num_after = 5; + rule->rule = "! _Method1 . __RET__"; + rule->condition = CommutativityCondition12; + commutativity_rule_table[12] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 3; + rule->interface_num_after = 1; + rule->rule = "! _Method1 . __RET__"; + rule->condition = CommutativityCondition13; + commutativity_rule_table[13] = rule; + /* Pass init info, including function table info & HB rules & Commutativity Rules */ + struct anno_init *anno_init = (struct anno_init*) malloc(sizeof(struct anno_init)); + anno_init->init_func = (void_func_t) __SPEC_INIT__; + anno_init->cleanup_func = (cleanup_func_t) __SPEC_CLEANUP__; + anno_init->func_table = func_ptr_table; + anno_init->func_table_size = INTERFACE_SIZE; + anno_init->hb_rule_table = hb_rule_table; + anno_init->hb_rule_table_size = HB_RULE_TABLE_SIZE; + anno_init->commutativity_rule_table = commutativity_rule_table; + anno_init->commutativity_rule_table_size = 14; + struct spec_annotation *init = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + init->type = INIT; + init->annotation = anno_init; + cdsannotate(SPEC_ANALYSIS, init); + +} + +/* End of Global construct generation in class */ + + +static inline int read_can_lock(rwlock_t *lock) +{ + return atomic_load_explicit(&lock->lock, memory_order_relaxed) > 0; +} + +static inline int write_can_lock(rwlock_t *lock) +{ + return atomic_load_explicit(&lock->lock, memory_order_relaxed) == RW_LOCK_BIAS; +} + + +void __wrapper__read_lock(rwlock_t * rw); + +void read_lock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 0; // Read_Lock + interface_begin->interface_name = "Read_Lock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__read_lock(rw); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 0; // Read_Lock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Read_Lock_info* info = (Read_Lock_info*) malloc(sizeof(Read_Lock_info)); + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 0; // Read_Lock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__read_lock(rwlock_t * rw) +{ + int priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire); + /* Automatically generated code for commit point define check: Read_Lock_Success_1 */ + + if (priorvalue > 0) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 0; + cp_define_check->label_name = "Read_Lock_Success_1"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + while (priorvalue <= 0) { + atomic_fetch_add_explicit(&rw->lock, 1, memory_order_relaxed); + while (atomic_load_explicit(&rw->lock, memory_order_relaxed) <= 0) { + thrd_yield(); + } + priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire); + /* Automatically generated code for commit point define check: Read_Lock_Success_2 */ + + if (priorvalue > 0) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 1; + cp_define_check->label_name = "Read_Lock_Success_2"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + } +} + + +void __wrapper__write_lock(rwlock_t * rw); + +void write_lock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 1; // Write_Lock + interface_begin->interface_name = "Write_Lock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__write_lock(rw); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 1; // Write_Lock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Write_Lock_info* info = (Write_Lock_info*) malloc(sizeof(Write_Lock_info)); + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 1; // Write_Lock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__write_lock(rwlock_t * rw) +{ + int priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire); + /* Automatically generated code for commit point define check: Write_Lock_Success_1 */ + + if (priorvalue == RW_LOCK_BIAS) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 2; + cp_define_check->label_name = "Write_Lock_Success_1"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + while (priorvalue != RW_LOCK_BIAS) { + atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_relaxed); + while (atomic_load_explicit(&rw->lock, memory_order_relaxed) != RW_LOCK_BIAS) { + thrd_yield(); + } + priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire); + /* Automatically generated code for commit point define check: Write_Lock_Success_2 */ + + if (priorvalue == RW_LOCK_BIAS) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 3; + cp_define_check->label_name = "Write_Lock_Success_2"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + } +} + +int __wrapper__read_trylock(rwlock_t * rw); + +int read_trylock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 2; // Read_Trylock + interface_begin->interface_name = "Read_Trylock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + int __RET__ = __wrapper__read_trylock(rw); + if (__RET__ == 1) { + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 2; // Read_Trylock + hb_condition->hb_condition_num = 2; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + } + + Read_Trylock_info* info = (Read_Trylock_info*) malloc(sizeof(Read_Trylock_info)); + info->__RET__ = __RET__; + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 2; // Read_Trylock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +int __wrapper__read_trylock(rwlock_t * rw) +{ + int priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire); + /* Automatically generated code for potential commit point: Potential_Read_Trylock_Point */ + + if (true) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 4; + potential_cp_define->label_name = "Potential_Read_Trylock_Point"; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + if (priorvalue > 0) { + /* Automatically generated code for commit point define: Read_Trylock_Succ_Point */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 5; + cp_define->label_name = "Read_Trylock_Succ_Point"; + cp_define->potential_cp_label_num = 4; + cp_define->potential_label_name = "Potential_Read_Trylock_Point"; + cp_define->interface_num = 2; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + return 1; + } + /* Automatically generated code for commit point define: Read_Trylock_Fail_Point */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 6; + cp_define->label_name = "Read_Trylock_Fail_Point"; + cp_define->potential_cp_label_num = 4; + cp_define->potential_label_name = "Potential_Read_Trylock_Point"; + cp_define->interface_num = 2; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + atomic_fetch_add_explicit(&rw->lock, 1, memory_order_relaxed); + return 0; +} + +int __wrapper__write_trylock(rwlock_t * rw); + +int write_trylock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 3; // Write_Trylock + interface_begin->interface_name = "Write_Trylock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + int __RET__ = __wrapper__write_trylock(rw); + if (__RET__ == 1) { + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 3; // Write_Trylock + hb_condition->hb_condition_num = 1; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + } + + Write_Trylock_info* info = (Write_Trylock_info*) malloc(sizeof(Write_Trylock_info)); + info->__RET__ = __RET__; + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 3; // Write_Trylock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +int __wrapper__write_trylock(rwlock_t * rw) +{ + int priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire); + /* Automatically generated code for potential commit point: Potential_Write_Trylock_Point */ + + if (true) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 7; + potential_cp_define->label_name = "Potential_Write_Trylock_Point"; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + if (priorvalue == RW_LOCK_BIAS) { + /* Automatically generated code for commit point define: Write_Trylock_Succ_Point */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 8; + cp_define->label_name = "Write_Trylock_Succ_Point"; + cp_define->potential_cp_label_num = 7; + cp_define->potential_label_name = "Potential_Write_Trylock_Point"; + cp_define->interface_num = 3; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + return 1; + } + /* Automatically generated code for commit point define: Write_Trylock_Fail_Point */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 9; + cp_define->label_name = "Write_Trylock_Fail_Point"; + cp_define->potential_cp_label_num = 7; + cp_define->potential_label_name = "Potential_Write_Trylock_Point"; + cp_define->interface_num = 3; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_relaxed); + return 0; +} + +void __wrapper__read_unlock(rwlock_t * rw); + +void read_unlock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 4; // Read_Unlock + interface_begin->interface_name = "Read_Unlock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__read_unlock(rw); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 4; // Read_Unlock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Read_Unlock_info* info = (Read_Unlock_info*) malloc(sizeof(Read_Unlock_info)); + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 4; // Read_Unlock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__read_unlock(rwlock_t * rw) +{ + + atomic_fetch_add_explicit(&rw->lock, 1, memory_order_release); + /* Automatically generated code for commit point define check: Read_Unlock_Point */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 10; + cp_define_check->label_name = "Read_Unlock_Point"; + cp_define_check->interface_num = 4; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + +} + +void __wrapper__write_unlock(rwlock_t * rw); + +void write_unlock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 5; // Write_Unlock + interface_begin->interface_name = "Write_Unlock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__write_unlock(rw); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 5; // Write_Unlock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Write_Unlock_info* info = (Write_Unlock_info*) malloc(sizeof(Write_Unlock_info)); + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 5; // Write_Unlock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__write_unlock(rwlock_t * rw) +{ + + atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_release); + /* Automatically generated code for commit point define check: Write_Unlock_Point */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 11; + cp_define_check->label_name = "Write_Unlock_Point"; + cp_define_check->interface_num = 5; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + + +} + +rwlock_t mylock; +int shareddata; + +static void a(void *obj) +{ + write_lock(&mylock); + shareddata = 47; + write_unlock(&mylock); +} + +static void b(void *obj) +{ + if (read_trylock(&mylock)) { + read_unlock(&mylock); + } +} + +int user_main(int argc, char **argv) +{ + __sequential_init(); + + thrd_t t1, t2; + atomic_init(&mylock.lock, RW_LOCK_BIAS); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&b, NULL); + + thrd_join(t1); + thrd_join(t2); + + return 0; +} + diff --git a/output/linuxrwlocks/testcase2 b/output/linuxrwlocks/testcase2 new file mode 100755 index 0000000..28de7a6 Binary files /dev/null and b/output/linuxrwlocks/testcase2 differ diff --git a/output/linuxrwlocks/testcase2.c b/output/linuxrwlocks/testcase2.c new file mode 100644 index 0000000..3c142ad --- /dev/null +++ b/output/linuxrwlocks/testcase2.c @@ -0,0 +1,930 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include "common.h" + +#include "librace.h" + +#define RW_LOCK_BIAS 0x00100000 +#define WRITE_LOCK_CMP RW_LOCK_BIAS + +typedef union { + atomic_int lock; +} rwlock_t; + + + + + + + +/* All other user-defined structs */ +static bool writer_lock_acquired; +static int reader_lock_cnt; +/* All other user-defined functions */ +/* Definition of interface info struct: Write_Trylock */ +typedef struct Write_Trylock_info { +int __RET__; +rwlock_t * rw; +} Write_Trylock_info; +/* End of info struct definition: Write_Trylock */ + +/* ID function of interface: Write_Trylock */ +inline static call_id_t Write_Trylock_id(void *info, thread_id_t __TID__) { + Write_Trylock_info* theInfo = (Write_Trylock_info*)info; + int __RET__ = theInfo->__RET__; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Write_Trylock */ + +/* Check action function of interface: Write_Trylock */ +inline static bool Write_Trylock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Write_Trylock_info* theInfo = (Write_Trylock_info*)info; + int __RET__ = theInfo->__RET__; + rwlock_t * rw = theInfo->rw; + + if ( __RET__ == 1 ) writer_lock_acquired = true ; + return true; +} +/* End of check action function: Write_Trylock */ + +/* Definition of interface info struct: Read_Trylock */ +typedef struct Read_Trylock_info { +int __RET__; +rwlock_t * rw; +} Read_Trylock_info; +/* End of info struct definition: Read_Trylock */ + +/* ID function of interface: Read_Trylock */ +inline static call_id_t Read_Trylock_id(void *info, thread_id_t __TID__) { + Read_Trylock_info* theInfo = (Read_Trylock_info*)info; + int __RET__ = theInfo->__RET__; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Read_Trylock */ + +/* Check action function of interface: Read_Trylock */ +inline static bool Read_Trylock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Read_Trylock_info* theInfo = (Read_Trylock_info*)info; + int __RET__ = theInfo->__RET__; + rwlock_t * rw = theInfo->rw; + + if ( __RET__ ) reader_lock_cnt ++ ; + check_passed = __RET__ == ! writer_lock_acquired || ! __RET__; + if (!check_passed) + return false; + return true; +} +/* End of check action function: Read_Trylock */ + +/* Definition of interface info struct: Write_Lock */ +typedef struct Write_Lock_info { +rwlock_t * rw; +} Write_Lock_info; +/* End of info struct definition: Write_Lock */ + +/* ID function of interface: Write_Lock */ +inline static call_id_t Write_Lock_id(void *info, thread_id_t __TID__) { + Write_Lock_info* theInfo = (Write_Lock_info*)info; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Write_Lock */ + +/* Check action function of interface: Write_Lock */ +inline static bool Write_Lock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Write_Lock_info* theInfo = (Write_Lock_info*)info; + rwlock_t * rw = theInfo->rw; + + check_passed = ! writer_lock_acquired && reader_lock_cnt == 0; + if (!check_passed) + return false; + writer_lock_acquired = true ; + return true; +} +/* End of check action function: Write_Lock */ + +/* Definition of interface info struct: Write_Unlock */ +typedef struct Write_Unlock_info { +rwlock_t * rw; +} Write_Unlock_info; +/* End of info struct definition: Write_Unlock */ + +/* ID function of interface: Write_Unlock */ +inline static call_id_t Write_Unlock_id(void *info, thread_id_t __TID__) { + Write_Unlock_info* theInfo = (Write_Unlock_info*)info; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Write_Unlock */ + +/* Check action function of interface: Write_Unlock */ +inline static bool Write_Unlock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Write_Unlock_info* theInfo = (Write_Unlock_info*)info; + rwlock_t * rw = theInfo->rw; + + check_passed = reader_lock_cnt == 0 && writer_lock_acquired; + if (!check_passed) + return false; + writer_lock_acquired = false ; + return true; +} +/* End of check action function: Write_Unlock */ + +/* Definition of interface info struct: Read_Unlock */ +typedef struct Read_Unlock_info { +rwlock_t * rw; +} Read_Unlock_info; +/* End of info struct definition: Read_Unlock */ + +/* ID function of interface: Read_Unlock */ +inline static call_id_t Read_Unlock_id(void *info, thread_id_t __TID__) { + Read_Unlock_info* theInfo = (Read_Unlock_info*)info; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Read_Unlock */ + +/* Check action function of interface: Read_Unlock */ +inline static bool Read_Unlock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Read_Unlock_info* theInfo = (Read_Unlock_info*)info; + rwlock_t * rw = theInfo->rw; + + check_passed = reader_lock_cnt > 0 && ! writer_lock_acquired; + if (!check_passed) + return false; + reader_lock_cnt -- ; + return true; +} +/* End of check action function: Read_Unlock */ + +/* Definition of interface info struct: Read_Lock */ +typedef struct Read_Lock_info { +rwlock_t * rw; +} Read_Lock_info; +/* End of info struct definition: Read_Lock */ + +/* ID function of interface: Read_Lock */ +inline static call_id_t Read_Lock_id(void *info, thread_id_t __TID__) { + Read_Lock_info* theInfo = (Read_Lock_info*)info; + rwlock_t * rw = theInfo->rw; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Read_Lock */ + +/* Check action function of interface: Read_Lock */ +inline static bool Read_Lock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Read_Lock_info* theInfo = (Read_Lock_info*)info; + rwlock_t * rw = theInfo->rw; + + check_passed = ! writer_lock_acquired; + if (!check_passed) + return false; + reader_lock_cnt ++ ; + return true; +} +/* End of check action function: Read_Lock */ + +#define INTERFACE_SIZE 6 +static void** func_ptr_table; +static hb_rule** hb_rule_table; +static commutativity_rule** commutativity_rule_table; +inline static bool CommutativityCondition0(void *info1, void *info2) { + Read_Lock_info *_info1 = (Read_Lock_info*) info1; + Read_Lock_info *_info2 = (Read_Lock_info*) info2; + return true; +} +inline static bool CommutativityCondition1(void *info1, void *info2) { + Read_Lock_info *_info1 = (Read_Lock_info*) info1; + Read_Unlock_info *_info2 = (Read_Unlock_info*) info2; + return true; +} +inline static bool CommutativityCondition2(void *info1, void *info2) { + Read_Lock_info *_info1 = (Read_Lock_info*) info1; + Read_Trylock_info *_info2 = (Read_Trylock_info*) info2; + return true; +} +inline static bool CommutativityCondition3(void *info1, void *info2) { + Read_Lock_info *_info1 = (Read_Lock_info*) info1; + Write_Trylock_info *_info2 = (Write_Trylock_info*) info2; + return ! _info2-> __RET__; +} +inline static bool CommutativityCondition4(void *info1, void *info2) { + Read_Unlock_info *_info1 = (Read_Unlock_info*) info1; + Read_Unlock_info *_info2 = (Read_Unlock_info*) info2; + return true; +} +inline static bool CommutativityCondition5(void *info1, void *info2) { + Read_Unlock_info *_info1 = (Read_Unlock_info*) info1; + Read_Trylock_info *_info2 = (Read_Trylock_info*) info2; + return true; +} +inline static bool CommutativityCondition6(void *info1, void *info2) { + Read_Unlock_info *_info1 = (Read_Unlock_info*) info1; + Write_Trylock_info *_info2 = (Write_Trylock_info*) info2; + return ! _info2-> __RET__; +} +inline static bool CommutativityCondition7(void *info1, void *info2) { + Read_Trylock_info *_info1 = (Read_Trylock_info*) info1; + Read_Trylock_info *_info2 = (Read_Trylock_info*) info2; + return true; +} +inline static bool CommutativityCondition8(void *info1, void *info2) { + Read_Trylock_info *_info1 = (Read_Trylock_info*) info1; + Write_Trylock_info *_info2 = (Write_Trylock_info*) info2; + return ! _info1-> __RET__ || ! _info2-> __RET__; +} +inline static bool CommutativityCondition9(void *info1, void *info2) { + Read_Trylock_info *_info1 = (Read_Trylock_info*) info1; + Write_Lock_info *_info2 = (Write_Lock_info*) info2; + return ! _info1-> __RET__; +} +inline static bool CommutativityCondition10(void *info1, void *info2) { + Read_Trylock_info *_info1 = (Read_Trylock_info*) info1; + Write_Unlock_info *_info2 = (Write_Unlock_info*) info2; + return ! _info1-> __RET__; +} +inline static bool CommutativityCondition11(void *info1, void *info2) { + Write_Trylock_info *_info1 = (Write_Trylock_info*) info1; + Write_Trylock_info *_info2 = (Write_Trylock_info*) info2; + return ! _info1-> __RET__ || ! _info2-> __RET__; +} +inline static bool CommutativityCondition12(void *info1, void *info2) { + Write_Trylock_info *_info1 = (Write_Trylock_info*) info1; + Write_Unlock_info *_info2 = (Write_Unlock_info*) info2; + return ! _info1-> __RET__; +} +inline static bool CommutativityCondition13(void *info1, void *info2) { + Write_Trylock_info *_info1 = (Write_Trylock_info*) info1; + Write_Lock_info *_info2 = (Write_Lock_info*) info2; + return ! _info1-> __RET__; +} + +/* Initialization of sequential varialbes */ +static void __SPEC_INIT__() { + writer_lock_acquired = false ; + reader_lock_cnt = 0 ; +} + +/* Cleanup routine of sequential variables */ +static bool __SPEC_CLEANUP__() { + return true; +} + +/* Define function for sequential code initialization */ +inline static void __sequential_init() { + /* Init func_ptr_table */ + func_ptr_table = (void**) malloc(sizeof(void*) * 6 * 2); + func_ptr_table[2 * 3] = (void*) &Write_Trylock_id; + func_ptr_table[2 * 3 + 1] = (void*) &Write_Trylock_check_action; + func_ptr_table[2 * 2] = (void*) &Read_Trylock_id; + func_ptr_table[2 * 2 + 1] = (void*) &Read_Trylock_check_action; + func_ptr_table[2 * 1] = (void*) &Write_Lock_id; + func_ptr_table[2 * 1 + 1] = (void*) &Write_Lock_check_action; + func_ptr_table[2 * 5] = (void*) &Write_Unlock_id; + func_ptr_table[2 * 5 + 1] = (void*) &Write_Unlock_check_action; + func_ptr_table[2 * 4] = (void*) &Read_Unlock_id; + func_ptr_table[2 * 4 + 1] = (void*) &Read_Unlock_check_action; + func_ptr_table[2 * 0] = (void*) &Read_Lock_id; + func_ptr_table[2 * 0 + 1] = (void*) &Read_Lock_check_action; + /* Read_Unlock(true) -> Write_Lock(true) */ + struct hb_rule *hbConditionInit0 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit0->interface_num_before = 4; // Read_Unlock + hbConditionInit0->hb_condition_num_before = 0; // + hbConditionInit0->interface_num_after = 1; // Write_Lock + hbConditionInit0->hb_condition_num_after = 0; // + /* Read_Unlock(true) -> Write_Trylock(HB_Write_Trylock_Succ) */ + struct hb_rule *hbConditionInit1 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit1->interface_num_before = 4; // Read_Unlock + hbConditionInit1->hb_condition_num_before = 0; // + hbConditionInit1->interface_num_after = 3; // Write_Trylock + hbConditionInit1->hb_condition_num_after = 1; // HB_Write_Trylock_Succ + /* Write_Unlock(true) -> Write_Lock(true) */ + struct hb_rule *hbConditionInit2 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit2->interface_num_before = 5; // Write_Unlock + hbConditionInit2->hb_condition_num_before = 0; // + hbConditionInit2->interface_num_after = 1; // Write_Lock + hbConditionInit2->hb_condition_num_after = 0; // + /* Write_Unlock(true) -> Write_Trylock(HB_Write_Trylock_Succ) */ + struct hb_rule *hbConditionInit3 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit3->interface_num_before = 5; // Write_Unlock + hbConditionInit3->hb_condition_num_before = 0; // + hbConditionInit3->interface_num_after = 3; // Write_Trylock + hbConditionInit3->hb_condition_num_after = 1; // HB_Write_Trylock_Succ + /* Write_Unlock(true) -> Read_Lock(true) */ + struct hb_rule *hbConditionInit4 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit4->interface_num_before = 5; // Write_Unlock + hbConditionInit4->hb_condition_num_before = 0; // + hbConditionInit4->interface_num_after = 0; // Read_Lock + hbConditionInit4->hb_condition_num_after = 0; // + /* Write_Unlock(true) -> Read_Trylock(HB_Read_Trylock_Succ) */ + struct hb_rule *hbConditionInit5 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit5->interface_num_before = 5; // Write_Unlock + hbConditionInit5->hb_condition_num_before = 0; // + hbConditionInit5->interface_num_after = 2; // Read_Trylock + hbConditionInit5->hb_condition_num_after = 2; // HB_Read_Trylock_Succ + /* Init hb_rule_table */ + hb_rule_table = (hb_rule**) malloc(sizeof(hb_rule*) * 6); + #define HB_RULE_TABLE_SIZE 6 + hb_rule_table[0] = hbConditionInit0; + hb_rule_table[1] = hbConditionInit1; + hb_rule_table[2] = hbConditionInit2; + hb_rule_table[3] = hbConditionInit3; + hb_rule_table[4] = hbConditionInit4; + hb_rule_table[5] = hbConditionInit5; + /* Init commutativity_rule_table */ + commutativity_rule_table = (commutativity_rule**) malloc(sizeof(commutativity_rule*) * 14); + commutativity_rule* rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 0; + rule->rule = "true"; + rule->condition = CommutativityCondition0; + commutativity_rule_table[0] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 4; + rule->rule = "true"; + rule->condition = CommutativityCondition1; + commutativity_rule_table[1] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 2; + rule->rule = "true"; + rule->condition = CommutativityCondition2; + commutativity_rule_table[2] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 3; + rule->rule = "! _Method2 . __RET__"; + rule->condition = CommutativityCondition3; + commutativity_rule_table[3] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 4; + rule->interface_num_after = 4; + rule->rule = "true"; + rule->condition = CommutativityCondition4; + commutativity_rule_table[4] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 4; + rule->interface_num_after = 2; + rule->rule = "true"; + rule->condition = CommutativityCondition5; + commutativity_rule_table[5] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 4; + rule->interface_num_after = 3; + rule->rule = "! _Method2 . __RET__"; + rule->condition = CommutativityCondition6; + commutativity_rule_table[6] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 2; + rule->rule = "true"; + rule->condition = CommutativityCondition7; + commutativity_rule_table[7] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 3; + rule->rule = "! _Method1 . __RET__ || ! _Method2 . __RET__"; + rule->condition = CommutativityCondition8; + commutativity_rule_table[8] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 1; + rule->rule = "! _Method1 . __RET__"; + rule->condition = CommutativityCondition9; + commutativity_rule_table[9] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 5; + rule->rule = "! _Method1 . __RET__"; + rule->condition = CommutativityCondition10; + commutativity_rule_table[10] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 3; + rule->interface_num_after = 3; + rule->rule = "! _Method1 . __RET__ || ! _Method2 . __RET__"; + rule->condition = CommutativityCondition11; + commutativity_rule_table[11] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 3; + rule->interface_num_after = 5; + rule->rule = "! _Method1 . __RET__"; + rule->condition = CommutativityCondition12; + commutativity_rule_table[12] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 3; + rule->interface_num_after = 1; + rule->rule = "! _Method1 . __RET__"; + rule->condition = CommutativityCondition13; + commutativity_rule_table[13] = rule; + /* Pass init info, including function table info & HB rules & Commutativity Rules */ + struct anno_init *anno_init = (struct anno_init*) malloc(sizeof(struct anno_init)); + anno_init->init_func = (void_func_t) __SPEC_INIT__; + anno_init->cleanup_func = (cleanup_func_t) __SPEC_CLEANUP__; + anno_init->func_table = func_ptr_table; + anno_init->func_table_size = INTERFACE_SIZE; + anno_init->hb_rule_table = hb_rule_table; + anno_init->hb_rule_table_size = HB_RULE_TABLE_SIZE; + anno_init->commutativity_rule_table = commutativity_rule_table; + anno_init->commutativity_rule_table_size = 14; + struct spec_annotation *init = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + init->type = INIT; + init->annotation = anno_init; + cdsannotate(SPEC_ANALYSIS, init); + +} + +/* End of Global construct generation in class */ + + +static inline int read_can_lock(rwlock_t *lock) +{ + return atomic_load_explicit(&lock->lock, memory_order_relaxed) > 0; +} + +static inline int write_can_lock(rwlock_t *lock) +{ + return atomic_load_explicit(&lock->lock, memory_order_relaxed) == RW_LOCK_BIAS; +} + + +void __wrapper__read_lock(rwlock_t * rw); + +void read_lock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 0; // Read_Lock + interface_begin->interface_name = "Read_Lock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__read_lock(rw); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 0; // Read_Lock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Read_Lock_info* info = (Read_Lock_info*) malloc(sizeof(Read_Lock_info)); + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 0; // Read_Lock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__read_lock(rwlock_t * rw) +{ + int priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire); + /* Automatically generated code for commit point define check: Read_Lock_Success_1 */ + + if (priorvalue > 0) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 0; + cp_define_check->label_name = "Read_Lock_Success_1"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + while (priorvalue <= 0) { + atomic_fetch_add_explicit(&rw->lock, 1, memory_order_relaxed); + while (atomic_load_explicit(&rw->lock, memory_order_relaxed) <= 0) { + thrd_yield(); + } + priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire); + /* Automatically generated code for commit point define check: Read_Lock_Success_2 */ + + if (priorvalue > 0) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 1; + cp_define_check->label_name = "Read_Lock_Success_2"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + } +} + + +void __wrapper__write_lock(rwlock_t * rw); + +void write_lock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 1; // Write_Lock + interface_begin->interface_name = "Write_Lock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__write_lock(rw); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 1; // Write_Lock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Write_Lock_info* info = (Write_Lock_info*) malloc(sizeof(Write_Lock_info)); + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 1; // Write_Lock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__write_lock(rwlock_t * rw) +{ + int priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire); + /* Automatically generated code for commit point define check: Write_Lock_Success_1 */ + + if (priorvalue == RW_LOCK_BIAS) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 2; + cp_define_check->label_name = "Write_Lock_Success_1"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + while (priorvalue != RW_LOCK_BIAS) { + atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_relaxed); + while (atomic_load_explicit(&rw->lock, memory_order_relaxed) != RW_LOCK_BIAS) { + thrd_yield(); + } + priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire); + /* Automatically generated code for commit point define check: Write_Lock_Success_2 */ + + if (priorvalue == RW_LOCK_BIAS) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 3; + cp_define_check->label_name = "Write_Lock_Success_2"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + } +} + +int __wrapper__read_trylock(rwlock_t * rw); + +int read_trylock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 2; // Read_Trylock + interface_begin->interface_name = "Read_Trylock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + int __RET__ = __wrapper__read_trylock(rw); + if (__RET__ == 1) { + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 2; // Read_Trylock + hb_condition->hb_condition_num = 2; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + } + + Read_Trylock_info* info = (Read_Trylock_info*) malloc(sizeof(Read_Trylock_info)); + info->__RET__ = __RET__; + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 2; // Read_Trylock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +int __wrapper__read_trylock(rwlock_t * rw) +{ + int priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire); + /* Automatically generated code for potential commit point: Potential_Read_Trylock_Point */ + + if (true) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 4; + potential_cp_define->label_name = "Potential_Read_Trylock_Point"; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + if (priorvalue > 0) { + /* Automatically generated code for commit point define: Read_Trylock_Succ_Point */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 5; + cp_define->label_name = "Read_Trylock_Succ_Point"; + cp_define->potential_cp_label_num = 4; + cp_define->potential_label_name = "Potential_Read_Trylock_Point"; + cp_define->interface_num = 2; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + return 1; + } + /* Automatically generated code for commit point define: Read_Trylock_Fail_Point */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 6; + cp_define->label_name = "Read_Trylock_Fail_Point"; + cp_define->potential_cp_label_num = 4; + cp_define->potential_label_name = "Potential_Read_Trylock_Point"; + cp_define->interface_num = 2; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + atomic_fetch_add_explicit(&rw->lock, 1, memory_order_relaxed); + return 0; +} + +int __wrapper__write_trylock(rwlock_t * rw); + +int write_trylock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 3; // Write_Trylock + interface_begin->interface_name = "Write_Trylock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + int __RET__ = __wrapper__write_trylock(rw); + if (__RET__ == 1) { + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 3; // Write_Trylock + hb_condition->hb_condition_num = 1; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + } + + Write_Trylock_info* info = (Write_Trylock_info*) malloc(sizeof(Write_Trylock_info)); + info->__RET__ = __RET__; + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 3; // Write_Trylock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +int __wrapper__write_trylock(rwlock_t * rw) +{ + int priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire); + /* Automatically generated code for potential commit point: Potential_Write_Trylock_Point */ + + if (true) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 7; + potential_cp_define->label_name = "Potential_Write_Trylock_Point"; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + if (priorvalue == RW_LOCK_BIAS) { + /* Automatically generated code for commit point define: Write_Trylock_Succ_Point */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 8; + cp_define->label_name = "Write_Trylock_Succ_Point"; + cp_define->potential_cp_label_num = 7; + cp_define->potential_label_name = "Potential_Write_Trylock_Point"; + cp_define->interface_num = 3; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + return 1; + } + /* Automatically generated code for commit point define: Write_Trylock_Fail_Point */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 9; + cp_define->label_name = "Write_Trylock_Fail_Point"; + cp_define->potential_cp_label_num = 7; + cp_define->potential_label_name = "Potential_Write_Trylock_Point"; + cp_define->interface_num = 3; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_relaxed); + return 0; +} + +void __wrapper__read_unlock(rwlock_t * rw); + +void read_unlock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 4; // Read_Unlock + interface_begin->interface_name = "Read_Unlock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__read_unlock(rw); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 4; // Read_Unlock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Read_Unlock_info* info = (Read_Unlock_info*) malloc(sizeof(Read_Unlock_info)); + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 4; // Read_Unlock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__read_unlock(rwlock_t * rw) +{ + + atomic_fetch_add_explicit(&rw->lock, 1, memory_order_release); + /* Automatically generated code for commit point define check: Read_Unlock_Point */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 10; + cp_define_check->label_name = "Read_Unlock_Point"; + cp_define_check->interface_num = 4; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + +} + +void __wrapper__write_unlock(rwlock_t * rw); + +void write_unlock(rwlock_t * rw) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 5; // Write_Unlock + interface_begin->interface_name = "Write_Unlock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__write_unlock(rw); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 5; // Write_Unlock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Write_Unlock_info* info = (Write_Unlock_info*) malloc(sizeof(Write_Unlock_info)); + info->rw = rw; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 5; // Write_Unlock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__write_unlock(rwlock_t * rw) +{ + + atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_release); + /* Automatically generated code for commit point define check: Write_Unlock_Point */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 11; + cp_define_check->label_name = "Write_Unlock_Point"; + cp_define_check->interface_num = 5; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + + +} + +rwlock_t mylock; +int shareddata; + +static void a(void *obj) +{ + write_lock(&mylock); + shareddata = 47; + write_unlock(&mylock); +} + +static void b(void *obj) +{ + if (write_trylock(&mylock)) { + shareddata = 47; + write_unlock(&mylock); + } + + read_lock(&mylock); + read_unlock(&mylock); +} + +int user_main(int argc, char **argv) +{ + __sequential_init(); + + thrd_t t1, t2; + atomic_init(&mylock.lock, RW_LOCK_BIAS); + + thrd_create(&t1, (thrd_start_t)&a, NULL); + thrd_create(&t2, (thrd_start_t)&b, NULL); + + thrd_join(t1); + thrd_join(t2); + + return 0; +} + diff --git a/output/mcs-lock/mcs-lock b/output/mcs-lock/mcs-lock new file mode 100755 index 0000000..2025053 Binary files /dev/null and b/output/mcs-lock/mcs-lock differ diff --git a/output/mcs-lock/mcs-lock.cc b/output/mcs-lock/mcs-lock.cc new file mode 100644 index 0000000..d95341e --- /dev/null +++ b/output/mcs-lock/mcs-lock.cc @@ -0,0 +1,40 @@ +#include +#include + +#include "mcs-lock.h" + + +#include "librace.h" + +struct mcs_mutex *mutex; +static uint32_t shared; + +void threadA(void *arg) +{ + mcs_mutex::guard g(mutex); + shared = 17; + mutex->unlock(&g); + mutex->lock(&g); + } + +void threadB(void *arg) +{ + mcs_mutex::guard g(mutex); + mutex->unlock(&g); + mutex->lock(&g); + shared = 17; + } + +int user_main(int argc, char **argv) +{ + thrd_t A, B; + + mutex = new mcs_mutex(); + + thrd_create(&A, &threadA, NULL); + thrd_create(&B, &threadB, NULL); + thrd_join(A); + thrd_join(B); + return 0; +} + diff --git a/output/mcs-lock/mcs-lock.h b/output/mcs-lock/mcs-lock.h new file mode 100644 index 0000000..c19e776 --- /dev/null +++ b/output/mcs-lock/mcs-lock.h @@ -0,0 +1,332 @@ + +#include +#include + +#include +#include +#include +#include +#include +#include "common.h" + +struct mcs_node { + std::atomic next; + std::atomic gate; + + mcs_node() { + next.store(0); + gate.store(0); + } +}; + + +struct mcs_mutex { +public: + std::atomic m_tail; + + mcs_mutex() { + __sequential_init(); + + m_tail.store( NULL ); + } + ~mcs_mutex() { + } + + class guard { + public: + mcs_mutex * m_t; + mcs_node m_node; + guard(mcs_mutex * t) : m_t(t) { t->lock(this); } + ~guard() { m_t->unlock(this); } + }; + +/* All other user-defined structs */ +static bool _lock_acquired; +/* All other user-defined functions */ +/* Definition of interface info struct: Unlock */ +typedef struct Unlock_info { +guard * I; +} Unlock_info; +/* End of info struct definition: Unlock */ + +/* ID function of interface: Unlock */ +inline static call_id_t Unlock_id(void *info, thread_id_t __TID__) { + Unlock_info* theInfo = (Unlock_info*)info; + guard * I = theInfo->I; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Unlock */ + +/* Check action function of interface: Unlock */ +inline static bool Unlock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Unlock_info* theInfo = (Unlock_info*)info; + guard * I = theInfo->I; + + check_passed = _lock_acquired == true; + if (!check_passed) + return false; + _lock_acquired = false ; + return true; +} +/* End of check action function: Unlock */ + +/* Definition of interface info struct: Lock */ +typedef struct Lock_info { +guard * I; +} Lock_info; +/* End of info struct definition: Lock */ + +/* ID function of interface: Lock */ +inline static call_id_t Lock_id(void *info, thread_id_t __TID__) { + Lock_info* theInfo = (Lock_info*)info; + guard * I = theInfo->I; + + call_id_t __ID__ = 0; + return __ID__; +} +/* End of ID function: Lock */ + +/* Check action function of interface: Lock */ +inline static bool Lock_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Lock_info* theInfo = (Lock_info*)info; + guard * I = theInfo->I; + + check_passed = _lock_acquired == false ;; + if (!check_passed) + return false; + _lock_acquired = true ; + return true; +} +/* End of check action function: Lock */ + +#define INTERFACE_SIZE 2 +static void** func_ptr_table; +static hb_rule** hb_rule_table; +static commutativity_rule** commutativity_rule_table; + +/* Initialization of sequential varialbes */ +static void __SPEC_INIT__() { + _lock_acquired = false ; +} + +/* Cleanup routine of sequential variables */ +static bool __SPEC_CLEANUP__() { + return true; +} + +/* Define function for sequential code initialization */ +inline static void __sequential_init() { + /* Init func_ptr_table */ + func_ptr_table = (void**) malloc(sizeof(void*) * 2 * 2); + func_ptr_table[2 * 1] = (void*) &Unlock_id; + func_ptr_table[2 * 1 + 1] = (void*) &Unlock_check_action; + func_ptr_table[2 * 0] = (void*) &Lock_id; + func_ptr_table[2 * 0 + 1] = (void*) &Lock_check_action; + /* Unlock(true) -> Lock(true) */ + struct hb_rule *hbConditionInit0 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit0->interface_num_before = 1; // Unlock + hbConditionInit0->hb_condition_num_before = 0; // + hbConditionInit0->interface_num_after = 0; // Lock + hbConditionInit0->hb_condition_num_after = 0; // + /* Init hb_rule_table */ + hb_rule_table = (hb_rule**) malloc(sizeof(hb_rule*) * 1); + #define HB_RULE_TABLE_SIZE 1 + hb_rule_table[0] = hbConditionInit0; + /* Init commutativity_rule_table */ + /* Pass init info, including function table info & HB rules & Commutativity Rules */ + struct anno_init *anno_init = (struct anno_init*) malloc(sizeof(struct anno_init)); + anno_init->init_func = (void_func_t) __SPEC_INIT__; + anno_init->cleanup_func = (cleanup_func_t) __SPEC_CLEANUP__; + anno_init->func_table = func_ptr_table; + anno_init->func_table_size = INTERFACE_SIZE; + anno_init->hb_rule_table = hb_rule_table; + anno_init->hb_rule_table_size = HB_RULE_TABLE_SIZE; + anno_init->commutativity_rule_table = commutativity_rule_table; + anno_init->commutativity_rule_table_size = 0; + struct spec_annotation *init = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + init->type = INIT; + init->annotation = anno_init; + cdsannotate(SPEC_ANALYSIS, init); + +} + +/* End of Global construct generation in class */ + + + +void lock(guard * I) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 0; // Lock + interface_begin->interface_name = "Lock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__lock(I); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 0; // Lock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Lock_info* info = (Lock_info*) malloc(sizeof(Lock_info)); + info->I = I; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 0; // Lock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__lock(guard * I) { + mcs_node * me = &(I->m_node); + + me->next.store(NULL, std::mo_relaxed ); + me->gate.store(1, std::mo_relaxed ); + + + + mcs_node * pred = m_tail.exchange(me, std::mo_acq_rel); + /* Automatically generated code for commit point define check: Lock_Enqueue_Point1 */ + + if (pred == NULL) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 0; + cp_define_check->label_name = "Lock_Enqueue_Point1"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + if ( pred != NULL ) { + + pred->next.store(me, std::mo_release ); + + + rl::linear_backoff bo; + int my_gate = 1; + while (my_gate ) { + + my_gate = me->gate.load(std::mo_acquire); + /* Automatically generated code for commit point define check: Lock_Enqueue_Point2 */ + + if (my_gate == 0) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 1; + cp_define_check->label_name = "Lock_Enqueue_Point2"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + thrd_yield(); + } + } + } + + +void unlock(guard * I) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 1; // Unlock + interface_begin->interface_name = "Unlock"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__unlock(I); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 1; // Unlock + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Unlock_info* info = (Unlock_info*) malloc(sizeof(Unlock_info)); + info->I = I; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 1; // Unlock + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__unlock(guard * I) { + mcs_node * me = &(I->m_node); + + mcs_node * next = me->next.load(std::mo_acquire); + if ( next == NULL ) + { + mcs_node * tail_was_me = me; + bool success; + + + success = m_tail.compare_exchange_strong( + tail_was_me,NULL,std::mo_acq_rel); + /* Automatically generated code for commit point define check: Unlock_Point_Success_1 */ + + if (success == true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 2; + cp_define_check->label_name = "Unlock_Point_Success_1"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + if (success) { + + return; + } + + rl::linear_backoff bo; + for(;;) { + next = me->next.load(std::mo_acquire); + if ( next != NULL ) + break; + thrd_yield(); + } + } + + + + next->gate.store( 0, std::mo_release ); + /* Automatically generated code for commit point define check: Unlock_Point_Success_2 */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 3; + cp_define_check->label_name = "Unlock_Point_Success_2"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + } +}; +void** mcs_mutex::func_ptr_table; +hb_rule** mcs_mutex::hb_rule_table; +commutativity_rule** mcs_mutex::commutativity_rule_table; +bool mcs_mutex::_lock_acquired; + + diff --git a/output/mpmc-queue/mpmc-1r2w b/output/mpmc-queue/mpmc-1r2w new file mode 100755 index 0000000..18ad44d Binary files /dev/null and b/output/mpmc-queue/mpmc-1r2w differ diff --git a/output/mpmc-queue/mpmc-1r2w-noinit b/output/mpmc-queue/mpmc-1r2w-noinit new file mode 100755 index 0000000..8619185 Binary files /dev/null and b/output/mpmc-queue/mpmc-1r2w-noinit differ diff --git a/output/mpmc-queue/mpmc-2r1w b/output/mpmc-queue/mpmc-2r1w new file mode 100755 index 0000000..fceaea1 Binary files /dev/null and b/output/mpmc-queue/mpmc-2r1w differ diff --git a/output/mpmc-queue/mpmc-2r1w-noinit b/output/mpmc-queue/mpmc-2r1w-noinit new file mode 100755 index 0000000..9b40cbd Binary files /dev/null and b/output/mpmc-queue/mpmc-2r1w-noinit differ diff --git a/output/mpmc-queue/mpmc-queue b/output/mpmc-queue/mpmc-queue new file mode 100755 index 0000000..ebb01df Binary files /dev/null and b/output/mpmc-queue/mpmc-queue differ diff --git a/output/mpmc-queue/mpmc-queue-noinit b/output/mpmc-queue/mpmc-queue-noinit new file mode 100755 index 0000000..caec501 Binary files /dev/null and b/output/mpmc-queue/mpmc-queue-noinit differ diff --git a/output/mpmc-queue/mpmc-queue-rdwr b/output/mpmc-queue/mpmc-queue-rdwr new file mode 100755 index 0000000..043c874 Binary files /dev/null and b/output/mpmc-queue/mpmc-queue-rdwr differ diff --git a/output/mpmc-queue/mpmc-queue.cc b/output/mpmc-queue/mpmc-queue.cc new file mode 100644 index 0000000..83b05f2 --- /dev/null +++ b/output/mpmc-queue/mpmc-queue.cc @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include + +#include + +#include "mpmc-queue.h" + +void threadA(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin = queue->write_prepare(); + *bin = 1; + printf("write_bin %d, val %d\n", bin, 1); + queue->write_publish(bin); +} + +void threadB(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin; + while (bin = queue->read_fetch()) { + printf("Read: %d\n", *bin); + queue->read_consume(bin); + } +} + +void threadC(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin = queue->write_prepare(); + *bin = 1; + queue->write_publish(bin); + + while (bin = queue->read_fetch()) { + printf("Read: %d\n", *bin); + queue->read_consume(bin); + } +} + +#define MAXREADERS 3 +#define MAXWRITERS 3 +#define MAXRDWR 3 + +#ifdef CONFIG_MPMC_READERS +#define DEFAULT_READERS (CONFIG_MPMC_READERS) +#else +#define DEFAULT_READERS 2 +#endif + +#ifdef CONFIG_MPMC_WRITERS +#define DEFAULT_WRITERS (CONFIG_MPMC_WRITERS) +#else +#define DEFAULT_WRITERS 2 +#endif + +#ifdef CONFIG_MPMC_RDWR +#define DEFAULT_RDWR (CONFIG_MPMC_RDWR) +#else +#define DEFAULT_RDWR 0 +#endif + +int readers = DEFAULT_READERS, writers = DEFAULT_WRITERS, rdwr = DEFAULT_RDWR; + +void print_usage() +{ + printf("Error: use the following options\n" + " -r Choose number of reader threads\n" + " -w Choose number of writer threads\n"); + exit(EXIT_FAILURE); +} + +void process_params(int argc, char **argv) +{ + const char *shortopts = "hr:w:"; + int opt; + bool error = false; + + while (!error && (opt = getopt(argc, argv, shortopts)) != -1) { + switch (opt) { + case 'h': + print_usage(); + break; + case 'r': + readers = atoi(optarg); + break; + case 'w': + writers = atoi(optarg); + break; + default: + error = true; + break; + } + } + + if (writers < 1 || writers > MAXWRITERS) + error = true; + if (readers < 1 || readers > MAXREADERS) + error = true; + + if (error) + print_usage(); +} + +int user_main(int argc, char **argv) +{ + struct mpmc_boundq_1_alt queue; + thrd_t A[MAXWRITERS], B[MAXREADERS], C[MAXRDWR]; + + + printf("%d reader(s), %d writer(s)\n", readers, writers); + +#ifndef CONFIG_MPMC_NO_INITIAL_ELEMENT + printf("Adding initial element\n"); + int32_t *bin = queue.write_prepare(); + *bin, 17; + printf("init_write_bin %d, val %d\n", bin, 17); + queue.write_publish(bin); +#endif + + printf("Start threads\n"); + + for (int i = 0; i < writers; i++) + thrd_create(&A[i], (thrd_start_t)&threadA, &queue); + for (int i = 0; i < readers; i++) + thrd_create(&B[i], (thrd_start_t)&threadB, &queue); + + for (int i = 0; i < rdwr; i++) + thrd_create(&C[i], (thrd_start_t)&threadC, &queue); + + for (int i = 0; i < writers; i++) + thrd_join(A[i]); + for (int i = 0; i < readers; i++) + thrd_join(B[i]); + for (int i = 0; i < rdwr; i++) + thrd_join(C[i]); + + printf("Threads complete\n"); + + return 0; +} + diff --git a/output/mpmc-queue/mpmc-queue.h b/output/mpmc-queue/mpmc-queue.h new file mode 100644 index 0000000..00eaf67 --- /dev/null +++ b/output/mpmc-queue/mpmc-queue.h @@ -0,0 +1,700 @@ +#include +#include +#include + +#include +#include +#include +#include +#include + + +template +struct mpmc_boundq_1_alt +{ +private: + + unsigned int MASK; + + t_element m_array[t_size]; + + atomic m_rdwr; + atomic m_read; + atomic m_written; + +public: + + mpmc_boundq_1_alt() + { + __sequential_init(); + + m_rdwr = 0; + m_read = 0; + m_written = 0; + MASK = 0x1; } + + +/* All other user-defined structs */ +/* All other user-defined functions */ +/* Definition of interface info struct: Publish */ +typedef struct Publish_info { +t_element * bin; +} Publish_info; +/* End of info struct definition: Publish */ + +/* ID function of interface: Publish */ +inline static call_id_t Publish_id(void *info, thread_id_t __TID__) { + Publish_info* theInfo = (Publish_info*)info; + t_element * bin = theInfo->bin; + + call_id_t __ID__ = ( call_id_t ) bin; + return __ID__; +} +/* End of ID function: Publish */ + +/* Check action function of interface: Publish */ +inline static bool Publish_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Publish_info* theInfo = (Publish_info*)info; + t_element * bin = theInfo->bin; + + return true; +} +/* End of check action function: Publish */ + +/* Definition of interface info struct: Fetch */ +typedef struct Fetch_info { +t_element * __RET__; +} Fetch_info; +/* End of info struct definition: Fetch */ + +/* ID function of interface: Fetch */ +inline static call_id_t Fetch_id(void *info, thread_id_t __TID__) { + Fetch_info* theInfo = (Fetch_info*)info; + t_element * __RET__ = theInfo->__RET__; + + call_id_t __ID__ = ( call_id_t ) __RET__; + return __ID__; +} +/* End of ID function: Fetch */ + +/* Check action function of interface: Fetch */ +inline static bool Fetch_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Fetch_info* theInfo = (Fetch_info*)info; + t_element * __RET__ = theInfo->__RET__; + + return true; +} +/* End of check action function: Fetch */ + +/* Definition of interface info struct: Prepare */ +typedef struct Prepare_info { +t_element * __RET__; +} Prepare_info; +/* End of info struct definition: Prepare */ + +/* ID function of interface: Prepare */ +inline static call_id_t Prepare_id(void *info, thread_id_t __TID__) { + Prepare_info* theInfo = (Prepare_info*)info; + t_element * __RET__ = theInfo->__RET__; + + call_id_t __ID__ = ( call_id_t ) __RET__; + return __ID__; +} +/* End of ID function: Prepare */ + +/* Check action function of interface: Prepare */ +inline static bool Prepare_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Prepare_info* theInfo = (Prepare_info*)info; + t_element * __RET__ = theInfo->__RET__; + + return true; +} +/* End of check action function: Prepare */ + +/* Definition of interface info struct: Consume */ +typedef struct Consume_info { +t_element * bin; +} Consume_info; +/* End of info struct definition: Consume */ + +/* ID function of interface: Consume */ +inline static call_id_t Consume_id(void *info, thread_id_t __TID__) { + Consume_info* theInfo = (Consume_info*)info; + t_element * bin = theInfo->bin; + + call_id_t __ID__ = ( call_id_t ) bin; + return __ID__; +} +/* End of ID function: Consume */ + +/* Check action function of interface: Consume */ +inline static bool Consume_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Consume_info* theInfo = (Consume_info*)info; + t_element * bin = theInfo->bin; + + return true; +} +/* End of check action function: Consume */ + +#define INTERFACE_SIZE 4 +static void** func_ptr_table; +static hb_rule** hb_rule_table; +static commutativity_rule** commutativity_rule_table; +inline static bool CommutativityCondition0(void *info1, void *info2) { + Prepare_info *_info1 = (Prepare_info*) info1; + Prepare_info *_info2 = (Prepare_info*) info2; + return _info1-> __RET__ != _info2-> __RET__ || ! _info1-> __RET__ || ! _info2-> __RET__; +} +inline static bool CommutativityCondition1(void *info1, void *info2) { + Prepare_info *_info1 = (Prepare_info*) info1; + Publish_info *_info2 = (Publish_info*) info2; + return _info1-> __RET__ != _info2-> bin || ! _info1-> __RET__; +} +inline static bool CommutativityCondition2(void *info1, void *info2) { + Prepare_info *_info1 = (Prepare_info*) info1; + Fetch_info *_info2 = (Fetch_info*) info2; + return _info1-> __RET__ != _info2-> __RET__ || ! _info1-> __RET__ || ! _info2-> __RET__; +} +inline static bool CommutativityCondition3(void *info1, void *info2) { + Prepare_info *_info1 = (Prepare_info*) info1; + Consume_info *_info2 = (Consume_info*) info2; + return _info1-> __RET__ != _info2-> bin || ! _info1-> __RET__; +} +inline static bool CommutativityCondition4(void *info1, void *info2) { + Publish_info *_info1 = (Publish_info*) info1; + Publish_info *_info2 = (Publish_info*) info2; + return _info1-> bin != _info2-> bin; +} +inline static bool CommutativityCondition5(void *info1, void *info2) { + Publish_info *_info1 = (Publish_info*) info1; + Fetch_info *_info2 = (Fetch_info*) info2; + return _info1-> bin != _info2-> __RET__ || ! _info2-> __RET__; +} +inline static bool CommutativityCondition6(void *info1, void *info2) { + Publish_info *_info1 = (Publish_info*) info1; + Consume_info *_info2 = (Consume_info*) info2; + return _info1-> bin != _info2-> bin; +} +inline static bool CommutativityCondition7(void *info1, void *info2) { + Fetch_info *_info1 = (Fetch_info*) info1; + Fetch_info *_info2 = (Fetch_info*) info2; + return _info1-> __RET__ != _info2-> __RET__ || ! _info1-> __RET__ || ! _info2-> __RET__; +} +inline static bool CommutativityCondition8(void *info1, void *info2) { + Fetch_info *_info1 = (Fetch_info*) info1; + Consume_info *_info2 = (Consume_info*) info2; + return _info1-> __RET__ != _info2-> bin || ! _info1-> __RET__; +} +inline static bool CommutativityCondition9(void *info1, void *info2) { + Consume_info *_info1 = (Consume_info*) info1; + Consume_info *_info2 = (Consume_info*) info2; + return _info1-> bin != _info2-> bin; +} + +/* Initialization of sequential varialbes */ +static void __SPEC_INIT__() { +} + +/* Cleanup routine of sequential variables */ +static bool __SPEC_CLEANUP__() { + return true; +} + +/* Define function for sequential code initialization */ +inline static void __sequential_init() { + /* Init func_ptr_table */ + func_ptr_table = (void**) malloc(sizeof(void*) * 4 * 2); + func_ptr_table[2 * 3] = (void*) &Publish_id; + func_ptr_table[2 * 3 + 1] = (void*) &Publish_check_action; + func_ptr_table[2 * 0] = (void*) &Fetch_id; + func_ptr_table[2 * 0 + 1] = (void*) &Fetch_check_action; + func_ptr_table[2 * 2] = (void*) &Prepare_id; + func_ptr_table[2 * 2 + 1] = (void*) &Prepare_check_action; + func_ptr_table[2 * 1] = (void*) &Consume_id; + func_ptr_table[2 * 1 + 1] = (void*) &Consume_check_action; + /* Consume(true) -> Prepare(true) */ + struct hb_rule *hbConditionInit0 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit0->interface_num_before = 1; // Consume + hbConditionInit0->hb_condition_num_before = 0; // + hbConditionInit0->interface_num_after = 2; // Prepare + hbConditionInit0->hb_condition_num_after = 0; // + /* Publish(true) -> Fetch(true) */ + struct hb_rule *hbConditionInit1 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit1->interface_num_before = 3; // Publish + hbConditionInit1->hb_condition_num_before = 0; // + hbConditionInit1->interface_num_after = 0; // Fetch + hbConditionInit1->hb_condition_num_after = 0; // + /* Init hb_rule_table */ + hb_rule_table = (hb_rule**) malloc(sizeof(hb_rule*) * 2); + #define HB_RULE_TABLE_SIZE 2 + hb_rule_table[0] = hbConditionInit0; + hb_rule_table[1] = hbConditionInit1; + /* Init commutativity_rule_table */ + commutativity_rule_table = (commutativity_rule**) malloc(sizeof(commutativity_rule*) * 10); + commutativity_rule* rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 2; + rule->rule = "_Method1 . __RET__ != _Method2 . __RET__ || ! _Method1 . __RET__ || ! _Method2 . __RET__"; + rule->condition = CommutativityCondition0; + commutativity_rule_table[0] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 3; + rule->rule = "_Method1 . __RET__ != _Method2 . bin || ! _Method1 . __RET__"; + rule->condition = CommutativityCondition1; + commutativity_rule_table[1] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 0; + rule->rule = "_Method1 . __RET__ != _Method2 . __RET__ || ! _Method1 . __RET__ || ! _Method2 . __RET__"; + rule->condition = CommutativityCondition2; + commutativity_rule_table[2] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 2; + rule->interface_num_after = 1; + rule->rule = "_Method1 . __RET__ != _Method2 . bin || ! _Method1 . __RET__"; + rule->condition = CommutativityCondition3; + commutativity_rule_table[3] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 3; + rule->interface_num_after = 3; + rule->rule = "_Method1 . bin != _Method2 . bin"; + rule->condition = CommutativityCondition4; + commutativity_rule_table[4] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 3; + rule->interface_num_after = 0; + rule->rule = "_Method1 . bin != _Method2 . __RET__ || ! _Method2 . __RET__"; + rule->condition = CommutativityCondition5; + commutativity_rule_table[5] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 3; + rule->interface_num_after = 1; + rule->rule = "_Method1 . bin != _Method2 . bin"; + rule->condition = CommutativityCondition6; + commutativity_rule_table[6] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 0; + rule->rule = "_Method1 . __RET__ != _Method2 . __RET__ || ! _Method1 . __RET__ || ! _Method2 . __RET__"; + rule->condition = CommutativityCondition7; + commutativity_rule_table[7] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 1; + rule->rule = "_Method1 . __RET__ != _Method2 . bin || ! _Method1 . __RET__"; + rule->condition = CommutativityCondition8; + commutativity_rule_table[8] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 1; + rule->interface_num_after = 1; + rule->rule = "_Method1 . bin != _Method2 . bin"; + rule->condition = CommutativityCondition9; + commutativity_rule_table[9] = rule; + /* Pass init info, including function table info & HB rules & Commutativity Rules */ + struct anno_init *anno_init = (struct anno_init*) malloc(sizeof(struct anno_init)); + anno_init->init_func = (void_func_t) __SPEC_INIT__; + anno_init->cleanup_func = (cleanup_func_t) __SPEC_CLEANUP__; + anno_init->func_table = func_ptr_table; + anno_init->func_table_size = INTERFACE_SIZE; + anno_init->hb_rule_table = hb_rule_table; + anno_init->hb_rule_table_size = HB_RULE_TABLE_SIZE; + anno_init->commutativity_rule_table = commutativity_rule_table; + anno_init->commutativity_rule_table_size = 10; + struct spec_annotation *init = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + init->type = INIT; + init->annotation = anno_init; + cdsannotate(SPEC_ANALYSIS, init); + +} + +/* End of Global construct generation in class */ + + + + +t_element * read_fetch() { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 0; // Fetch + interface_begin->interface_name = "Fetch"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + t_element * __RET__ = __wrapper__read_fetch(); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 0; // Fetch + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Fetch_info* info = (Fetch_info*) malloc(sizeof(Fetch_info)); + info->__RET__ = __RET__; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 0; // Fetch + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +t_element * __wrapper__read_fetch() { + unsigned int rdwr = m_rdwr.load(mo_acquire); + /* Automatically generated code for potential commit point: Fetch_Potential_RW_Load */ + + if (true) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 0; + potential_cp_define->label_name = "Fetch_Potential_RW_Load"; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + unsigned int rd,wr; + for(;;) { + rd = (rdwr>>16) & MASK; + wr = rdwr & MASK; + + if ( wr == rd ) { + /* Automatically generated code for commit point define: Fetch_RW_Load_Empty */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 1; + cp_define->label_name = "Fetch_RW_Load_Empty"; + cp_define->potential_cp_label_num = 0; + cp_define->potential_label_name = "Fetch_Potential_RW_Load"; + cp_define->interface_num = 0; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + + return false; + } + + + bool succ = + m_rdwr.compare_exchange_weak(rdwr,rdwr+(1<<16),mo_acq_rel); + /* Automatically generated code for commit point define check: Fetch_RW_RMW */ + + if (succ) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 2; + cp_define_check->label_name = "Fetch_RW_RMW"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + if (succ) + break; + else + thrd_yield(); + } + + rl::backoff bo; + while (true) { + + int written = m_written.load(mo_acquire); + /* Automatically generated code for potential commit point: Fetch_Potential_W_Load */ + + if (true) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 3; + potential_cp_define->label_name = "Fetch_Potential_W_Load"; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + if ((written & MASK) != wr) { + thrd_yield(); + } else { + printf("Fetch: m_written=%d\n", written); + break; + } + } + + /* Automatically generated code for commit point define: Fetch_W_Load */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 4; + cp_define->label_name = "Fetch_W_Load"; + cp_define->potential_cp_label_num = 3; + cp_define->potential_label_name = "Fetch_Potential_W_Load"; + cp_define->interface_num = 0; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + + t_element * p = & ( m_array[ rd % t_size ] ); + + return p; + } + + +void read_consume(t_element * bin) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 1; // Consume + interface_begin->interface_name = "Consume"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__read_consume(bin); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 1; // Consume + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Consume_info* info = (Consume_info*) malloc(sizeof(Consume_info)); + info->bin = bin; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 1; // Consume + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__read_consume(t_element * bin) { + + m_read.fetch_add(1,mo_release); + /* Automatically generated code for commit point define check: Consume_R_RMW */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 5; + cp_define_check->label_name = "Consume_R_RMW"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + } + + + +t_element * write_prepare() { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 2; // Prepare + interface_begin->interface_name = "Prepare"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + t_element * __RET__ = __wrapper__write_prepare(); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 2; // Prepare + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Prepare_info* info = (Prepare_info*) malloc(sizeof(Prepare_info)); + info->__RET__ = __RET__; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 2; // Prepare + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +t_element * __wrapper__write_prepare() { + unsigned int rdwr = m_rdwr.load(mo_acquire); + /* Automatically generated code for potential commit point: Prepare_Potential_RW_Load */ + + if (true) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 6; + potential_cp_define->label_name = "Prepare_Potential_RW_Load"; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + unsigned int rd,wr; + for(;;) { + rd = (rdwr>>16) & MASK; + wr = rdwr & MASK; + + if ( wr == ((rd + t_size)&MASK) ) { + /* Automatically generated code for commit point define: Prepare_RW_Load_Full */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 7; + cp_define->label_name = "Prepare_RW_Load_Full"; + cp_define->potential_cp_label_num = 6; + cp_define->potential_label_name = "Prepare_Potential_RW_Load"; + cp_define->interface_num = 2; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + return NULL; + } + + + bool succ = m_rdwr.compare_exchange_weak(rdwr,(rd<<16) | + ((wr+1)&MASK),mo_acq_rel); + /* Automatically generated code for commit point define check: Prepare_RW_RMW */ + + if (succ) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 8; + cp_define_check->label_name = "Prepare_RW_RMW"; + cp_define_check->interface_num = 2; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + if (succ) + break; + else + thrd_yield(); + } + + rl::backoff bo; + while (true) { + + int read = m_read.load(mo_acquire); + /* Automatically generated code for potential commit point: Prepare_Potential_R_Load */ + + if (true) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 9; + potential_cp_define->label_name = "Prepare_Potential_R_Load"; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + if ((read & MASK) != rd) + thrd_yield(); + else + break; + } + + /* Automatically generated code for commit point define: Prepare_R_Load */ + + if (true) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 10; + cp_define->label_name = "Prepare_R_Load"; + cp_define->potential_cp_label_num = 9; + cp_define->potential_label_name = "Prepare_Potential_R_Load"; + cp_define->interface_num = 2; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + + t_element * p = & ( m_array[ wr % t_size ] ); + + return p; + } + + +void write_publish(t_element * bin) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 3; // Publish + interface_begin->interface_name = "Publish"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__write_publish(bin); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 3; // Publish + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Publish_info* info = (Publish_info*) malloc(sizeof(Publish_info)); + info->bin = bin; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 3; // Publish + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__write_publish(t_element * bin) + { + + int tmp = m_written.fetch_add(1,mo_release); + /* Automatically generated code for commit point define check: Publish_W_RMW */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 11; + cp_define_check->label_name = "Publish_W_RMW"; + cp_define_check->interface_num = 3; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + printf("publish: m_written=%d\n", tmp + 1); + } + + + +}; +template +void** mpmc_boundq_1_alt::func_ptr_table; +template +hb_rule** mpmc_boundq_1_alt::hb_rule_table; +template +commutativity_rule** mpmc_boundq_1_alt::commutativity_rule_table; + + diff --git a/output/mpmc-queue/mpmc-rdwr-noinit b/output/mpmc-queue/mpmc-rdwr-noinit new file mode 100755 index 0000000..0f12666 Binary files /dev/null and b/output/mpmc-queue/mpmc-rdwr-noinit differ diff --git a/output/mpmc-queue/testcase b/output/mpmc-queue/testcase new file mode 100755 index 0000000..5c9c9ad Binary files /dev/null and b/output/mpmc-queue/testcase differ diff --git a/output/mpmc-queue/testcase.cc b/output/mpmc-queue/testcase.cc new file mode 100644 index 0000000..936315c --- /dev/null +++ b/output/mpmc-queue/testcase.cc @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +#include + +#include "mpmc-queue.h" + +void threadA(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin; + bin = queue->write_prepare(); + if (bin) { + *bin = 1; + printf("write_bin %d, val %d\n", bin, 1); + queue->write_publish(bin); + } else { + printf("write failed\n"); + } +} + +void threadB(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin; + bin = queue->read_fetch(); + if (bin) { + printf("read_bin: %d, val %d\n", bin, *bin); + queue->read_consume(bin); + } else { + printf("Read failed\n"); + } +} + +int user_main(int argc, char **argv) +{ + struct mpmc_boundq_1_alt queue; + thrd_t A, B; + + printf("Adding initial element\n"); + int32_t *bin; + bin = queue.write_prepare(); + *bin = 17; + printf("init_write_bin %d, val %d\n", bin, 17); + queue.write_publish(bin); + + bin = queue.write_prepare(); + *bin = 27; + printf("init_write_bin %d, val %d\n", bin, 27); + queue.write_publish(bin); + + + printf("Start threads\n"); + + thrd_create(&A, (thrd_start_t)&threadA, &queue); + thrd_create(&B, (thrd_start_t)&threadB, &queue); + + thrd_join(A); + thrd_join(B); + printf("Threads complete\n"); + + return 0; +} + diff --git a/output/mpmc-queue/testcase1 b/output/mpmc-queue/testcase1 new file mode 100755 index 0000000..6d8a654 Binary files /dev/null and b/output/mpmc-queue/testcase1 differ diff --git a/output/mpmc-queue/testcase1.cc b/output/mpmc-queue/testcase1.cc new file mode 100644 index 0000000..936315c --- /dev/null +++ b/output/mpmc-queue/testcase1.cc @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +#include + +#include "mpmc-queue.h" + +void threadA(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin; + bin = queue->write_prepare(); + if (bin) { + *bin = 1; + printf("write_bin %d, val %d\n", bin, 1); + queue->write_publish(bin); + } else { + printf("write failed\n"); + } +} + +void threadB(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin; + bin = queue->read_fetch(); + if (bin) { + printf("read_bin: %d, val %d\n", bin, *bin); + queue->read_consume(bin); + } else { + printf("Read failed\n"); + } +} + +int user_main(int argc, char **argv) +{ + struct mpmc_boundq_1_alt queue; + thrd_t A, B; + + printf("Adding initial element\n"); + int32_t *bin; + bin = queue.write_prepare(); + *bin = 17; + printf("init_write_bin %d, val %d\n", bin, 17); + queue.write_publish(bin); + + bin = queue.write_prepare(); + *bin = 27; + printf("init_write_bin %d, val %d\n", bin, 27); + queue.write_publish(bin); + + + printf("Start threads\n"); + + thrd_create(&A, (thrd_start_t)&threadA, &queue); + thrd_create(&B, (thrd_start_t)&threadB, &queue); + + thrd_join(A); + thrd_join(B); + printf("Threads complete\n"); + + return 0; +} + diff --git a/output/mpmc-queue/testcase2 b/output/mpmc-queue/testcase2 new file mode 100755 index 0000000..59fdfe4 Binary files /dev/null and b/output/mpmc-queue/testcase2 differ diff --git a/output/mpmc-queue/testcase2.cc b/output/mpmc-queue/testcase2.cc new file mode 100644 index 0000000..a311400 --- /dev/null +++ b/output/mpmc-queue/testcase2.cc @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include + +#include + +#include "mpmc-queue.h" + +void threadA(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin; + + + for (int i = 0; i < 1; i++) { + bin = queue->write_prepare(); + if (bin) { + *bin = 1; + queue->write_publish(bin); + printf("write_bin %d, val %d\n", bin, 1); + } else { + printf("write failed\n"); + } + + bin = queue->read_fetch(); + if (bin) { + printf("read_bin: %d, val %d\n", bin, *bin); + queue->read_consume(bin); + } else { + printf("read failed\n"); + } + } + +} + +void threadB(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin; + for (int i = 0; i < 1; i++) { + bin = queue->read_fetch(); + if (bin) { + printf("read_bin: %d, val %d\n", bin, *bin); + queue->read_consume(bin); + } else { + printf("read failed\n"); + } + } + + +} + +int user_main(int argc, char **argv) +{ + struct mpmc_boundq_1_alt queue; + thrd_t A, A1, B; + + printf("Adding initial element\n"); + int32_t *bin; + for (int i = 0; i < 1; i++) { + printf("#%d, \n", i); + bin = queue.write_prepare(); + *bin = 17; + printf("init_write_bin %d, val %d\n", bin, 17); + queue.write_publish(bin); + + bin = queue.read_fetch(); + if (bin) { + printf("init_read: %d, val %d\n", bin, *bin); + queue.read_consume(bin); + } + } + + for (int i = 0; i < 3; i++) { + + } + + printf("Start threads\n"); + + thrd_create(&A, (thrd_start_t)&threadA, &queue); + thrd_create(&A1, (thrd_start_t)&threadA, &queue); + thrd_create(&B, (thrd_start_t)&threadB, &queue); + + thrd_join(A); + thrd_join(A1); + thrd_join(B); + printf("Threads complete\n"); + + return 0; +} + diff --git a/output/mpmc-queue/testcase3 b/output/mpmc-queue/testcase3 new file mode 100755 index 0000000..f0939b9 Binary files /dev/null and b/output/mpmc-queue/testcase3 differ diff --git a/output/mpmc-queue/testcase3.cc b/output/mpmc-queue/testcase3.cc new file mode 100644 index 0000000..fc91497 --- /dev/null +++ b/output/mpmc-queue/testcase3.cc @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include + +#include + +#include "mpmc-queue.h" + +void threadA(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin; + + + for (int i = 0; i < 1; i++) { + bin = queue->write_prepare(); + if (bin) { + *bin = 1; + queue->write_publish(bin); + printf("write_bin %d, val %d\n", bin, 1); + } else { + printf("write failed\n"); + } + + bin = queue->read_fetch(); + if (bin) { + printf("read_bin: %d, val %d\n", bin, *bin); + queue->read_consume(bin); + } else { + printf("read failed\n"); + } + } + +} + +void threadB(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin; + for (int i = 0; i < 1; i++) { + bin = queue->read_fetch(); + if (bin) { + printf("read_bin: %d, val %d\n", bin, *bin); + queue->read_consume(bin); + } else { + printf("read failed\n"); + } + } + + +} + +void threadC(struct mpmc_boundq_1_alt *queue) +{ + int *bin; + bin = queue->write_prepare(); + if (bin) { + *bin = 1; + queue->write_publish(bin); + printf("write_bin %d, val %d\n", bin, 1); + } else { + printf("write failed\n"); + } +} + +int user_main(int argc, char **argv) +{ + struct mpmc_boundq_1_alt queue; + thrd_t A, A1, B, B1, C, C1; + + printf("Adding initial element\n"); + int32_t *bin; + for (int i = 0; i < 0; i++) { + printf("#%d, \n", i); + bin = queue.write_prepare(); + *bin = 17; + printf("init_write_bin %d, val %d\n", bin, 17); + queue.write_publish(bin); + + } + + for (int i = 0; i < 3; i++) { + + } + + printf("Start threads\n"); + + thrd_create(&A, (thrd_start_t)&threadB, &queue); + thrd_create(&A1, (thrd_start_t)&threadC, &queue); + thrd_create(&B, (thrd_start_t)&threadB, &queue); + thrd_create(&B1, (thrd_start_t)&threadC, &queue); + thrd_create(&C, (thrd_start_t)&threadB, &queue); + thrd_create(&C1, (thrd_start_t)&threadC, &queue); + + thrd_join(A); + thrd_join(A1); + thrd_join(B); + thrd_join(B1); + thrd_join(C); + thrd_join(C1); + printf("Threads complete\n"); + + return 0; +} + diff --git a/output/ms-queue/Makefile b/output/ms-queue/Makefile index 78ea6a6..d75881c 100644 --- a/output/ms-queue/Makefile +++ b/output/ms-queue/Makefile @@ -1,6 +1,6 @@ include ../benchmarks.mk -TESTNAME = main testcase1 testcase2 +TESTNAME = main testcase1 testcase2 testcase3 HEADERS = my_queue.h OBJECTS = main.o my_queue.o @@ -16,6 +16,9 @@ testcase1: $(HEADERS) my_queue.o testcase1.o testcase2: $(HEADERS) my_queue.o testcase2.o $(CC) -o $@ my_queue.o testcase2.o $(CFLAGS) $(LDFLAGS) +testcase3: $(HEADERS) my_queue.o testcase3.o + $(CC) -o $@ my_queue.o testcase3.o $(CFLAGS) $(LDFLAGS) + %.o: %.c $(CC) -c -o $@ $< $(CFLAGS) diff --git a/output/ms-queue/main b/output/ms-queue/main new file mode 100755 index 0000000..0621f42 Binary files /dev/null and b/output/ms-queue/main differ diff --git a/output/ms-queue/main.c b/output/ms-queue/main.c new file mode 100644 index 0000000..e5cbd07 --- /dev/null +++ b/output/ms-queue/main.c @@ -0,0 +1,88 @@ +#include +#include +#include + +#include "my_queue.h" +#include "model-assert.h" + +static int procs = 2; +static queue_t *queue; +static thrd_t *threads; +static unsigned int *input; +static unsigned int *output; +static int num_threads; + +int get_thread_num() +{ + thrd_t curr = thrd_current(); + int i; + for (i = 0; i < num_threads; i++) + if (curr.priv == threads[i].priv) + return i; + return -1; +} + +bool succ1, succ2; + +static void main_task(void *param) +{ + + unsigned int val; + int pid = *((int *)param); + + if (pid % 2 == 0) { + input[0] = 17; + enqueue(queue, input[0]); + printf("Thrd %d Enqueue %d.\n", get_thread_num(), input[0]); + + succ1 = dequeue(queue, &output[0]); + if (succ1) + printf("Thrd %d: Dequeue %d.\n", get_thread_num(), output[0]); + else + printf("Thrd %d: Dequeue NULL.\n", get_thread_num()); + + } else if (pid % 2 == 1) { + input[1] = 37; + enqueue(queue, input[1]); + printf("Thrd %d Enqueue %d.\n", get_thread_num(), input[1]); + + succ2 = dequeue(queue, &output[1]); + if (succ2) + printf("Thrd %d: Dequeue %d.\n", get_thread_num(), output[1]); + else + printf("Thrd %d: Dequeue NULL.\n", get_thread_num()); + } +} + +int user_main(int argc, char **argv) +{ + __sequential_init(); + + int i; + int *param; + unsigned int in_sum = 0, out_sum = 0; + + queue = calloc(1, sizeof(*queue)); + + num_threads = procs; + threads = malloc(num_threads * sizeof(thrd_t)); + param = malloc(num_threads * sizeof(*param)); + input = calloc(num_threads, sizeof(*input)); + output = calloc(num_threads, sizeof(*output)); + + init_queue(queue, num_threads); + for (i = 0; i < num_threads; i++) { + param[i] = i; + thrd_create(&threads[i], main_task, ¶m[i]); + } + for (i = 0; i < num_threads; i++) + thrd_join(threads[i]); + + + free(param); + free(threads); + free(queue); + + return 0; +} + diff --git a/output/ms-queue/main.o b/output/ms-queue/main.o new file mode 100644 index 0000000..b1618c1 Binary files /dev/null and b/output/ms-queue/main.o differ diff --git a/output/ms-queue/my_queue.c b/output/ms-queue/my_queue.c new file mode 100644 index 0000000..1a09033 --- /dev/null +++ b/output/ms-queue/my_queue.c @@ -0,0 +1,333 @@ +#include +#include +#include "librace.h" +#include "model-assert.h" + +#include "my_queue.h" + +#define relaxed memory_order_relaxed +#define release memory_order_release +#define acquire memory_order_acquire + +#define MAX_FREELIST 4 +#define INITIAL_FREE 3 + +#define POISON_IDX 0x666 + +static unsigned int (*free_lists)[MAX_FREELIST]; + + +static unsigned int new_node() +{ + int i; + int t = get_thread_num(); + for (i = 0; i < MAX_FREELIST; i++) { + unsigned int node = free_lists[t][i]; + if (node) { + free_lists[t][i] = 0; + return node; + } + } + + return 0; +} + + +static void reclaim(unsigned int node) +{ + int i; + int t = get_thread_num(); + + + + for (i = 0; i < MAX_FREELIST; i++) { + + unsigned int idx = free_lists[t][i]; + + + if (idx == 0) { + store_32(&free_lists[t][i], node); + return; + } + } + + } + +void init_queue(queue_t *q, int num_threads) +{ + int i, j; + for (i = 0; i < MAX_NODES; i++) { + atomic_init(&q->nodes[i].next, MAKE_POINTER(POISON_IDX, 0)); + } + + + + free_lists = malloc(num_threads * sizeof(*free_lists)); + for (i = 0; i < num_threads; i++) { + for (j = 0; j < INITIAL_FREE; j++) { + free_lists[i][j] = 2 + i * MAX_FREELIST + j; + atomic_init(&q->nodes[free_lists[i][j]].next, MAKE_POINTER(POISON_IDX, 0)); + } + } + + + atomic_init(&q->head, MAKE_POINTER(1, 0)); + atomic_init(&q->tail, MAKE_POINTER(1, 0)); + atomic_init(&q->nodes[1].next, MAKE_POINTER(0, 0)); +} + + +void enqueue(queue_t * q, unsigned int val) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 0; // Enqueue + interface_begin->interface_name = "Enqueue"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__enqueue(q, val); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 0; // Enqueue + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Enqueue_info* info = (Enqueue_info*) malloc(sizeof(Enqueue_info)); + info->q = q; + info->val = val; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 0; // Enqueue + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__enqueue(queue_t * q, unsigned int val) +{ + int success = 0; + unsigned int node; + pointer tail; + pointer next; + pointer tmp; + + node = new_node(); + q->nodes[node].value = val; + tmp = atomic_load_explicit(&q->nodes[node].next, relaxed); + set_ptr(&tmp, 0); atomic_store_explicit(&q->nodes[node].next, tmp, relaxed); + + while (!success) { + + /* Automatically generated code for commit point clear: Enqueue_Clear */ + + if (true) { + struct anno_cp_clear *cp_clear = (struct anno_cp_clear*) malloc(sizeof(struct anno_cp_clear)); + cp_clear->label_name = "Enqueue_Clear"; + cp_clear->label_num = 0; + struct spec_annotation *annotation_cp_clear = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_clear->type = CP_CLEAR; + annotation_cp_clear->annotation = cp_clear; + cdsannotate(SPEC_ANALYSIS, annotation_cp_clear); + } + + + tail = atomic_load_explicit(&q->tail, acquire); + + next = atomic_load_explicit(&q->nodes[get_ptr(tail)].next, acquire); + if (tail == atomic_load_explicit(&q->tail, relaxed)) { + + + + if (get_ptr(next) == 0) { pointer value = MAKE_POINTER(node, get_count(next) + 1); + + success = atomic_compare_exchange_strong_explicit(&q->nodes[get_ptr(tail)].next, + &next, value, release, relaxed); + /* Automatically generated code for commit point define check: EnqueueUpdateNext */ + + if (success) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 1; + cp_define_check->label_name = "EnqueueUpdateNext"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + } + if (!success) { + + unsigned int ptr = get_ptr(atomic_load_explicit(&q->nodes[get_ptr(tail)].next, acquire)); + pointer value = MAKE_POINTER(ptr, + get_count(tail) + 1); + + bool succ = false; + succ = atomic_compare_exchange_strong_explicit(&q->tail, + &tail, value, relaxed, relaxed); + if (succ) { + } + thrd_yield(); + } + } + } + + bool succ = atomic_compare_exchange_strong_explicit(&q->tail, + &tail, + MAKE_POINTER(node, get_count(tail) + 1), + release, relaxed); +} + + +bool dequeue(queue_t * q, int * retVal) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 1; // Dequeue + interface_begin->interface_name = "Dequeue"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + bool __RET__ = __wrapper__dequeue(q, retVal); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 1; // Dequeue + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Dequeue_info* info = (Dequeue_info*) malloc(sizeof(Dequeue_info)); + info->__RET__ = __RET__; + info->q = q; + info->retVal = retVal; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 1; // Dequeue + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +bool __wrapper__dequeue(queue_t * q, int * retVal) +{ + unsigned int value = 0; + int success = 0; + pointer head; + pointer tail; + pointer next; + + while (!success) { + /* Automatically generated code for commit point clear: Dequeue_Clear */ + + if (true) { + struct anno_cp_clear *cp_clear = (struct anno_cp_clear*) malloc(sizeof(struct anno_cp_clear)); + cp_clear->label_name = "Dequeue_Clear"; + cp_clear->label_num = 2; + struct spec_annotation *annotation_cp_clear = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_clear->type = CP_CLEAR; + annotation_cp_clear->annotation = cp_clear; + cdsannotate(SPEC_ANALYSIS, annotation_cp_clear); + } + + + head = atomic_load_explicit(&q->head, acquire); + /* Automatically generated code for commit point define check: DequeueReadHead */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 3; + cp_define_check->label_name = "DequeueReadHead"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + + + + tail = atomic_load_explicit(&q->tail, acquire); + + + next = atomic_load_explicit(&q->nodes[get_ptr(head)].next, acquire); + /* Automatically generated code for potential commit point: DequeueReadNext */ + + if (true) { + struct anno_potential_cp_define *potential_cp_define = (struct anno_potential_cp_define*) malloc(sizeof(struct anno_potential_cp_define)); + potential_cp_define->label_num = 4; + potential_cp_define->label_name = "DequeueReadNext"; + struct spec_annotation *annotation_potential_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_potential_cp_define->type = POTENTIAL_CP_DEFINE; + annotation_potential_cp_define->annotation = potential_cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_potential_cp_define); + } + + if (atomic_load_explicit(&q->head, relaxed) == head) { + if (get_ptr(head) == get_ptr(tail)) { + + + + if (get_ptr(next) == 0) { return false; } + + bool succ = false; + succ = atomic_compare_exchange_strong_explicit(&q->tail, + &tail, + MAKE_POINTER(get_ptr(next), get_count(tail) + 1), + release, relaxed); + if (succ) { + } + thrd_yield(); + } else { + value = q->nodes[get_ptr(next)].value; + + success = atomic_compare_exchange_strong_explicit(&q->head, + &head, + MAKE_POINTER(get_ptr(next), get_count(head) + 1), + release, relaxed); + /* Automatically generated code for commit point define check: DequeueUpdateHead */ + + if (success) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 5; + cp_define_check->label_name = "DequeueUpdateHead"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + + /* Automatically generated code for commit point define: DequeueReadNextVerify */ + + if (success) { + struct anno_cp_define *cp_define = (struct anno_cp_define*) malloc(sizeof(struct anno_cp_define)); + cp_define->label_num = 6; + cp_define->label_name = "DequeueReadNextVerify"; + cp_define->potential_cp_label_num = 4; + cp_define->potential_label_name = "DequeueReadNext"; + cp_define->interface_num = 1; + struct spec_annotation *annotation_cp_define = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define->type = CP_DEFINE; + annotation_cp_define->annotation = cp_define; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define); + } + + if (!success) + thrd_yield(); + } + } + } + reclaim(get_ptr(head)); + *retVal = value; + return true; +} + diff --git a/output/ms-queue/my_queue.h b/output/ms-queue/my_queue.h new file mode 100644 index 0000000..90849d8 --- /dev/null +++ b/output/ms-queue/my_queue.h @@ -0,0 +1,204 @@ +#ifndef _MY_QUEUE_H +#define _MY_QUEUE_H + +#include + +#include +#include +#include +#include +#include +#include "common.h" + +#define MAX_NODES 0xf + +typedef unsigned long long pointer; +typedef atomic_ullong pointer_t; + +#define MAKE_POINTER(ptr, count) ((((pointer)count) << 32) | ptr) +#define PTR_MASK 0xffffffffLL +#define COUNT_MASK (0xffffffffLL << 32) + +static inline void set_count(pointer *p, unsigned int val) { *p = (*p & ~COUNT_MASK) | ((pointer)val << 32); } +static inline void set_ptr(pointer *p, unsigned int val) { *p = (*p & ~PTR_MASK) | val; } +static inline unsigned int get_count(pointer p) { return (p & COUNT_MASK) >> 32; } +static inline unsigned int get_ptr(pointer p) { return p & PTR_MASK; } + +typedef struct node { + unsigned int value; + pointer_t next; +} node_t; + +typedef struct { + pointer_t head; + pointer_t tail; + node_t nodes[MAX_NODES + 1]; +} queue_t; + +void init_queue(queue_t *q, int num_threads); + +/* All other user-defined structs */ +static IntegerList * __queue; +/* All other user-defined functions */ +/* Definition of interface info struct: Dequeue */ +typedef struct Dequeue_info { +bool __RET__; +queue_t * q; +int * retVal; +} Dequeue_info; +/* End of info struct definition: Dequeue */ + +/* ID function of interface: Dequeue */ +inline static call_id_t Dequeue_id(void *info, thread_id_t __TID__) { + Dequeue_info* theInfo = (Dequeue_info*)info; + bool __RET__ = theInfo->__RET__; + queue_t * q = theInfo->q; + int * retVal = theInfo->retVal; + + call_id_t __ID__ = __RET__ ? * retVal : 0; + return __ID__; +} +/* End of ID function: Dequeue */ + +/* Check action function of interface: Dequeue */ +inline static bool Dequeue_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Dequeue_info* theInfo = (Dequeue_info*)info; + bool __RET__ = theInfo->__RET__; + queue_t * q = theInfo->q; + int * retVal = theInfo->retVal; + + int elem = 0 ; + if ( __RET__ ) { + elem = front ( __queue ) ; + pop_front ( __queue ) ; + } + check_passed = __RET__ ? * retVal == elem : true; + if (!check_passed) + return false; + return true; +} +/* End of check action function: Dequeue */ + +/* Definition of interface info struct: Enqueue */ +typedef struct Enqueue_info { +queue_t * q; + unsigned int val; +} Enqueue_info; +/* End of info struct definition: Enqueue */ + +/* ID function of interface: Enqueue */ +inline static call_id_t Enqueue_id(void *info, thread_id_t __TID__) { + Enqueue_info* theInfo = (Enqueue_info*)info; + queue_t * q = theInfo->q; + unsigned int val = theInfo->val; + + call_id_t __ID__ = val; + return __ID__; +} +/* End of ID function: Enqueue */ + +/* Check action function of interface: Enqueue */ +inline static bool Enqueue_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Enqueue_info* theInfo = (Enqueue_info*)info; + queue_t * q = theInfo->q; + unsigned int val = theInfo->val; + + push_back ( __queue , val ) ; + return true; +} +/* End of check action function: Enqueue */ + +#define INTERFACE_SIZE 2 +static void** func_ptr_table; +static hb_rule** hb_rule_table; +static commutativity_rule** commutativity_rule_table; +inline static bool CommutativityCondition0(void *info1, void *info2) { + Enqueue_info *_info1 = (Enqueue_info*) info1; + Dequeue_info *_info2 = (Dequeue_info*) info2; + return true; +} +inline static bool CommutativityCondition1(void *info1, void *info2) { + Dequeue_info *_info1 = (Dequeue_info*) info1; + Dequeue_info *_info2 = (Dequeue_info*) info2; + return ! _info1-> __RET__ || ! _info2-> __RET__; +} + +/* Initialization of sequential varialbes */ +static void __SPEC_INIT__() { + __queue = createIntegerList ( ) ; +} + +/* Cleanup routine of sequential variables */ +static bool __SPEC_CLEANUP__() { + if ( __queue ) destroyIntegerList ( __queue ) ; + return true ; +} + +/* Define function for sequential code initialization */ +inline static void __sequential_init() { + /* Init func_ptr_table */ + func_ptr_table = (void**) malloc(sizeof(void*) * 2 * 2); + func_ptr_table[2 * 1] = (void*) &Dequeue_id; + func_ptr_table[2 * 1 + 1] = (void*) &Dequeue_check_action; + func_ptr_table[2 * 0] = (void*) &Enqueue_id; + func_ptr_table[2 * 0 + 1] = (void*) &Enqueue_check_action; + /* Enqueue(true) -> Dequeue(true) */ + struct hb_rule *hbConditionInit0 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit0->interface_num_before = 0; // Enqueue + hbConditionInit0->hb_condition_num_before = 0; // + hbConditionInit0->interface_num_after = 1; // Dequeue + hbConditionInit0->hb_condition_num_after = 0; // + /* Init hb_rule_table */ + hb_rule_table = (hb_rule**) malloc(sizeof(hb_rule*) * 1); + #define HB_RULE_TABLE_SIZE 1 + hb_rule_table[0] = hbConditionInit0; + /* Init commutativity_rule_table */ + commutativity_rule_table = (commutativity_rule**) malloc(sizeof(commutativity_rule*) * 2); + commutativity_rule* rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 1; + rule->rule = "true"; + rule->condition = CommutativityCondition0; + commutativity_rule_table[0] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 1; + rule->interface_num_after = 1; + rule->rule = "! _Method1 . __RET__ || ! _Method2 . __RET__"; + rule->condition = CommutativityCondition1; + commutativity_rule_table[1] = rule; + /* Pass init info, including function table info & HB rules & Commutativity Rules */ + struct anno_init *anno_init = (struct anno_init*) malloc(sizeof(struct anno_init)); + anno_init->init_func = (void_func_t) __SPEC_INIT__; + anno_init->cleanup_func = (cleanup_func_t) __SPEC_CLEANUP__; + anno_init->func_table = func_ptr_table; + anno_init->func_table_size = INTERFACE_SIZE; + anno_init->hb_rule_table = hb_rule_table; + anno_init->hb_rule_table_size = HB_RULE_TABLE_SIZE; + anno_init->commutativity_rule_table = commutativity_rule_table; + anno_init->commutativity_rule_table_size = 2; + struct spec_annotation *init = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + init->type = INIT; + init->annotation = anno_init; + cdsannotate(SPEC_ANALYSIS, init); + +} + +/* End of Global construct generation in class */ + + + + +void __wrapper__enqueue(queue_t * q, unsigned int val); + +void __wrapper__enqueue(queue_t * q, unsigned int val) ; + +bool __wrapper__dequeue(queue_t * q, int * retVal); + +bool __wrapper__dequeue(queue_t * q, int * retVal) ; +int get_thread_num(); + +#endif + diff --git a/output/ms-queue/my_queue.o b/output/ms-queue/my_queue.o new file mode 100644 index 0000000..b35d4c9 Binary files /dev/null and b/output/ms-queue/my_queue.o differ diff --git a/output/ms-queue/testcase1 b/output/ms-queue/testcase1 new file mode 100755 index 0000000..35c5e69 Binary files /dev/null and b/output/ms-queue/testcase1 differ diff --git a/output/ms-queue/testcase1.o b/output/ms-queue/testcase1.o new file mode 100644 index 0000000..d55a3eb Binary files /dev/null and b/output/ms-queue/testcase1.o differ diff --git a/output/ms-queue/testcase2 b/output/ms-queue/testcase2 new file mode 100755 index 0000000..8a4c860 Binary files /dev/null and b/output/ms-queue/testcase2 differ diff --git a/output/ms-queue/testcase2.c b/output/ms-queue/testcase2.c index f5b2133..116df35 100644 --- a/output/ms-queue/testcase2.c +++ b/output/ms-queue/testcase2.c @@ -5,7 +5,7 @@ #include "my_queue.h" #include "model-assert.h" -static int procs = 2; +static int procs = 3; static queue_t *queue; static thrd_t *threads; static unsigned int *input; @@ -37,13 +37,9 @@ static void main_task(void *param) else printf("Thrd 1: Dequeue NULL.\n"); } else if (pid % 4 == 1) { + enqueue(queue, 1); + } else if (pid % 4 == 2) { enqueue(queue, 2); - output2 = 1; - succ2 = dequeue(queue, &output2); - if (succ2) - printf("Thrd 2: Dequeue %d.\n", output2); - else - printf("Thrd 2: Dequeue NULL.\n"); } } diff --git a/output/ms-queue/testcase2.o b/output/ms-queue/testcase2.o new file mode 100644 index 0000000..8a45d38 Binary files /dev/null and b/output/ms-queue/testcase2.o differ diff --git a/output/ms-queue/testcase3 b/output/ms-queue/testcase3 new file mode 100755 index 0000000..9c35f67 Binary files /dev/null and b/output/ms-queue/testcase3 differ diff --git a/output/ms-queue/testcase3.c b/output/ms-queue/testcase3.c new file mode 100644 index 0000000..e4fb362 --- /dev/null +++ b/output/ms-queue/testcase3.c @@ -0,0 +1,84 @@ +#include +#include +#include + +#include "my_queue.h" +#include "model-assert.h" + +static int procs = 3; +static queue_t *queue; +static thrd_t *threads; +static unsigned int *input; +static unsigned int *output; +static int num_threads; + +int get_thread_num() +{ + thrd_t curr = thrd_current(); + int i; + for (i = 0; i < num_threads; i++) + if (curr.priv == threads[i].priv) + return i; + return -1; +} + + +bool succ1, succ2; +unsigned int output1, output2; + +static void main_task(void *param) +{ + int pid = *((int *)param); + if (pid % 4 == 0) { + output1 = 1; + succ1 = dequeue(queue, &output1); + if (succ1) + printf("Thrd 1: Dequeue %d.\n", output1); + else + printf("Thrd 1: Dequeue NULL.\n"); + } else if (pid % 4 == 1) { + enqueue(queue, 1); + printf("Thrd 2: Enqueue %d.\n", 1); + } else if (pid % 4 == 2) { + + output1 = 1; + succ1 = dequeue(queue, &output1); + if (succ1) + printf("Thrd 3: Dequeue %d.\n", output1); + else + printf("Thrd 3: Dequeue NULL.\n"); + } +} + +int user_main(int argc, char **argv) +{ + __sequential_init(); + + int i; + int *param; + unsigned int in_sum = 0, out_sum = 0; + + queue = calloc(1, sizeof(*queue)); + + num_threads = procs; + threads = malloc(num_threads * sizeof(thrd_t)); + param = malloc(num_threads * sizeof(*param)); + input = calloc(num_threads, sizeof(*input)); + output = calloc(num_threads, sizeof(*output)); + + init_queue(queue, num_threads); + for (i = 0; i < num_threads; i++) { + param[i] = i; + thrd_create(&threads[i], main_task, ¶m[i]); + } + for (i = 0; i < num_threads; i++) + thrd_join(threads[i]); + + + free(param); + free(threads); + free(queue); + + return 0; +} + diff --git a/output/ms-queue/testcase3.o b/output/ms-queue/testcase3.o new file mode 100644 index 0000000..3dff7b1 Binary files /dev/null and b/output/ms-queue/testcase3.o differ diff --git a/output/read-copy-update/rcu b/output/read-copy-update/rcu new file mode 100755 index 0000000..8e26721 Binary files /dev/null and b/output/read-copy-update/rcu differ diff --git a/output/read-copy-update/rcu.cc b/output/read-copy-update/rcu.cc new file mode 100644 index 0000000..adc4766 --- /dev/null +++ b/output/read-copy-update/rcu.cc @@ -0,0 +1,352 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "common.h" + +#include "librace.h" + + + +typedef struct Data { + int data1; + int data2; +} Data; + +atomic data; + +/* All other user-defined structs */ +static IntegerList * set; +/* All other user-defined functions */ +inline static call_id_t getID ( int64_t d1 , int64_t d2 ) { +return d1 + d2 ; +} + +inline static bool print ( int64_t p ) { +Data * d = ( Data * ) p ; +model_print ( "Elem-> d1 = %d, d2 = %d\n" , d -> data1 , d -> data2 ) ; +} +bool equal ( int64_t p1 , int64_t p2 ) { +if ( ! p1 || ! p2 ) return false ; +Data * d1 = ( Data * ) p1 ; +Data * d2 = ( Data * ) p2 ; +if ( d1 -> data1 == d2 -> data1 && d1 -> data2 == d2 -> data2 ) { +return true ; +} +else { +return false ; +} +} + +inline static void _write ( int64_t d1 , int64_t d2 ) { +Data * d = ( Data * ) MODEL_MALLOC ( sizeof ( Data ) ) ; +d -> data1 = d1 ; +d -> data2 = d2 ; +push_back ( set , ( int64_t ) d ) ; +} + +inline static bool _read ( Data * res ) { +bool hasElem = has_elem_by_value ( set , ( int64_t ) res , & equal ) ; +return hasElem ; +} + +/* Definition of interface info struct: Write */ +typedef struct Write_info { +Data * __RET__; +int d1; +int d2; +} Write_info; +/* End of info struct definition: Write */ + +/* ID function of interface: Write */ +inline static call_id_t Write_id(void *info, thread_id_t __TID__) { + Write_info* theInfo = (Write_info*)info; + Data * __RET__ = theInfo->__RET__; + int d1 = theInfo->d1; + int d2 = theInfo->d2; + + call_id_t __ID__ = getID ( d1 , d2 ) ;; + return __ID__; +} +/* End of ID function: Write */ + +/* Check action function of interface: Write */ +inline static bool Write_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Write_info* theInfo = (Write_info*)info; + Data * __RET__ = theInfo->__RET__; + int d1 = theInfo->d1; + int d2 = theInfo->d2; + + _write ( d1 , d2 ) ; + return true; +} +/* End of check action function: Write */ + +/* Definition of interface info struct: Read */ +typedef struct Read_info { +Data * __RET__; +} Read_info; +/* End of info struct definition: Read */ + +/* ID function of interface: Read */ +inline static call_id_t Read_id(void *info, thread_id_t __TID__) { + Read_info* theInfo = (Read_info*)info; + Data * __RET__ = theInfo->__RET__; + + call_id_t __ID__ = getID ( __RET__ -> data1 , __RET__ -> data2 ); + return __ID__; +} +/* End of ID function: Read */ + +/* Check action function of interface: Read */ +inline static bool Read_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Read_info* theInfo = (Read_info*)info; + Data * __RET__ = theInfo->__RET__; + + check_passed = _read ( __RET__ ) ;; + if (!check_passed) + return false; + return true; +} +/* End of check action function: Read */ + +#define INTERFACE_SIZE 2 +static void** func_ptr_table; +static hb_rule** hb_rule_table; +static commutativity_rule** commutativity_rule_table; +inline static bool CommutativityCondition0(void *info1, void *info2) { + Write_info *_info1 = (Write_info*) info1; + Read_info *_info2 = (Read_info*) info2; + return true; +} + +/* Initialization of sequential varialbes */ +static void __SPEC_INIT__() { + set = createIntegerList ( ) ; + Data * d = ( Data * ) MODEL_MALLOC ( sizeof ( Data ) ) ; + d -> data1 = 0 ; + d -> data2 = 0 ; + push_back ( set , ( int64_t ) d ) ; +} + +/* Cleanup routine of sequential variables */ +static bool __SPEC_CLEANUP__() { + if ( set ) destroyIntegerList ( set ) ; + return true ; +} + +/* Define function for sequential code initialization */ +inline static void __sequential_init() { + /* Init func_ptr_table */ + func_ptr_table = (void**) malloc(sizeof(void*) * 2 * 2); + func_ptr_table[2 * 1] = (void*) &Write_id; + func_ptr_table[2 * 1 + 1] = (void*) &Write_check_action; + func_ptr_table[2 * 0] = (void*) &Read_id; + func_ptr_table[2 * 0 + 1] = (void*) &Read_check_action; + /* Write(true) -> Read(true) */ + struct hb_rule *hbConditionInit0 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit0->interface_num_before = 1; // Write + hbConditionInit0->hb_condition_num_before = 0; // + hbConditionInit0->interface_num_after = 0; // Read + hbConditionInit0->hb_condition_num_after = 0; // + /* Write(true) -> Write(true) */ + struct hb_rule *hbConditionInit1 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit1->interface_num_before = 1; // Write + hbConditionInit1->hb_condition_num_before = 0; // + hbConditionInit1->interface_num_after = 1; // Write + hbConditionInit1->hb_condition_num_after = 0; // + /* Init hb_rule_table */ + hb_rule_table = (hb_rule**) malloc(sizeof(hb_rule*) * 2); + #define HB_RULE_TABLE_SIZE 2 + hb_rule_table[0] = hbConditionInit0; + hb_rule_table[1] = hbConditionInit1; + /* Init commutativity_rule_table */ + commutativity_rule_table = (commutativity_rule**) malloc(sizeof(commutativity_rule*) * 1); + commutativity_rule* rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 1; + rule->interface_num_after = 0; + rule->rule = "true"; + rule->condition = CommutativityCondition0; + commutativity_rule_table[0] = rule; + /* Pass init info, including function table info & HB rules & Commutativity Rules */ + struct anno_init *anno_init = (struct anno_init*) malloc(sizeof(struct anno_init)); + anno_init->init_func = (void_func_t) __SPEC_INIT__; + anno_init->cleanup_func = (cleanup_func_t) __SPEC_CLEANUP__; + anno_init->func_table = func_ptr_table; + anno_init->func_table_size = INTERFACE_SIZE; + anno_init->hb_rule_table = hb_rule_table; + anno_init->hb_rule_table_size = HB_RULE_TABLE_SIZE; + anno_init->commutativity_rule_table = commutativity_rule_table; + anno_init->commutativity_rule_table_size = 1; + struct spec_annotation *init = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + init->type = INIT; + init->annotation = anno_init; + cdsannotate(SPEC_ANALYSIS, init); + +} + +/* End of Global construct generation in class */ + + +Data * __wrapper__read(); + +Data * read() { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 0; // Read + interface_begin->interface_name = "Read"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + Data * __RET__ = __wrapper__read(); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 0; // Read + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Read_info* info = (Read_info*) malloc(sizeof(Read_info)); + info->__RET__ = __RET__; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 0; // Read + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +Data * __wrapper__read() { + + Data *res = data.load(memory_order_acquire); + /* Automatically generated code for commit point define check: Read_Success_Point */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 0; + cp_define_check->label_name = "Read_Success_Point"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + return res; +} + +Data * __wrapper__write(int d1, int d2); + +Data * write(int d1, int d2) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 1; // Write + interface_begin->interface_name = "Write"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + Data * __RET__ = __wrapper__write(d1, d2); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 1; // Write + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Write_info* info = (Write_info*) malloc(sizeof(Write_info)); + info->__RET__ = __RET__; + info->d1 = d1; + info->d2 = d2; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 1; // Write + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +Data * __wrapper__write(int d1, int d2) { + bool succ = false; + Data *tmp = (Data*) malloc(sizeof(Data)); + do { + + Data *prev = data.load(memory_order_acquire); + tmp->data1 = d1; + tmp->data2 = d2; + + succ = data.compare_exchange_strong(prev, tmp, + memory_order_release, memory_order_relaxed); + /* Automatically generated code for commit point define check: Write_Success_Point */ + + if (succ) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 1; + cp_define_check->label_name = "Write_Success_Point"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + } while (!succ); + return tmp; +} + + +void threadA(void *arg) { + write(1, 0); +} + +void threadB(void *arg) { + write(0, 2); +} + +void threadC(void *arg) { + write(2, 2); +} + +void threadD(void *arg) { + Data *d = read(); + printf("ThreadD: d1=%d, d2=%d\n", d->data1, d->data2); +} + +int user_main(int argc, char **argv) { + __sequential_init(); + + + thrd_t t1, t2, t3, t4; + Data *dataInit = (Data*) malloc(sizeof(Data)); + dataInit->data1 = 0; + dataInit->data2 = 0; + atomic_init(&data, dataInit); + + thrd_create(&t1, threadA, NULL); + thrd_create(&t2, threadB, NULL); + thrd_create(&t4, threadD, NULL); + + thrd_join(t1); + thrd_join(t2); + thrd_join(t4); + + return 0; +} + diff --git a/output/spsc-bugfix/eventcount.h b/output/spsc-bugfix/eventcount.h new file mode 100644 index 0000000..a7dd1ee --- /dev/null +++ b/output/spsc-bugfix/eventcount.h @@ -0,0 +1,74 @@ +#ifndef _EVENTCOUNT_H +#define _EVENTCOUNT_H + +#include +#include +#include + +class eventcount +{ +public: + eventcount() : waiters(0) + { + count = 0; + } + + void signal_relaxed() + { + unsigned cmp = count.load(std::memory_order_relaxed); + signal_impl(cmp); + } + + void signal() + { + unsigned cmp = count.fetch_add(0, std::memory_order_seq_cst); + signal_impl(cmp); + } + + unsigned get() + { + unsigned cmp = count.fetch_or(0x80000000, +std::memory_order_seq_cst); + return cmp & 0x7FFFFFFF; + } + + void wait(unsigned cmp) + { + unsigned ec = count.load(std::memory_order_seq_cst); + if (cmp == (ec & 0x7FFFFFFF)) + { + guard.lock($); + ec = count.load(std::memory_order_seq_cst); + if (cmp == (ec & 0x7FFFFFFF)) + { + waiters += 1; + cv.wait(guard); + } + guard.unlock($); + } + } + +private: + std::atomic count; + rl::var waiters; + std::mutex guard; + std::condition_variable cv; + + void signal_impl(unsigned cmp) + { + if (cmp & 0x80000000) + { + guard.lock($); + while (false == count.compare_exchange_weak(cmp, + (cmp + 1) & 0x7FFFFFFF, std::memory_order_relaxed)); + unsigned w = waiters($); + waiters = 0; + guard.unlock($); + if (w) + cv.notify_all($); + } + } +}; + +#endif + diff --git a/output/spsc-bugfix/queue.h b/output/spsc-bugfix/queue.h new file mode 100644 index 0000000..456b7d1 --- /dev/null +++ b/output/spsc-bugfix/queue.h @@ -0,0 +1,340 @@ +#ifndef _QUEUE_H +#define _QUEUE_H + +#include +#include + +#include +#include +#include +#include +#include +#include "common.h" + +#include "eventcount.h" + + +template +class spsc_queue +{ + +public: + + + spsc_queue() + { + + __sequential_init(); + + + node* n = new node (); + head = n; + tail = n; + } + + ~spsc_queue() + { + delete ((node*)head); + } + +/* All other user-defined structs */ +static IntegerList * __queue; +/* All other user-defined functions */ +/* Definition of interface info struct: Dequeue */ +typedef struct Dequeue_info { +T __RET__; +} Dequeue_info; +/* End of info struct definition: Dequeue */ + +/* ID function of interface: Dequeue */ +inline static call_id_t Dequeue_id(void *info, thread_id_t __TID__) { + Dequeue_info* theInfo = (Dequeue_info*)info; + T __RET__ = theInfo->__RET__; + + call_id_t __ID__ = __RET__ ? __RET__ : 0; + return __ID__; +} +/* End of ID function: Dequeue */ + +/* Check action function of interface: Dequeue */ +inline static bool Dequeue_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Dequeue_info* theInfo = (Dequeue_info*)info; + T __RET__ = theInfo->__RET__; + + int elem = 0 ; + if ( __RET__ ) { + elem = front ( __queue ) ; + pop_front ( __queue ) ; + } + check_passed = __RET__ ? __RET__ == elem : true; + if (!check_passed) + return false; + return true; +} +/* End of check action function: Dequeue */ + +/* Definition of interface info struct: Enqueue */ +typedef struct Enqueue_info { +T data; +} Enqueue_info; +/* End of info struct definition: Enqueue */ + +/* ID function of interface: Enqueue */ +inline static call_id_t Enqueue_id(void *info, thread_id_t __TID__) { + Enqueue_info* theInfo = (Enqueue_info*)info; + T data = theInfo->data; + + call_id_t __ID__ = data; + return __ID__; +} +/* End of ID function: Enqueue */ + +/* Check action function of interface: Enqueue */ +inline static bool Enqueue_check_action(void *info, call_id_t __ID__, thread_id_t __TID__) { + bool check_passed; + Enqueue_info* theInfo = (Enqueue_info*)info; + T data = theInfo->data; + + push_back ( __queue , data ) ; + return true; +} +/* End of check action function: Enqueue */ + +#define INTERFACE_SIZE 2 +static void** func_ptr_table; +static hb_rule** hb_rule_table; +static commutativity_rule** commutativity_rule_table; +inline static bool CommutativityCondition0(void *info1, void *info2) { + Enqueue_info *_info1 = (Enqueue_info*) info1; + Dequeue_info *_info2 = (Dequeue_info*) info2; + return true; +} +inline static bool CommutativityCondition1(void *info1, void *info2) { + Dequeue_info *_info1 = (Dequeue_info*) info1; + Dequeue_info *_info2 = (Dequeue_info*) info2; + return ! _info1-> __RET__ || ! _info2-> __RET__; +} + +/* Initialization of sequential varialbes */ +static void __SPEC_INIT__() { + __queue = createIntegerList ( ) ; +} + +/* Cleanup routine of sequential variables */ +static bool __SPEC_CLEANUP__() { + if ( __queue ) destroyIntegerList ( __queue ) ; + return true ; +} + +/* Define function for sequential code initialization */ +inline static void __sequential_init() { + /* Init func_ptr_table */ + func_ptr_table = (void**) malloc(sizeof(void*) * 2 * 2); + func_ptr_table[2 * 1] = (void*) &Dequeue_id; + func_ptr_table[2 * 1 + 1] = (void*) &Dequeue_check_action; + func_ptr_table[2 * 0] = (void*) &Enqueue_id; + func_ptr_table[2 * 0 + 1] = (void*) &Enqueue_check_action; + /* Enqueue(true) -> Dequeue(true) */ + struct hb_rule *hbConditionInit0 = (struct hb_rule*) malloc(sizeof(struct hb_rule)); + hbConditionInit0->interface_num_before = 0; // Enqueue + hbConditionInit0->hb_condition_num_before = 0; // + hbConditionInit0->interface_num_after = 1; // Dequeue + hbConditionInit0->hb_condition_num_after = 0; // + /* Init hb_rule_table */ + hb_rule_table = (hb_rule**) malloc(sizeof(hb_rule*) * 1); + #define HB_RULE_TABLE_SIZE 1 + hb_rule_table[0] = hbConditionInit0; + /* Init commutativity_rule_table */ + commutativity_rule_table = (commutativity_rule**) malloc(sizeof(commutativity_rule*) * 2); + commutativity_rule* rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 0; + rule->interface_num_after = 1; + rule->rule = "true"; + rule->condition = CommutativityCondition0; + commutativity_rule_table[0] = rule; + rule = (commutativity_rule*) malloc (sizeof(commutativity_rule)); + rule->interface_num_before = 1; + rule->interface_num_after = 1; + rule->rule = "! _Method1 . __RET__ || ! _Method2 . __RET__"; + rule->condition = CommutativityCondition1; + commutativity_rule_table[1] = rule; + /* Pass init info, including function table info & HB rules & Commutativity Rules */ + struct anno_init *anno_init = (struct anno_init*) malloc(sizeof(struct anno_init)); + anno_init->init_func = (void_func_t) __SPEC_INIT__; + anno_init->cleanup_func = (cleanup_func_t) __SPEC_CLEANUP__; + anno_init->func_table = func_ptr_table; + anno_init->func_table_size = INTERFACE_SIZE; + anno_init->hb_rule_table = hb_rule_table; + anno_init->hb_rule_table_size = HB_RULE_TABLE_SIZE; + anno_init->commutativity_rule_table = commutativity_rule_table; + anno_init->commutativity_rule_table_size = 2; + struct spec_annotation *init = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + init->type = INIT; + init->annotation = anno_init; + cdsannotate(SPEC_ANALYSIS, init); + +} + +/* End of Global construct generation in class */ + + + + +void enqueue(T data) { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 0; // Enqueue + interface_begin->interface_name = "Enqueue"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + __wrapper__enqueue(data); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 0; // Enqueue + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Enqueue_info* info = (Enqueue_info*) malloc(sizeof(Enqueue_info)); + info->data = data; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 0; // Enqueue + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); +} + +void __wrapper__enqueue(T data) + { + node* n = new node (data); + + head->next.store(n, std::memory_order_release); + /* Automatically generated code for commit point define check: Enqueue_Point */ + + if (true) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 0; + cp_define_check->label_name = "Enqueue_Point"; + cp_define_check->interface_num = 0; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + head = n; + ec.signal(); + } + +T dequeue() { + /* Interface begins */ + struct anno_interface_begin *interface_begin = (struct anno_interface_begin*) malloc(sizeof(struct anno_interface_begin)); + interface_begin->interface_num = 1; // Dequeue + interface_begin->interface_name = "Dequeue"; + struct spec_annotation *annotation_interface_begin = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_interface_begin->type = INTERFACE_BEGIN; + annotation_interface_begin->annotation = interface_begin; + cdsannotate(SPEC_ANALYSIS, annotation_interface_begin); + T __RET__ = __wrapper__dequeue(); + struct anno_hb_condition *hb_condition = (struct anno_hb_condition*) malloc(sizeof(struct anno_hb_condition)); + hb_condition->interface_num = 1; // Dequeue + hb_condition->hb_condition_num = 0; + struct spec_annotation *annotation_hb_condition = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_hb_condition->type = HB_CONDITION; + annotation_hb_condition->annotation = hb_condition; + cdsannotate(SPEC_ANALYSIS, annotation_hb_condition); + + Dequeue_info* info = (Dequeue_info*) malloc(sizeof(Dequeue_info)); + info->__RET__ = __RET__; + struct anno_interface_end *interface_end = (struct anno_interface_end*) malloc(sizeof(struct anno_interface_end)); + interface_end->interface_num = 1; // Dequeue + interface_end->info = info; + struct spec_annotation *annoation_interface_end = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annoation_interface_end->type = INTERFACE_END; + annoation_interface_end->annotation = interface_end; + cdsannotate(SPEC_ANALYSIS, annoation_interface_end); + return __RET__; +} + +T __wrapper__dequeue() + { + T data = try_dequeue(); + while (0 == data) + { + int cmp = ec.get(); + data = try_dequeue(); + if (data) + break; + ec.wait(cmp); + data = try_dequeue(); + if (data) + break; + } + return data; + } + +private: + struct node + { + std::atomic next; + T data; + + node(T data = T()) + : data(data) + { + next = 0; + } + }; + + node *head; + node *tail; + + + + eventcount ec; + + T try_dequeue() + { + node *t = tail; + + node* n = t->next.load(std::memory_order_acquire); + /* Automatically generated code for commit point define check: Dequeue_Point */ + + if (n != 0) { + struct anno_cp_define_check *cp_define_check = (struct anno_cp_define_check*) malloc(sizeof(struct anno_cp_define_check)); + cp_define_check->label_num = 1; + cp_define_check->label_name = "Dequeue_Point"; + cp_define_check->interface_num = 1; + struct spec_annotation *annotation_cp_define_check = (struct spec_annotation*) malloc(sizeof(struct spec_annotation)); + annotation_cp_define_check->type = CP_DEFINE_CHECK; + annotation_cp_define_check->annotation = cp_define_check; + cdsannotate(SPEC_ANALYSIS, annotation_cp_define_check); + } + + if (0 == n) + return 0; + T data = n->data; + delete (t); + tail = n; + return data; + } +}; +template +void** spsc_queue::func_ptr_table; +template +hb_rule** spsc_queue::hb_rule_table; +template +commutativity_rule** spsc_queue::commutativity_rule_table; +template +IntegerList * spsc_queue::__queue; + + +#endif + diff --git a/output/spsc-bugfix/spsc-queue b/output/spsc-bugfix/spsc-queue new file mode 100755 index 0000000..90244b2 Binary files /dev/null and b/output/spsc-bugfix/spsc-queue differ diff --git a/output/spsc-bugfix/spsc-queue.cc b/output/spsc-bugfix/spsc-queue.cc new file mode 100644 index 0000000..e824eed --- /dev/null +++ b/output/spsc-bugfix/spsc-queue.cc @@ -0,0 +1,34 @@ +#include + +#include "queue.h" + +spsc_queue *q; + + void thread(unsigned thread_index) + { + if (0 == thread_index) + { + q->enqueue(11); + } + else + { + int d = q->dequeue(); + } + } + +int user_main(int argc, char **argv) +{ + thrd_t A, B; + + q = new spsc_queue(); + + thrd_create(&A, (thrd_start_t)&thread, (void *)0); + thrd_create(&B, (thrd_start_t)&thread, (void *)1); + thrd_join(A); + thrd_join(B); + + delete q; + + return 0; +} + diff --git a/src/edu/uci/eecs/specCompiler/codeGenerator/CodeGenerator.java b/src/edu/uci/eecs/specCompiler/codeGenerator/CodeGenerator.java index 7491e70..28609e6 100644 --- a/src/edu/uci/eecs/specCompiler/codeGenerator/CodeGenerator.java +++ b/src/edu/uci/eecs/specCompiler/codeGenerator/CodeGenerator.java @@ -344,8 +344,8 @@ public class CodeGenerator { // File[][] sources = {srcLinuxRWLock1 , srcMSQueue, srcRCU, // srcDeque, srcMCSLock, srcSPSCQueue, srcMPMCQueue, srcHashtable }; -// File[][] sources = {srcDeque, srcLinuxRWLock1, srcLinuxRWLock2, srcLinuxRWLock3, srcMCSLock, srcHashtable, srcRCU}; - File[][] sources = {srcMPMCQueue}; + File[][] sources = {srcDeque, srcLinuxRWLock1, srcLinuxRWLock2, srcLinuxRWLock3, srcMCSLock, srcHashtable, srcRCU, srcMSQueue, srcSPSCQueue, srcMPMCQueue}; +// File[][] sources = {srcMSQueue}; // Compile all the benchmarks for (int i = 0; i < sources.length; i++) { CodeGenerator gen = new CodeGenerator(sources[i]);