summaryrefslogtreecommitdiffstats
path: root/lib/libthr
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2007-11-21 06:01:02 +0000
committerdavidxu <davidxu@FreeBSD.org>2007-11-21 06:01:02 +0000
commitdf28d4b72f5b72653df344622ae8461f17512038 (patch)
tree234728425e81abd800eb478202fda01424c2bfca /lib/libthr
parent605bcd0e65435f111196a1b72d58370bf5daeba2 (diff)
downloadFreeBSD-src-df28d4b72f5b72653df344622ae8461f17512038.zip
FreeBSD-src-df28d4b72f5b72653df344622ae8461f17512038.tar.gz
Reuse nwaiter member field to record number of waiters, in sem_post(),
this should reduce the chance having to do a syscall when there is no waiter in the semaphore.
Diffstat (limited to 'lib/libthr')
-rw-r--r--lib/libthr/thread/thr_sem.c38
1 files changed, 31 insertions, 7 deletions
diff --git a/lib/libthr/thread/thr_sem.c b/lib/libthr/thread/thr_sem.c
index 01557f3..3953590 100644
--- a/lib/libthr/thread/thr_sem.c
+++ b/lib/libthr/thread/thr_sem.c
@@ -172,6 +172,14 @@ _sem_trywait(sem_t *sem)
return (-1);
}
+static void
+sem_cancel_handler(void *arg)
+{
+ sem_t *sem = arg;
+
+ atomic_add_int(&(*sem)->nwaiters, -1);
+}
+
int
_sem_wait(sem_t *sem)
{
@@ -191,13 +199,19 @@ _sem_wait(sem_t *sem)
_pthread_testcancel();
do {
+ atomic_add_int(&(*sem)->nwaiters, 1);
while ((val = (*sem)->count) > 0) {
- if (atomic_cmpset_acq_int(&(*sem)->count, val, val - 1))
+ if (atomic_cmpset_acq_int(&(*sem)->count, val, val - 1)) {
+ atomic_add_int(&(*sem)->nwaiters, -1);
return (0);
+ }
}
+ THR_CLEANUP_PUSH(curthread, sem_cancel_handler, sem);
_thr_cancel_enter(curthread);
retval = _thr_umtx_wait_uint(&(*sem)->count, 0, NULL);
+ atomic_add_int(&(*sem)->nwaiters, -1);
_thr_cancel_leave(curthread);
+ THR_CLEANUP_POP(curthread, 0);
} while (retval == 0);
errno = retval;
return (-1);
@@ -228,19 +242,26 @@ _sem_timedwait(sem_t * __restrict sem,
*/
_pthread_testcancel();
do {
+ atomic_add_int(&(*sem)->nwaiters, 1);
while ((val = (*sem)->count) > 0) {
- if (atomic_cmpset_acq_int(&(*sem)->count, val, val - 1))
+ if (atomic_cmpset_acq_int(&(*sem)->count, val, val - 1)) {
+ atomic_add_int(&(*sem)->nwaiters, -1);
return (0);
+ }
}
if (abstime == NULL) {
+ atomic_add_int(&(*sem)->nwaiters, -1);
errno = EINVAL;
return (-1);
}
+ THR_CLEANUP_PUSH(curthread, sem_cancel_handler, sem);
clock_gettime(CLOCK_REALTIME, &ts);
TIMESPEC_SUB(&ts2, abstime, &ts);
_thr_cancel_enter(curthread);
retval = _thr_umtx_wait_uint(&(*sem)->count, 0, &ts2);
+ atomic_add_int(&(*sem)->nwaiters, -1);
_thr_cancel_leave(curthread);
+ THR_CLEANUP_POP(curthread, 0);
} while (retval == 0);
errno = retval;
return (-1);
@@ -249,7 +270,7 @@ _sem_timedwait(sem_t * __restrict sem,
int
_sem_post(sem_t *sem)
{
- int val, retval;
+ int val, retval = 0;
if (sem_check_validity(sem) != 0)
return (-1);
@@ -263,9 +284,12 @@ _sem_post(sem_t *sem)
*/
do {
val = (*sem)->count;
- } while (!atomic_cmpset_acq_int(&(*sem)->count, val, val + 1));
- retval = _thr_umtx_wake(&(*sem)->count, val + 1);
- if (retval > 0)
- retval = 0;
+ } while (!atomic_cmpset_rel_int(&(*sem)->count, val, val + 1));
+
+ if ((*sem)->nwaiters) {
+ retval = _thr_umtx_wake(&(*sem)->count, val + 1);
+ if (retval > 0)
+ retval = 0;
+ }
return (retval);
}
OpenPOWER on IntegriCloud