diff options
author | 2012-02-20 04:08:52 +0000 | |
---|---|---|
committer | 2012-02-20 04:08:52 +0000 | |
commit | f77193dbb93e10052c9fb6526269b7b6e31f31b1 (patch) | |
tree | 0f17735607695bc6ab1a173cfd77226930f615c9 | |
parent | End the output with a newline (diff) | |
download | wireguard-openbsd-f77193dbb93e10052c9fb6526269b7b6e31f31b1.tar.xz wireguard-openbsd-f77193dbb93e10052c9fb6526269b7b6e31f31b1.zip |
Enable the errno test; add a quick rwlocks test
-rw-r--r-- | regress/lib/libpthread/Makefile | 7 | ||||
-rw-r--r-- | regress/lib/libpthread/pthread_rwlock/Makefile | 5 | ||||
-rw-r--r-- | regress/lib/libpthread/pthread_rwlock/pthread_rwlock.c | 152 |
3 files changed, 161 insertions, 3 deletions
diff --git a/regress/lib/libpthread/Makefile b/regress/lib/libpthread/Makefile index 41e9ec199dc..da07b2627b3 100644 --- a/regress/lib/libpthread/Makefile +++ b/regress/lib/libpthread/Makefile @@ -1,13 +1,14 @@ -# $OpenBSD: Makefile,v 1.31 2012/02/19 06:47:31 guenther Exp $ +# $OpenBSD: Makefile,v 1.32 2012/02/20 04:08:52 guenther Exp $ # disabled because they assume uthread's particular undefined behavior; # blocked_close blocked_dup2 blocked_shutdown SUBDIR= cancel cancel2 \ - close close_race closefrom cwd dup2_race execve fork \ + close close_race closefrom cwd dup2_race errno execve fork \ group malloc_duel netdb pcap poll preemption preemption_float \ pthread_atfork pthread_cond_timedwait pthread_create \ - pthread_join pthread_kill pthread_mutex pthread_specific \ + pthread_join pthread_kill pthread_mutex \ + pthread_rwlock pthread_specific \ readdir restart select semaphore setjmp setsockopt sigdeliver siginfo \ siginterrupt signal signals signodefer sigsuspend sigwait sleep \ socket stack stdarg stdio switch system diff --git a/regress/lib/libpthread/pthread_rwlock/Makefile b/regress/lib/libpthread/pthread_rwlock/Makefile new file mode 100644 index 00000000000..8d9900767b5 --- /dev/null +++ b/regress/lib/libpthread/pthread_rwlock/Makefile @@ -0,0 +1,5 @@ +# $OpenBSD: Makefile,v 1.1 2012/02/20 04:08:52 guenther Exp $ + +PROG= pthread_rwlock + +.include <bsd.regress.mk> diff --git a/regress/lib/libpthread/pthread_rwlock/pthread_rwlock.c b/regress/lib/libpthread/pthread_rwlock/pthread_rwlock.c new file mode 100644 index 00000000000..f5e77b27881 --- /dev/null +++ b/regress/lib/libpthread/pthread_rwlock/pthread_rwlock.c @@ -0,0 +1,152 @@ +/* $OpenBSD: pthread_rwlock.c,v 1.1 2012/02/20 04:08:52 guenther Exp $ */ +/* PUBLIC DOMAIN Feb 2012 <guenther@openbsd.org> */ + +#include <sys/types.h> +#include <assert.h> +#include <err.h> +#include <pthread.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +/* + * Set up an rwlock with a few reader threads, start a writer blocking, + * then let go the reader threads one by one. Verify that the writer + * thread gets, gets out, and then the rwlock can be locked for reading + * again. + */ + +pthread_rwlock_t rw; + +pthread_mutex_t m; +pthread_cond_t c; +enum +{ + UNLOCKED, + NUM_READERS = 6, + WRITE_STARTED, + WRITE, + WRITE_DONE, +} state; +time_t write_started; + +static void * +reader(void *arg) +{ + int me = *(int *)arg; + + pthread_mutex_lock(&m); + assert(state < NUM_READERS); + pthread_rwlock_rdlock(&rw); + state++; + printf("reader %d locked, state = %d\n", me, state); + pthread_cond_broadcast(&c); + pthread_mutex_unlock(&m); + + pthread_mutex_lock(&m); + while (state < WRITE_STARTED) { + pthread_cond_wait(&c, &m); + printf("reader %d woken, state = %d\n", me, state); + } + + int diff = difftime(time(NULL), write_started); + if (diff < 2) + sleep(3 - diff); + + pthread_rwlock_unlock(&rw); + printf("reader %d unlocked\n", me); + sleep(1); + + pthread_mutex_unlock(&m); + + pthread_mutex_lock(&m); + while (state >= WRITE_STARTED) { + pthread_cond_wait(&c, &m); + printf("reader %d woken, state = %d\n", me, state); + } + state++; + printf("reader %d trying again (%d)\n", me, state); + pthread_rwlock_rdlock(&rw); + printf("reader %d locked again (%d)\n", me, state); + pthread_cond_broadcast(&c); + while (state != NUM_READERS) { + pthread_cond_wait(&c, &m); + printf("reader %d woken, state = %d\n", me, state); + } + pthread_mutex_unlock(&m); + pthread_rwlock_unlock(&rw); + + printf("reader %d exiting\n", me); + return NULL; +} + +static void * +writer(void *arg) +{ + pthread_mutex_lock(&m); + printf("writer started, state = %d\n", state); + while (state != NUM_READERS) { + pthread_cond_wait(&c, &m); + printf("writer woken, state = %d\n", state); + } + state = WRITE_STARTED; + printf("writer starting\n"); + write_started = time(NULL); + pthread_cond_broadcast(&c); + pthread_mutex_unlock(&m); + + pthread_rwlock_wrlock(&rw); + printf("writer locked\n"); + + pthread_mutex_lock(&m); + state = WRITE; + pthread_cond_broadcast(&c); + + while (state == WRITE) + pthread_cond_wait(&c, &m); + + printf("writer unlocking\n"); + pthread_rwlock_unlock(&rw); + state = UNLOCKED; + pthread_cond_broadcast(&c); + pthread_mutex_unlock(&m); + + printf("writer exiting\n"); + return NULL; +} + + +int +main(void) +{ + pthread_t tr[NUM_READERS], tw; + int ids[NUM_READERS], i, r; + + pthread_rwlock_init(&rw, NULL); + pthread_mutex_init(&m, NULL); + pthread_cond_init(&c, NULL); + state = UNLOCKED; + + for (i = 0; i < NUM_READERS; i++) { + ids[i] = i; + if ((r = pthread_create(&tr[i], NULL, reader, &ids[i]))) + errx(1, "create %d: %s", i, strerror(r)); + } + + if ((r = pthread_create(&tw, NULL, writer, NULL))) + errx(1, "create writer: %s", strerror(r)); + + pthread_mutex_lock(&m); + while (state != WRITE) + pthread_cond_wait(&c, &m); + state = WRITE_DONE; + pthread_mutex_unlock(&m); + pthread_cond_broadcast(&c); + + pthread_join(tw, NULL); + + for (i = 0; i < NUM_READERS; i++) + pthread_join(tr[i], NULL); + return 0; +} |