From e7fb1d3fca70b9f871b961f2f3c3443d4955a3b4 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 4 Mar 2013 17:00:52 -0800 Subject: [PATCH] deque: add "proven correct" work-stealing Chase-Lev deque MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 chase-lev-deque/deque.c diff --git a/chase-lev-deque/deque.c b/chase-lev-deque/deque.c new file mode 100644 index 0000000..956e8e0 --- /dev/null +++ b/chase-lev-deque/deque.c @@ -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; +} -- 2.34.1