diff options
author | rpj <rpj> | 2001-07-08 16:44:06 +0000 |
---|---|---|
committer | rpj <rpj> | 2001-07-08 16:44:06 +0000 |
commit | f58aab44e671bb39b8afb29804a9ca94c238c523 (patch) | |
tree | d1bac0558d5146c6468f8f421f22762f382c6c6e /tests/barrier5.c | |
parent | 704925281289e0f937eab045bd327b4275b2e03a (diff) |
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.
Diffstat (limited to 'tests/barrier5.c')
-rw-r--r-- | tests/barrier5.c | 93 |
1 files changed, 93 insertions, 0 deletions
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; +} |