From 1af8c0a4514c147221b92a1056afc58dc305f53c Mon Sep 17 00:00:00 2001
From: Brian Demsky <bdemsky@uci.edu>
Date: Wed, 6 Mar 2013 12:02:48 -0800
Subject: [PATCH] add make file, header, and extra code to deque

---
 chase-lev-deque/Makefile | 17 +++++++++++++
 chase-lev-deque/deque.c  | 52 +++++++++++++++++++++++++++-------------
 chase-lev-deque/deque.h  | 22 +++++++++++++++++
 3 files changed, 75 insertions(+), 16 deletions(-)
 create mode 100644 chase-lev-deque/Makefile
 create mode 100644 chase-lev-deque/deque.h

diff --git a/chase-lev-deque/Makefile b/chase-lev-deque/Makefile
new file mode 100644
index 0000000..3f0fc86
--- /dev/null
+++ b/chase-lev-deque/Makefile
@@ -0,0 +1,17 @@
+include ../benchmarks.mk
+
+TESTNAME = main
+
+HEADERS = 
+OBJECTS = deque.o
+
+all: $(TESTNAME)
+
+$(TESTNAME): $(HEADERS) $(OBJECTS)
+	$(CC) -o $@ $(OBJECTS) $(CPPFLAGS) $(LDFLAGS)
+
+%.o: %.c
+	$(CC) -c -o $@ $< $(CPPFLAGS)
+
+clean:
+	rm -f $(TESTNAME) *.o
diff --git a/chase-lev-deque/deque.c b/chase-lev-deque/deque.c
index efa9b16..34f645b 100644
--- a/chase-lev-deque/deque.c
+++ b/chase-lev-deque/deque.c
@@ -1,26 +1,28 @@
 #include <stdatomic.h>
 #include <inttypes.h>
+#include "deque.h"
+#include <stdlib.h>
 
-typedef struct {
-	atomic_size_t size;
-	atomic_int buffer[];
-} Array;
-
-typedef struct {
-	atomic_size_t top, bottom;
-	atomic_uintptr_t array; /* Atomic(Array *) */
-} Deque;
+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) {
 	size_t b = atomic_load_explicit(&q->bottom, memory_order_relaxed) - 1;
-	Array *a = atomic_load_explicit(&q->array, memory_order_relaxed);
+	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) {
 		/* Non-empty queue. */
-		x = atomic_load_explicit(&a->buffer[b % a->size], memory_order_relaxed);
+		x = atomic_load_explicit(&a->buffer[b % atomic_load_explicit(&a->size,memory_order_relaxed)], memory_order_relaxed);
 		if (t == b) {
 			/* Single last element in queue. */
 			if (!atomic_compare_exchange_strong_explicit(&q->top, &t, t + 1, memory_order_seq_cst, memory_order_relaxed))
@@ -35,13 +37,31 @@ int take(Deque *q) {
 	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], atomic_load_explicit(&a->buffer[i], memory_order_relaxed), memory_order_relaxed);
+	}
+	atomic_store_explicit(&q->array, new_a, memory_order_relaxed);
+}
+
 void 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 = atomic_load_explicit(&q->array, memory_order_relaxed);
-	if (b - t > a->size - 1) /* Full queue. */
+	Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed);
+	if (b - t > atomic_load_explicit(&a->size, memory_order_relaxed) - 1) /* Full queue. */ {
 		resize(q);
-	atomic_store_explicit(&a->buffer[b % a->size], x, memory_order_relaxed);
+		//Bug in paper...should have next line...
+		a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed);
+	}
+	atomic_store_explicit(&a->buffer[b % atomic_load_explicit(&a->size, memory_order_relaxed)], x, memory_order_relaxed);
 	atomic_thread_fence(memory_order_release);
 	atomic_store_explicit(&q->bottom, b + 1, memory_order_relaxed);
 }
@@ -53,8 +73,8 @@ int steal(Deque *q) {
 	int x = EMPTY;
 	if (t < b) {
 		/* Non-empty queue. */
-		Array *a = atomic_load_explicit(&q->array, memory_order_relaxed);
-		x = atomic_load_explicit(&a->buffer[t % a->size], memory_order_relaxed);
+		Array *a = (Array *) atomic_load_explicit(&q->array, memory_order_relaxed);
+		x = atomic_load_explicit(&a->buffer[t % atomic_load_explicit(&a->size, memory_order_relaxed)], memory_order_relaxed);
 		if (!atomic_compare_exchange_strong_explicit(&q->top, &t, t + 1, memory_order_seq_cst, memory_order_relaxed))
 			/* Failed race. */
 			return ABORT;
diff --git a/chase-lev-deque/deque.h b/chase-lev-deque/deque.h
new file mode 100644
index 0000000..bc670e7
--- /dev/null
+++ b/chase-lev-deque/deque.h
@@ -0,0 +1,22 @@
+#ifndef DEQUE_H
+#define DEQUE_H
+
+typedef struct {
+	atomic_size_t size;
+	atomic_int buffer[];
+} Array;
+
+typedef struct {
+	atomic_size_t top, bottom;
+	atomic_uintptr_t array; /* Atomic(Array *) */
+} Deque;
+
+Deque * create();
+int take(Deque *q);
+void resize(Deque *q);
+void push(Deque *q, int x);
+
+#define EMPTY 0xffffffff
+#define ABORT 0xfffffffe
+
+#endif
-- 
2.34.1