summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Guenthe <guenther@cvs.openbsd.org>2010-04-12 03:34:32 +0000
committerPhilip Guenthe <guenther@cvs.openbsd.org>2010-04-12 03:34:32 +0000
commit2b52dc96f2f92c46e7f2a29a5b59a9ab66e115e8 (patch)
tree0d10d082cdd77af81f6d157b056083c0925b99d1
parent41c1a3e3e6683fe9b4edf023cd5a862fd79746b0 (diff)
Add pthread_rwlock_timed{rd,wr}lock().
Avoid missed wakeups in pthread_rwlock_{rd,wr}lock() by linking the spinlocks. ok tedu@
-rw-r--r--lib/librthread/rthread_sync.c71
1 files changed, 68 insertions, 3 deletions
diff --git a/lib/librthread/rthread_sync.c b/lib/librthread/rthread_sync.c
index 56b35d467dc..5644eb5cc1d 100644
--- a/lib/librthread/rthread_sync.c
+++ b/lib/librthread/rthread_sync.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread_sync.c,v 1.22 2009/11/27 19:45:54 guenther Exp $ */
+/* $OpenBSD: rthread_sync.c,v 1.23 2010/04/12 03:34:31 guenther Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -527,8 +527,9 @@ pthread_rwlock_rdlock(pthread_rwlock_t *lockp)
again:
_spinlock(&lock->lock);
if (lock->writer) {
+ _spinlock(&lock->sem.lock);
_spinunlock(&lock->lock);
- _sem_wait(&lock->sem, 0);
+ _sem_waitl(&lock->sem, 0, 0, NULL);
goto again;
}
lock->readers++;
@@ -538,6 +539,36 @@ again:
}
int
+pthread_rwlock_timedrdlock(pthread_rwlock_t *lockp,
+ const struct timespec *abstime)
+{
+ pthread_rwlock_t lock;
+ int do_wait = 1;
+ int error;
+
+ if ((error = _rthread_rwlock_ensure_init(lockp)))
+ return (error);
+
+ lock = *lockp;
+ _spinlock(&lock->lock);
+ while (lock->writer && do_wait) {
+ _spinlock(&lock->sem.lock);
+ _spinunlock(&lock->lock);
+ do_wait = _sem_waitl(&lock->sem, 0, CLOCK_REALTIME, abstime);
+ _spinlock(&lock->lock);
+ }
+ if (lock->writer) {
+ /* do_wait must be 0, so timed out */
+ _spinunlock(&lock->lock);
+ return (ETIMEDOUT);
+ }
+ lock->readers++;
+ _spinunlock(&lock->lock);
+
+ return (0);
+}
+
+int
pthread_rwlock_tryrdlock(pthread_rwlock_t *lockp)
{
pthread_rwlock_t lock;
@@ -573,10 +604,44 @@ pthread_rwlock_wrlock(pthread_rwlock_t *lockp)
_spinlock(&lock->lock);
lock->writer++;
while (lock->readers) {
+ _spinlock(&lock->sem.lock);
+ _spinunlock(&lock->lock);
+ _sem_waitl(&lock->sem, 0, 0, NULL);
+ _spinlock(&lock->lock);
+ }
+ lock->readers = -pthread_self()->tid;
+ _spinunlock(&lock->lock);
+
+ return (0);
+}
+
+int
+pthread_rwlock_timedwrlock(pthread_rwlock_t *lockp,
+ const struct timespec *abstime)
+{
+ pthread_rwlock_t lock;
+ int do_wait = 1;
+ int error;
+
+ if ((error = _rthread_rwlock_ensure_init(lockp)))
+ return (error);
+
+ lock = *lockp;
+
+ _spinlock(&lock->lock);
+ lock->writer++;
+ while (lock->readers && do_wait) {
+ _spinlock(&lock->sem.lock);
_spinunlock(&lock->lock);
- _sem_wait(&lock->sem, 0);
+ do_wait = _sem_waitl(&lock->sem, 0, CLOCK_REALTIME, abstime);
_spinlock(&lock->lock);
}
+ if (lock->readers) {
+ /* do_wait must be 0, so timed out */
+ lock->writer--;
+ _spinunlock(&lock->lock);
+ return (ETIMEDOUT);
+ }
lock->readers = -pthread_self()->tid;
_spinunlock(&lock->lock);