From f58aab44e671bb39b8afb29804a9ca94c238c523 Mon Sep 17 00:00:00 2001 From: rpj Date: Sun, 8 Jul 2001 16:44:06 +0000 Subject: Barriers fixed and tested more extensively. * barrier.c: Fix several bugs in all routines. Now passes tests/barrier5.c which is fairly rigorous. There is still a non-optimal work-around for a race condition between the barrier breeched event signal and event wait. Basically the last (signalling) thread to hit the barrier yields to allow any other threads, which may have lost the race, to complete. tests/ChangeLog: * barrier3.c: Fixed. * barrier4.c: Fixed. * barrier5.c: New; proves that all threads in the group reaching the barrier wait and then resume together. Repeats the test using groups of 1 to 16 threads. Each group of threads must negotiate a large number of barriers (10000). * spin4.c: Fixed. * test.h (error_string): Modified the success (0) value. --- tests/ChangeLog | 11 +++++++ tests/GNUmakefile | 3 +- tests/Makefile | 3 +- tests/barrier3.c | 2 +- tests/barrier4.c | 12 ++++++- tests/barrier5.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/spin4.c | 2 +- tests/test.h | 2 +- 8 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 tests/barrier5.c (limited to 'tests') diff --git a/tests/ChangeLog b/tests/ChangeLog index 1c5d766..144454a 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,14 @@ +2001-07-09 Ross Johnson + + * barrier3.c: Fixed. + * barrier4.c: Fixed. + * barrier5.c: New; proves that all threads in the group + reaching the barrier wait and then resume together. Repeats the test + using groups of 1 to 16 threads. Each group of threads must negotiate + a large number of barriers (10000). + * spin4.c: Fixed. + * test.h (error_string): Modified the success (0) value. + 2001-07-07 Ross Johnson * spin3.c: Changed test and fixed. diff --git a/tests/GNUmakefile b/tests/GNUmakefile index f005664..d62e45c 100644 --- a/tests/GNUmakefile +++ b/tests/GNUmakefile @@ -49,7 +49,7 @@ TESTS = loadfree \ cleanup0 cleanup1 cleanup2 cleanup3 \ priority1 priority2 inherit1 \ spin1 spin2 spin3 spin4 \ - barrier1 barrier2 barrier3 barrier4 \ + barrier1 barrier2 barrier3 barrier4 barrier5 \ exception1 exception2 exception3 BENCHTESTS = \ @@ -96,6 +96,7 @@ barrier1.pass: barrier2.pass: barrier1.pass barrier3.pass: barrier2.pass barrier4.pass: barrier3.pass +barrier5.pass: barrier4.pass cancel1.pass: create1.pass cancel2.pass: cancel1.pass cancel2_1.pass: cancel2.pass diff --git a/tests/Makefile b/tests/Makefile index f3a4f91..dba30d3 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -58,7 +58,7 @@ PASSES= loadfree.pass \ cleanup0.pass cleanup1.pass cleanup2.pass cleanup3.pass \ priority1.pass priority2.pass inherit1.pass \ spin1.pass spin2.pass spin3.pass spin4.pass \ - barrier1.pass barrier2.pass barrier3.pass barrier4.pass \ + barrier1.pass barrier2.pass barrier3.pass barrier4.pass barrier5.pass \ exception1.pass exception2.pass exception3.pass BENCHRESULTS = \ @@ -151,6 +151,7 @@ barrier1.pass: barrier2.pass: barrier1.pass barrier3.pass: barrier2.pass barrier4.pass: barrier3.pass +barrier5.pass: barrier4.pass cancel1.pass: create1.pass cancel2.pass: cancel1.pass cancel3.pass: context1.pass diff --git a/tests/barrier3.c b/tests/barrier3.c index 97f6dc2..1fea5a1 100644 --- a/tests/barrier3.c +++ b/tests/barrier3.c @@ -28,7 +28,7 @@ main() assert(pthread_create(&t, NULL, func, NULL) == 0); - assert(pthread_join(t, (void *) &result) == 0); + assert(pthread_join(t, (void **) &result) == 0); assert(result == PTHREAD_BARRIER_SERIAL_THREAD); diff --git a/tests/barrier4.c b/tests/barrier4.c index 8f33e85..dd40b79 100644 --- a/tests/barrier4.c +++ b/tests/barrier4.c @@ -23,14 +23,24 @@ func(void * arg) int result = pthread_barrier_wait(&barrier); assert(pthread_mutex_lock(&mx) == 0); + +// printf("Barrier wait returned %d [%d]\n", result, WAIT_FAILED); +// fflush(stdout); + if (result == PTHREAD_BARRIER_SERIAL_THREAD) { serialThreadCount++; } - else + else if (0 == result) { otherThreadCount++; } + else + { + printf("Barrier wait failed: error = %s\n", error_string[result]); + fflush(stdout); + return NULL; + } assert(pthread_mutex_unlock(&mx) == 0); return NULL; diff --git a/tests/barrier5.c b/tests/barrier5.c new file mode 100644 index 0000000..6576b05 --- /dev/null +++ b/tests/barrier5.c @@ -0,0 +1,93 @@ +/* + * barrier5.c + * + * Declare a single barrier object, set up a sequence of + * barrier points to prove lockstepness, and then destroy it. + * + */ + +#include "test.h" + +enum { + NUMTHREADS = 16, + ITERATIONS = 10000 +}; + +pthread_barrier_t barrier = NULL; +pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER; + +int barrierReleases[ITERATIONS + 1]; + +void * +func(void * barrierHeight) +{ + int i; + int result; + + for (i = 1; i < ITERATIONS; i++) + { + result = pthread_barrier_wait(&barrier); + + assert(pthread_mutex_lock(&mx) == 0); + barrierReleases[i]++; + assert(pthread_mutex_unlock(&mx) == 0); + /* + * Confirm the correct number of releases from the previous + * barrier. We can't do the current barrier yet because there may + * still be threads waking up. + */ + if (result == PTHREAD_BARRIER_SERIAL_THREAD) + { + assert(pthread_mutex_lock(&mx) == 0); +//printf("Releases bucket %d = %d\n", i - 1, barrierReleases[i - 1]); +//fflush(stdout); + assert(barrierReleases[i - 1] == (int) barrierHeight); + barrierReleases[i + 1] = 0; + assert(pthread_mutex_unlock(&mx) == 0); + } + else if (result != 0) + { + printf("Barrier failed: result = %s\n", error_string[result]); + fflush(stdout); + return NULL; + } + } + + return NULL; +} + +int +main() +{ + int i, j; + pthread_t t[NUMTHREADS + 1]; + + for (j = 1; j <= NUMTHREADS; j++) + { + printf("Barrier height = %d\n", j); + + barrierReleases[0] = j; + barrierReleases[1] = 0; + + assert(pthread_barrier_init(&barrier, NULL, j) == 0); + + for (i = 1; i <= j; i++) + { + assert(pthread_create(&t[i], NULL, func, (void *) j) == 0); + } + + for (i = 1; i <= j; i++) + { + assert(pthread_join(t[i], NULL) == 0); + } + + assert(barrierReleases[ITERATIONS - 1] == j); + assert(barrierReleases[ITERATIONS] == 0); + + assert(pthread_barrier_destroy(&barrier) == 0); + } + + assert(pthread_mutex_destroy(&mx) == 0); + + return 0; +} diff --git a/tests/spin4.c b/tests/spin4.c index 5f04a27..8f73008 100644 --- a/tests/spin4.c +++ b/tests/spin4.c @@ -59,7 +59,7 @@ main() assert(pthread_spin_unlock(&lock) == 0); - assert(pthread_join(t, (void *) &result) == 0); + assert(pthread_join(t, (void **) &result) == 0); assert(result > 1000); assert(pthread_spin_destroy(&lock) == 0); diff --git a/tests/test.h b/tests/test.h index 018b215..c5b565d 100644 --- a/tests/test.h +++ b/tests/test.h @@ -13,7 +13,7 @@ #include char * error_string[] = { - "ZERO", + "ZERO_or_EOK", "EPERM", "ENOFILE_or_ENOENT", "ESRCH", -- cgit v1.2.3