deque: add "proven correct" work-stealing Chase-Lev deque
authorBrian Norris <banorris@uci.edu>
Tue, 5 Mar 2013 01:00:52 +0000 (17:00 -0800)
committerBrian Norris <banorris@uci.edu>
Tue, 5 Mar 2013 01:52:05 +0000 (17:52 -0800)
From the PPoPP 2013 paper "Correct and efficient work-stealing for weak
memory models"

By:

  Nhat Minh LĂȘ
  Antoniu Pop
  Albert Cohen
  Francesco Zappa Nardelli

Citation URL:

  http://dl.acm.org/citation.cfm?id=2442524

chase-lev-deque/deque.c [new file with mode: 0644]

diff --git a/chase-lev-deque/deque.c b/chase-lev-deque/deque.c
new file mode 100644 (file)
index 0000000..956e8e0
--- /dev/null
@@ -0,0 +1,60 @@
+typedef struct {
+       atomic_size_t size;
+       atomic_int buffer[];
+} Array;
+
+typedef struct {
+       atomic_size_t top, bottom;
+       Atomic(Array *) array;
+} Deque;
+
+int take(Deque *q) {
+       size_t b = load_explicit(&q->bottom, relaxed) - 1;
+       Array *a = load_explicit(&q->array, relaxed);
+       store_explicit(&q->bottom, b, relaxed);
+       thread_fence(seq_cst);
+       size_t t = load_explicit(&q->top, relaxed);
+       int x;
+       if (t <= b) {
+               /* Non-empty queue. */
+               x = load_explicit(&a->buffer[b % a->size], relaxed);
+               if (t == b) {
+                       /* Single last element in queue. */
+                       if (!compare_exchange_strong_explicit(&q->top, &t, t + 1, seq_cst, relaxed))
+                               /* Failed race. */
+                               x = EMPTY;
+                       store_explicit(&q->bottom, b + 1, relaxed);
+               }
+       } else { /* Empty queue. */
+               x = EMPTY;
+               store_explicit(&q->bottom, b + 1, relaxed);
+       }
+       return x;
+}
+
+void push(Deque *q, int x) {
+       size_t b = load_explicit(&q->bottom, relaxed);
+       size_t t = load_explicit(&q->top, acquire);
+       Array *a = load_explicit(&q->array, relaxed);
+       if (b - t > a->size - 1) /* Full queue. */
+               resize(q);
+       store_explicit(&a->buffer[b % a->size], x, relaxed);
+       thread_fence(release);
+       store_explicit(&q->bottom, b + 1, relaxed);
+}
+
+int steal(Deque *q) {
+       size_t t = load_explicit(&q->top, acquire);
+       thread_fence(seq_cst);
+       size_t b = load_explicit(&q->bottom, acquire);
+       int x = EMPTY;
+       if (t < b) {
+               /* Non-empty queue. */
+               Array *a = load_explicit(&q->array, relaxed);
+               x = load_explicit(&a->buffer[t % a->size], relaxed);
+               if (!compare_exchange_strong_explicit(&q->top, &t, t + 1, seq_cst, relaxed))
+                       /* Failed race. */
+                       return ABORT;
+       }
+       return x;
+}