make code look better
[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         atomic_thread_fence(memory_order_seq_cst);
28         size_t t = atomic_load_explicit(&q->top, memory_order_relaxed);
29         /**
30                 @Begin
31                 @Commit_point_define_check: t > b
32                 @Label: Take_Point_1
33                 @End
34         */
35         int x;
36         if (t <= b) {
37                 /* Non-empty queue. */
38                 x = atomic_load_explicit(&a->buffer[b % atomic_load_explicit(&a->size,memory_order_relaxed)], memory_order_relaxed);
39                 /**
40                         @Begin
41                         @Commit_point_define_check: t != b
42                         @Label: Take_Point2
43                         @End
44                 */
45                 if (t == b) {
46                         /* Single last element in queue. */
47                         bool succ = atomic_compare_exchange_strong_explicit(&q->top, &t, t +
48                                 1, memory_order_seq_cst, memory_order_relaxed);
49                         /**
50                                 @Begin
51                                 @Commit_point_define_check: succ == true
52                                 @Label: Take_Point3
53                                 @End
54                         */
55                         
56                         /**
57                                 @Begin
58                                 @Commit_point_define_check: succ == false
59                                 @Label: Take_Point4
60                                 @End
61                         */
62                         if (!succ) {
63                                 /* Failed race. */
64                                 x = EMPTY;
65                         }
66                         atomic_store_explicit(&q->bottom, b + 1, memory_order_relaxed);
67                 }
68         } else { /* Empty queue. */
69                 x = EMPTY;
70                 atomic_store_explicit(&q->bottom, b + 1, memory_order_relaxed);
71         }
72         return x;
73 }
74
75 void resize(Deque *q) {
76         Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed);
77         size_t size=atomic_load_explicit(&a->size, memory_order_relaxed);
78         size_t new_size=size << 1;
79         Array *new_a = (Array *) calloc(1, new_size * sizeof(atomic_int) + sizeof(Array));
80         size_t top=atomic_load_explicit(&q->top, memory_order_relaxed);
81         size_t bottom=atomic_load_explicit(&q->bottom, memory_order_relaxed);
82         atomic_store_explicit(&new_a->size, new_size, memory_order_relaxed);
83         size_t i;
84         for(i=top; i < bottom; i++) {
85                 atomic_store_explicit(&new_a->buffer[i % new_size], atomic_load_explicit(&a->buffer[i % size], memory_order_relaxed), memory_order_relaxed);
86         }
87         atomic_store_explicit(&q->array, new_a, memory_order_release);
88         printf("resize\n");
89 }
90
91 /**
92         @Begin
93         @Interface_define: Push
94         @End
95 */
96 void push(Deque *q, int x) {
97         size_t b = atomic_load_explicit(&q->bottom, memory_order_relaxed);
98         size_t t = atomic_load_explicit(&q->top, memory_order_acquire);
99         Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed);
100         if (b - t > atomic_load_explicit(&a->size, memory_order_relaxed) - 1) /* Full queue. */ {
101                 resize(q);
102                 //Bug in paper...should have next line...
103                 a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed);
104         }
105         atomic_store_explicit(&a->buffer[b % atomic_load_explicit(&a->size, memory_order_relaxed)], x, memory_order_relaxed);
106         atomic_thread_fence(memory_order_release);
107         /**
108                 @Begin
109                 @Commit_point_define_check: true
110                 @Label: Push_Point
111                 @End
112         */
113         atomic_store_explicit(&q->bottom, b + 1, memory_order_relaxed);
114 }
115
116 /**
117         @Begin
118         @Interface_define: Steal 
119         @End
120 */
121 int steal(Deque *q) {
122         size_t t = atomic_load_explicit(&q->top, memory_order_acquire);
123         atomic_thread_fence(memory_order_seq_cst);
124         size_t b = atomic_load_explicit(&q->bottom, memory_order_acquire);
125         /**
126                 @Begin
127                 @Commit_point_define_check: t >= b
128                 @Label: Steal_Point1
129                 @End
130         */
131         int x = EMPTY;
132         if (t < b) {
133                 /* Non-empty queue. */
134                 Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_acquire);
135                 x = atomic_load_explicit(&a->buffer[t % atomic_load_explicit(&a->size, memory_order_relaxed)], memory_order_relaxed);
136                 bool succ = atomic_compare_exchange_strong_explicit(&q->top, &t, t + 1,
137                         memory_order_seq_cst, memory_order_relaxed);
138                 /**
139                         @Begin
140                         @Commit_point_define_check: succ == true
141                         @Label: Steal_Point2
142                         @End
143                 */
144                 
145                 /**
146                         @Begin
147                         @Commit_point_define_check: succ == false
148                         @Label: Steal_Point3
149                         @End
150                 */
151                 if (!succ) {
152                         /* Failed race. */
153                         return ABORT;
154                 }
155         }
156         return x;
157 }