From 1066ff319f565bb63268c1e6b6f48c114aac34b2 Mon Sep 17 00:00:00 2001 From: Brian Norris 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 +#include +#include + +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 +#include +#include + +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 +#include +#include + +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 +#include +#include +#include + +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 +#include +#include + +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 +#include +#include +#include + +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