summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorguenther <guenther@openbsd.org>2012-02-20 04:08:52 +0000
committerguenther <guenther@openbsd.org>2012-02-20 04:08:52 +0000
commitf77193dbb93e10052c9fb6526269b7b6e31f31b1 (patch)
tree0f17735607695bc6ab1a173cfd77226930f615c9
parentEnd the output with a newline (diff)
downloadwireguard-openbsd-f77193dbb93e10052c9fb6526269b7b6e31f31b1.tar.xz
wireguard-openbsd-f77193dbb93e10052c9fb6526269b7b6e31f31b1.zip
Enable the errno test; add a quick rwlocks test
-rw-r--r--regress/lib/libpthread/Makefile7
-rw-r--r--regress/lib/libpthread/pthread_rwlock/Makefile5
-rw-r--r--regress/lib/libpthread/pthread_rwlock/pthread_rwlock.c152
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;
+}