From 1066ff319f565bb63268c1e6b6f48c114aac34b2 Mon Sep 17 00:00:00 2001
From: Brian Norris <banorris@uci.edu>
Date: Tue, 15 Jan 2013 12:44:47 -0800
Subject: [PATCH] test: litmus: add litmus tests from Nitpicking C++

This adds most of the litmus tests from Nitpicking C++ Concurrency. Note
that it leaves out the 'consume' tests (replacing it with the
also-mentioned release/acquire test). It doesn't test the seq_cst
results, although I could provide command-line switches to do so...
---
 test/litmus/Makefile           | 20 +++++++++++++
 test/litmus/iriw.cc            | 50 ++++++++++++++++++++++++++++++++
 test/litmus/load-buffer.cc     | 36 +++++++++++++++++++++++
 test/litmus/message-passing.cc | 44 ++++++++++++++++++++++++++++
 test/litmus/seq-lock.cc        | 52 +++++++++++++++++++++++++++++++++
 test/litmus/store-buffer.cc    | 36 +++++++++++++++++++++++
 test/litmus/wrc.cc             | 53 ++++++++++++++++++++++++++++++++++
 7 files changed, 291 insertions(+)
 create mode 100644 test/litmus/Makefile
 create mode 100644 test/litmus/iriw.cc
 create mode 100644 test/litmus/load-buffer.cc
 create mode 100644 test/litmus/message-passing.cc
 create mode 100644 test/litmus/seq-lock.cc
 create mode 100644 test/litmus/store-buffer.cc
 create mode 100644 test/litmus/wrc.cc

diff --git a/test/litmus/Makefile b/test/litmus/Makefile
new file mode 100644
index 0000000..b4a1233
--- /dev/null
+++ b/test/litmus/Makefile
@@ -0,0 +1,20 @@
+BASE = ../..
+
+include $(BASE)/common.mk
+
+CPPFLAGS += -I$(BASE) -I$(BASE)/include
+
+SRCS = $(wildcard *.c)
+CPSRCS = $(wildcard *.cc)
+OBJS = $(patsubst %.c,%.o,$(SRCS)) $(patsubst %.cc,%.o,$(CPSRCS))
+
+all: $(OBJS)
+
+%.o: %.c
+	$(CC) -o $@ $< $(CPPFLAGS) -L$(BASE) -l$(LIB_NAME)
+
+%.o: %.cc
+	$(CXX) -o $@ $< $(CPPFLAGS) -L$(BASE) -l$(LIB_NAME)
+
+clean::
+	rm -f *.o
diff --git a/test/litmus/iriw.cc b/test/litmus/iriw.cc
new file mode 100644
index 0000000..cc519f1
--- /dev/null
+++ b/test/litmus/iriw.cc
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <threads.h>
+#include <atomic>
+
+std::atomic_int x;
+std::atomic_int y;
+
+static void a(void *obj)
+{
+	x.store(1, std::memory_order_release);
+}
+
+static void b(void *obj)
+{
+	y.store(1, std::memory_order_release);
+}
+
+static void c(void *obj)
+{
+	printf("x1: %d\n", x.load(std::memory_order_relaxed));
+	printf("y1: %d\n", y.load(std::memory_order_relaxed));
+}
+
+static void d(void *obj)
+{
+	printf("y2: %d\n", y.load(std::memory_order_relaxed));
+	printf("x2: %d\n", x.load(std::memory_order_relaxed));
+}
+
+int user_main(int argc, char **argv)
+{
+	thrd_t t1, t2, t3, t4;
+
+	atomic_init(&x, 0);
+	atomic_init(&y, 0);
+
+	printf("Main thread: creating 4 threads\n");
+	thrd_create(&t1, (thrd_start_t)&a, NULL);
+	thrd_create(&t2, (thrd_start_t)&b, NULL);
+	thrd_create(&t3, (thrd_start_t)&c, NULL);
+	thrd_create(&t4, (thrd_start_t)&d, NULL);
+
+	thrd_join(t1);
+	thrd_join(t2);
+	thrd_join(t3);
+	thrd_join(t4);
+	printf("Main thread is finished\n");
+
+	return 0;
+}
diff --git a/test/litmus/load-buffer.cc b/test/litmus/load-buffer.cc
new file mode 100644
index 0000000..9c9923c
--- /dev/null
+++ b/test/litmus/load-buffer.cc
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <threads.h>
+#include <atomic>
+
+std::atomic_int x;
+std::atomic_int y;
+
+static void a(void *obj)
+{
+	printf("x: %d\n", x.load(std::memory_order_relaxed));
+	y.store(1, std::memory_order_relaxed);
+}
+
+static void b(void *obj)
+{
+	printf("y: %d\n", y.load(std::memory_order_relaxed));
+	x.store(1, std::memory_order_relaxed);
+}
+
+int user_main(int argc, char **argv)
+{
+	thrd_t t1, t2;
+
+	atomic_init(&x, 0);
+	atomic_init(&y, 0);
+
+	printf("Main thread: creating 2 threads\n");
+	thrd_create(&t1, (thrd_start_t)&a, NULL);
+	thrd_create(&t2, (thrd_start_t)&b, NULL);
+
+	thrd_join(t1);
+	thrd_join(t2);
+	printf("Main thread is finished\n");
+
+	return 0;
+}
diff --git a/test/litmus/message-passing.cc b/test/litmus/message-passing.cc
new file mode 100644
index 0000000..6ef41eb
--- /dev/null
+++ b/test/litmus/message-passing.cc
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <threads.h>
+#include <atomic>
+
+std::atomic_int x;
+std::atomic_int y;
+
+static void a(void *obj)
+{
+	x.store(1, std::memory_order_relaxed);
+	y.store(1, std::memory_order_relaxed);
+}
+
+static void b(void *obj)
+{
+	printf("y1: %d\n", y.load(std::memory_order_relaxed));
+	printf("x1: %d\n", x.load(std::memory_order_relaxed));
+}
+
+static void c(void *obj)
+{
+	printf("x2: %d\n", x.load(std::memory_order_relaxed));
+	printf("y2: %d\n", y.load(std::memory_order_relaxed));
+}
+
+int user_main(int argc, char **argv)
+{
+	thrd_t t1, t2, t3;
+
+	atomic_init(&x, 0);
+	atomic_init(&y, 0);
+
+	printf("Main thread: creating 3 threads\n");
+	thrd_create(&t1, (thrd_start_t)&a, NULL);
+	thrd_create(&t2, (thrd_start_t)&b, NULL);
+	thrd_create(&t3, (thrd_start_t)&c, NULL);
+
+	thrd_join(t1);
+	thrd_join(t2);
+	thrd_join(t3);
+	printf("Main thread is finished\n");
+
+	return 0;
+}
diff --git a/test/litmus/seq-lock.cc b/test/litmus/seq-lock.cc
new file mode 100644
index 0000000..447123c
--- /dev/null
+++ b/test/litmus/seq-lock.cc
@@ -0,0 +1,52 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <threads.h>
+#include <atomic>
+
+std::atomic_int x;
+std::atomic_int y;
+std::atomic_int z;
+
+static int N = 1;
+
+static void a(void *obj)
+{
+	for (int i = 0; i < N; i++) {
+		x.store(2 * i + 1, std::memory_order_release);
+		y.store(i + 1, std::memory_order_release);
+		z.store(i + 1, std::memory_order_release);
+		x.store(2 * i + 2, std::memory_order_release);
+	}
+}
+
+static void b(void *obj)
+{
+	printf("x: %d\n", x.load(std::memory_order_acquire));
+	printf("y: %d\n", y.load(std::memory_order_acquire));
+	printf("z: %d\n", z.load(std::memory_order_acquire));
+	printf("x: %d\n", x.load(std::memory_order_acquire));
+}
+
+int user_main(int argc, char **argv)
+{
+	thrd_t t1, t2;
+
+	if (argc > 1)
+		N = atoi(argv[1]);
+
+	printf("N: %d\n", N);
+
+	atomic_init(&x, 0);
+	atomic_init(&y, 0);
+	atomic_init(&z, 0);
+
+	printf("Main thread: creating 2 threads\n");
+	thrd_create(&t1, (thrd_start_t)&a, NULL);
+	thrd_create(&t2, (thrd_start_t)&b, NULL);
+
+	thrd_join(t1);
+	thrd_join(t2);
+	printf("Main thread is finished\n");
+
+	return 0;
+}
diff --git a/test/litmus/store-buffer.cc b/test/litmus/store-buffer.cc
new file mode 100644
index 0000000..eb43d44
--- /dev/null
+++ b/test/litmus/store-buffer.cc
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <threads.h>
+#include <atomic>
+
+std::atomic_int x;
+std::atomic_int y;
+
+static void a(void *obj)
+{
+	x.store(1, std::memory_order_relaxed);
+	printf("y: %d\n", y.load(std::memory_order_relaxed));
+}
+
+static void b(void *obj)
+{
+	y.store(1, std::memory_order_relaxed);
+	printf("x: %d\n", x.load(std::memory_order_relaxed));
+}
+
+int user_main(int argc, char **argv)
+{
+	thrd_t t1, t2;
+
+	atomic_init(&x, 0);
+	atomic_init(&y, 0);
+
+	printf("Main thread: creating 2 threads\n");
+	thrd_create(&t1, (thrd_start_t)&a, NULL);
+	thrd_create(&t2, (thrd_start_t)&b, NULL);
+
+	thrd_join(t1);
+	thrd_join(t2);
+	printf("Main thread is finished\n");
+
+	return 0;
+}
diff --git a/test/litmus/wrc.cc b/test/litmus/wrc.cc
new file mode 100644
index 0000000..225eb4b
--- /dev/null
+++ b/test/litmus/wrc.cc
@@ -0,0 +1,53 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <threads.h>
+#include <atomic>
+
+static int N = 2;
+
+std::atomic_int *x;
+
+static void a(void *obj)
+{
+	int idx = *((int *)obj);
+
+	if (idx > 0)
+		x[idx - 1].load(std::memory_order_relaxed);
+
+	if (idx < N)
+		x[idx].store(1, std::memory_order_relaxed);
+	else
+		x[0].load(std::memory_order_relaxed);
+}
+
+int user_main(int argc, char **argv)
+{
+	thrd_t *threads;
+	int *indexes;
+
+	if (argc > 1)
+		N = atoi(argv[1]);
+	if (N < 2) {
+		printf("Error: must have N >= 2\n");
+		return 1;
+	}
+	printf("N: %d\n", N);
+
+	threads = (thrd_t *)malloc((N + 1) * sizeof(thrd_t));
+	x = (std::atomic_int *)malloc(N * sizeof(std::atomic_int));
+	indexes = (int *)malloc((N + 1) * sizeof(int));
+	
+	for (int i = 0; i < N + 1; i++)
+		indexes[i] = i;
+
+	for (int i = 0; i < N; i++)
+		atomic_init(&x[i], 0);
+
+	for (int i = 0; i < N + 1; i++)
+		thrd_create(&threads[i], (thrd_start_t)&a, (void *)&indexes[i]);
+
+	for (int i = 0; i < N + 1; i++)
+		thrd_join(threads[i]);
+
+        return 0;
+}
-- 
2.34.1