changes
[cdsspec-compiler.git] / benchmark / chase-lev-deque-bugfix / deque.c
1 #include <stdatomic.h>
2 #include <inttypes.h>
3 #include "deque.h"
4 #include <stdlib.h>
5 #include <stdio.h>
6
7 Deque * create() {
8         Deque * q = (Deque *) calloc(1, sizeof(Deque));
9         Array * a = (Array *) calloc(1, sizeof(Array)+2*sizeof(atomic_int));
10         atomic_store_explicit(&q->array, a, memory_order_relaxed);
11         atomic_store_explicit(&q->top, 0, memory_order_relaxed);
12         atomic_store_explicit(&q->bottom, 0, memory_order_relaxed);
13         atomic_store_explicit(&a->size, 2, memory_order_relaxed);
14         return q;
15 }
16
17
18 /**
19         @Begin
20         @Interface_define: Take 
21         @End
22 */
23 int take(Deque *q) {
24         size_t b = atomic_load_explicit(&q->bottom, memory_order_relaxed) - 1;
25         Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed);
26         atomic_store_explicit(&q->bottom, b, memory_order_relaxed);
27         /**** detected correctness ****/
28         atomic_thread_fence(memory_order_seq_cst);
29         size_t t = atomic_load_explicit(&q->top, memory_order_relaxed);
30         /**
31                 @Begin
32                 @Commit_point_define_check: t > b
33                 @Label: Take_Point1
34                 @End
35         */
36         int x;
37         if (t <= b) {
38                 /* Non-empty queue. */
39                 int size = atomic_load_explicit(&a->size,memory_order_relaxed);
40                 x = atomic_load_explicit(&a->buffer[b % size], memory_order_relaxed);
41                 /**
42                         @Begin
43                         @Commit_point_define_check: t != b
44                         @Label: Take_Point2
45                         @End
46                 */
47                 if (t == b) {
48                         /* Single last element in queue. */
49                         //FIXME: weaken the following seq_cst causes no spec problem
50                         bool succ = atomic_compare_exchange_strong_explicit(&q->top, &t, t +
51                                 1, memory_order_seq_cst, memory_order_relaxed);
52                         /**
53                                 @Begin
54                                 @Commit_point_define_check: true
55                                 @Label: Take_Point3
56                                 @End
57                         */
58                         if (!succ) {
59                                 /* Failed race. */
60                                 x = EMPTY;
61                         }
62                         atomic_store_explicit(&q->bottom, b + 1, memory_order_relaxed);
63                 }
64         } else { /* Empty queue. */
65                 x = EMPTY;
66                 atomic_store_explicit(&q->bottom, b + 1, memory_order_relaxed);
67         }
68         return x;
69 }
70
71 void resize(Deque *q) {
72         Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed);
73         size_t size=atomic_load_explicit(&a->size, memory_order_relaxed);
74         size_t new_size=size << 1;
75         Array *new_a = (Array *) calloc(1, new_size * sizeof(atomic_int) + sizeof(Array));
76         size_t top=atomic_load_explicit(&q->top, memory_order_relaxed);
77         size_t bottom=atomic_load_explicit(&q->bottom, memory_order_relaxed);
78         atomic_store_explicit(&new_a->size, new_size, memory_order_relaxed);
79         size_t i;
80         for(i=top; i < bottom; i++) {
81                 atomic_store_explicit(&new_a->buffer[i % new_size], atomic_load_explicit(&a->buffer[i % size], memory_order_relaxed), memory_order_relaxed);
82         }
83         /**** detected UL ****/
84         atomic_store_explicit(&q->array, new_a, memory_order_release);
85         //printf("resize\n");
86 }
87
88 /**
89         @Begin
90         @Interface_define: Push
91         @End
92 */
93 void push(Deque *q, int x) {
94         size_t b = atomic_load_explicit(&q->bottom, memory_order_relaxed);
95         /**** detected correctness ****/
96         size_t t = atomic_load_explicit(&q->top, memory_order_acquire);
97         Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed);
98         if (b - t > atomic_load_explicit(&a->size, memory_order_relaxed) - 1) /* Full queue. */ {
99                 resize(q);
100                 //Bug in paper...should have next line...
101                 a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed);
102                 /**
103                         @Begin
104                         @Commit_point_define_check: true
105                         @Label: Push_Read_Array
106                         @End
107                 */
108         }
109         int size = atomic_load_explicit(&a->size, memory_order_relaxed);
110
111         atomic_store_explicit(&a->buffer[b % size], x, memory_order_relaxed);
112         /**
113                 @Begin
114                 @Commit_point_define_check: true
115                 @Label: Push_Update_Buffer
116                 @End
117         */
118         /**** correctness error ****/
119         atomic_thread_fence(memory_order_release);
120         
121         atomic_store_explicit(&q->bottom, b + 1, memory_order_relaxed);
122         /**
123                 @Begin
124                 @Commit_point_define_check: true
125                 @Label: Push_Update_Bottom
126                 @End
127         */
128 }
129
130 /**
131         @Begin
132         @Interface_define: Steal 
133         @End
134 */
135 int steal(Deque *q) {
136         //FIXME: weaken the following acquire causes no spec problem
137         size_t t = atomic_load_explicit(&q->top, memory_order_acquire);
138         //FIXME: remove the fence causes no error and fewer executions..
139         atomic_thread_fence(memory_order_seq_cst);
140         /**** detected UL ****/
141         size_t b = atomic_load_explicit(&q->bottom, memory_order_acquire);
142         /**
143                 @Begin
144                 @Commit_point_define_check: t >= b
145                 @Label: Steal_Point1
146                 @End
147         */
148         int x = EMPTY;
149         if (t < b) {
150                 /* Non-empty queue. */
151                 /**** detected UL ****/
152                 Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_acquire);
153                 int size = atomic_load_explicit(&a->size, memory_order_relaxed);
154                 x = atomic_load_explicit(&a->buffer[t % size], memory_order_relaxed);
155                 /**
156                         @Begin
157                         @Potential_commit_point_define: true
158                         @Label: Potential_Steal
159                         @End
160                 */
161                 /**** detected correctness failure ****/ 
162                 bool succ = atomic_compare_exchange_strong_explicit(&q->top, &t, t + 1,
163                         memory_order_seq_cst, memory_order_relaxed);
164                 /**
165                         @Begin
166                         @Commit_point_define_check: !succ
167                         @Label: Steal_Point2
168                         @End
169                 */
170
171                 /**
172                         @Begin
173                         @Commit_point_define: succ
174                         @Potential_commit_point_label: Potential_Steal
175                         @Label: Steal_Point3
176                         @End
177                 */
178                 if (!succ) {
179                         /* Failed race. */
180                         return ABORT;
181                 }
182         }
183         return x;
184 }