From 41d403a758afbfbe951e96ebb9461eb4b245363d Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 2 Nov 2012 16:23:10 -0700 Subject: [PATCH 1/1] mpmc-queue: expand to 2R2W, 2R1W, 1R2W tests I rewrote the test to allow a configurable number of readers and writers, but then I figured out that our model-checker doesn't support optarg() and its global optind properly, when using mmap()/mprotect() snapshotting (it doesn't add the optarg library to be snapshotted...) So, this test grows to 3 separate source files, at least for now. The only change is the number of reader and writer threads. --- mpmc-queue/.gitignore | 2 + mpmc-queue/Makefile | 5 +- mpmc-queue/mpmc-1r2w.cc | 101 +++++++++++++++++++++++++++++++++++++++ mpmc-queue/mpmc-2r1w.cc | 101 +++++++++++++++++++++++++++++++++++++++ mpmc-queue/mpmc-queue.cc | 71 +++++++++++++++++++++++---- 5 files changed, 269 insertions(+), 11 deletions(-) create mode 100644 mpmc-queue/mpmc-1r2w.cc create mode 100644 mpmc-queue/mpmc-2r1w.cc diff --git a/mpmc-queue/.gitignore b/mpmc-queue/.gitignore index 4b0d836..6166337 100644 --- a/mpmc-queue/.gitignore +++ b/mpmc-queue/.gitignore @@ -1 +1,3 @@ /mpmc-queue +/mpmc-1r2w +/mpmc-2r1w diff --git a/mpmc-queue/Makefile b/mpmc-queue/Makefile index 07e2540..6636fcd 100644 --- a/mpmc-queue/Makefile +++ b/mpmc-queue/Makefile @@ -1,10 +1,11 @@ include ../benchmarks.mk TESTNAME = mpmc-queue +TESTS = mpmc-queue mpmc-1r2w mpmc-2r1w -all: $(TESTNAME) +all: $(TESTS) -$(TESTNAME): $(TESTNAME).cc $(TESTNAME).h +%: %.cc $(TESTNAME).h $(CXX) -o $@ $< $(CPPFLAGS) $(LDFLAGS) clean: diff --git a/mpmc-queue/mpmc-1r2w.cc b/mpmc-queue/mpmc-1r2w.cc new file mode 100644 index 0000000..78c9597 --- /dev/null +++ b/mpmc-queue/mpmc-1r2w.cc @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include + +#include + +#include "mpmc-queue.h" + +void threadA(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin = queue->write_prepare(); + store_32(bin, 1); + queue->write_publish(); +} + +void threadB(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin; + while (bin = queue->read_fetch()) { + printf("Read: %d\n", load_32(bin)); + queue->read_consume(); + } +} + +#define MAXREADERS 3 +#define MAXWRITERS 3 + +int readers = 1, writers = 2; + +void print_usage() +{ + printf("Error: use the following options\n" + " -r Choose number of reader threads\n" + " -w Choose number of writer threads\n"); + exit(EXIT_FAILURE); +} + +void process_params(int argc, char **argv) +{ + const char *shortopts = "hr:w:"; + int opt; + bool error = false; + + while (!error && (opt = getopt(argc, argv, shortopts)) != -1) { + switch (opt) { + case 'h': + print_usage(); + break; + case 'r': + readers = atoi(optarg); + break; + case 'w': + writers = atoi(optarg); + break; + default: /* '?' */ + error = true; + break; + } + } + + if (writers < 1 || writers > MAXWRITERS) + error = true; + if (readers < 1 || readers > MAXREADERS) + error = true; + + if (error) + print_usage(); +} + +int user_main(int argc, char **argv) +{ + struct mpmc_boundq_1_alt queue; + thrd_t A[MAXWRITERS], B[MAXREADERS]; + + /* Note: optarg() / optind is broken in model-checker - workaround is + * to just copy&paste this test a few times */ + //process_params(argc, argv); + printf("%d reader(s), %d writer(s)\n", readers, writers); + + int32_t *bin = queue.write_prepare(); + store_32(bin, 17); + queue.write_publish(); + + printf("Start threads\n"); + + for (int i = 0; i < writers; i++) + thrd_create(&A[i], (thrd_start_t)&threadA, &queue); + for (int i = 0; i < readers; i++) + thrd_create(&B[i], (thrd_start_t)&threadB, &queue); + + for (int i = 0; i < writers; i++) + thrd_join(A[i]); + for (int i = 0; i < readers; i++) + thrd_join(B[i]); + + printf("Threads complete\n"); + + return 0; +} diff --git a/mpmc-queue/mpmc-2r1w.cc b/mpmc-queue/mpmc-2r1w.cc new file mode 100644 index 0000000..8fc4652 --- /dev/null +++ b/mpmc-queue/mpmc-2r1w.cc @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include + +#include + +#include "mpmc-queue.h" + +void threadA(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin = queue->write_prepare(); + store_32(bin, 1); + queue->write_publish(); +} + +void threadB(struct mpmc_boundq_1_alt *queue) +{ + int32_t *bin; + while (bin = queue->read_fetch()) { + printf("Read: %d\n", load_32(bin)); + queue->read_consume(); + } +} + +#define MAXREADERS 3 +#define MAXWRITERS 3 + +int readers = 2, writers = 1; + +void print_usage() +{ + printf("Error: use the following options\n" + " -r Choose number of reader threads\n" + " -w Choose number of writer threads\n"); + exit(EXIT_FAILURE); +} + +void process_params(int argc, char **argv) +{ + const char *shortopts = "hr:w:"; + int opt; + bool error = false; + + while (!error && (opt = getopt(argc, argv, shortopts)) != -1) { + switch (opt) { + case 'h': + print_usage(); + break; + case 'r': + readers = atoi(optarg); + break; + case 'w': + writers = atoi(optarg); + break; + default: /* '?' */ + error = true; + break; + } + } + + if (writers < 1 || writers > MAXWRITERS) + error = true; + if (readers < 1 || readers > MAXREADERS) + error = true; + + if (error) + print_usage(); +} + +int user_main(int argc, char **argv) +{ + struct mpmc_boundq_1_alt queue; + thrd_t A[MAXWRITERS], B[MAXREADERS]; + + /* Note: optarg() / optind is broken in model-checker - workaround is + * to just copy&paste this test a few times */ + //process_params(argc, argv); + printf("%d reader(s), %d writer(s)\n", readers, writers); + + int32_t *bin = queue.write_prepare(); + store_32(bin, 17); + queue.write_publish(); + + printf("Start threads\n"); + + for (int i = 0; i < writers; i++) + thrd_create(&A[i], (thrd_start_t)&threadA, &queue); + for (int i = 0; i < readers; i++) + thrd_create(&B[i], (thrd_start_t)&threadB, &queue); + + for (int i = 0; i < writers; i++) + thrd_join(A[i]); + for (int i = 0; i < readers; i++) + thrd_join(B[i]); + + printf("Threads complete\n"); + + return 0; +} diff --git a/mpmc-queue/mpmc-queue.cc b/mpmc-queue/mpmc-queue.cc index 741811a..d6271be 100644 --- a/mpmc-queue/mpmc-queue.cc +++ b/mpmc-queue/mpmc-queue.cc @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include @@ -22,10 +24,60 @@ void threadB(struct mpmc_boundq_1_alt *queue) } } +#define MAXREADERS 3 +#define MAXWRITERS 3 + +int readers = 2, writers = 2; + +void print_usage() +{ + printf("Error: use the following options\n" + " -r Choose number of reader threads\n" + " -w Choose number of writer threads\n"); + exit(EXIT_FAILURE); +} + +void process_params(int argc, char **argv) +{ + const char *shortopts = "hr:w:"; + int opt; + bool error = false; + + while (!error && (opt = getopt(argc, argv, shortopts)) != -1) { + switch (opt) { + case 'h': + print_usage(); + break; + case 'r': + readers = atoi(optarg); + break; + case 'w': + writers = atoi(optarg); + break; + default: /* '?' */ + error = true; + break; + } + } + + if (writers < 1 || writers > MAXWRITERS) + error = true; + if (readers < 1 || readers > MAXREADERS) + error = true; + + if (error) + print_usage(); +} + int user_main(int argc, char **argv) { struct mpmc_boundq_1_alt queue; - thrd_t A1, A2, B1, B2; + thrd_t A[MAXWRITERS], B[MAXREADERS]; + + /* Note: optarg() / optind is broken in model-checker - workaround is + * to just copy&paste this test a few times */ + //process_params(argc, argv); + printf("%d reader(s), %d writer(s)\n", readers, writers); int32_t *bin = queue.write_prepare(); store_32(bin, 17); @@ -33,14 +85,15 @@ int user_main(int argc, char **argv) printf("Start threads\n"); - thrd_create(&A1, (thrd_start_t)&threadA, &queue); - thrd_create(&A2, (thrd_start_t)&threadA, &queue); - thrd_create(&B1, (thrd_start_t)&threadB, &queue); - thrd_create(&B2, (thrd_start_t)&threadB, &queue); - thrd_join(A1); - thrd_join(A2); - thrd_join(B1); - thrd_join(B2); + for (int i = 0; i < writers; i++) + thrd_create(&A[i], (thrd_start_t)&threadA, &queue); + for (int i = 0; i < readers; i++) + thrd_create(&B[i], (thrd_start_t)&threadB, &queue); + + for (int i = 0; i < writers; i++) + thrd_join(A[i]); + for (int i = 0; i < readers; i++) + thrd_join(B[i]); printf("Threads complete\n"); -- 2.34.1