Do a similar tuneup on pthread_cond_signal() and

pthread_cond_broadcast(): use double-checked locking to avoid
pthread__self() and pthread_spinlock() when signaling or broadcasting
on a condition variable with no waiters.
This commit is contained in:
nathanw 2003-01-31 04:26:50 +00:00
parent 6cca91fc86
commit 69367db47f
1 changed files with 25 additions and 21 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: pthread_cond.c,v 1.3 2003/01/27 21:01:01 nathanw Exp $ */ /* $NetBSD: pthread_cond.c,v 1.4 2003/01/31 04:26:50 nathanw Exp $ */
/*- /*-
* Copyright (c) 2001 The NetBSD Foundation, Inc. * Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -267,21 +267,23 @@ pthread_cond_signal(pthread_cond_t *cond)
#endif #endif
PTHREADD_ADD(PTHREADD_COND_SIGNAL); PTHREADD_ADD(PTHREADD_COND_SIGNAL);
self = pthread__self();
SDPRINTF(("(cond signal %p) Signaling %p\n", SDPRINTF(("(cond signal %p) Signaling %p\n",
self, cond)); pthread__self(), cond));
pthread_spinlock(self, &cond->ptc_lock); if (!PTQ_EMPTY(&cond->ptc_waiters)) {
signaled = PTQ_FIRST(&cond->ptc_waiters); self = pthread__self();
if (signaled != NULL) pthread_spinlock(self, &cond->ptc_lock);
PTQ_REMOVE(&cond->ptc_waiters, signaled, pt_sleep); signaled = PTQ_FIRST(&cond->ptc_waiters);
if (signaled != NULL)
PTQ_REMOVE(&cond->ptc_waiters, signaled, pt_sleep);
#ifdef ERRORCHECK #ifdef ERRORCHECK
if (PTQ_EMPTY(&cond->ptc_waiters)) if (PTQ_EMPTY(&cond->ptc_waiters))
cond->ptc_mutex = NULL; cond->ptc_mutex = NULL;
#endif #endif
if (signaled != NULL) if (signaled != NULL)
pthread__sched(self, signaled); pthread__sched(self, signaled);
pthread_spinunlock(self, &cond->ptc_lock); pthread_spinunlock(self, &cond->ptc_lock);
}
return 0; return 0;
} }
@ -298,19 +300,21 @@ pthread_cond_broadcast(pthread_cond_t *cond)
#endif #endif
PTHREADD_ADD(PTHREADD_COND_BROADCAST); PTHREADD_ADD(PTHREADD_COND_BROADCAST);
self = pthread__self();
SDPRINTF(("(cond signal %p) Broadcasting %p\n", SDPRINTF(("(cond signal %p) Broadcasting %p\n",
self, cond)); pthread__self(), cond));
pthread_spinlock(self, &cond->ptc_lock); if (!PTQ_EMPTY(&cond->ptc_waiters)) {
blockedq = cond->ptc_waiters; self = pthread__self();
PTQ_INIT(&cond->ptc_waiters); pthread_spinlock(self, &cond->ptc_lock);
blockedq = cond->ptc_waiters;
PTQ_INIT(&cond->ptc_waiters);
#ifdef ERRORCHECK #ifdef ERRORCHECK
cond->ptc_mutex = NULL; cond->ptc_mutex = NULL;
#endif #endif
PTQ_FOREACH(signaled, &blockedq, pt_sleep) PTQ_FOREACH(signaled, &blockedq, pt_sleep)
pthread__sched(self, signaled); pthread__sched(self, signaled);
pthread_spinunlock(self, &cond->ptc_lock); pthread_spinunlock(self, &cond->ptc_lock);
}
return 0; return 0;