summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_synch.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2007-03-09 22:41:01 +0000
committerjhb <jhb@FreeBSD.org>2007-03-09 22:41:01 +0000
commitf5e396934025920e30b32a3eef21d05548f16898 (patch)
tree343c44631b470578282dfd1c1d3fb73ed2833f3c /sys/kern/kern_synch.c
parentb470e17165153afeed8259afb043250b76f64e76 (diff)
downloadFreeBSD-src-f5e396934025920e30b32a3eef21d05548f16898.zip
FreeBSD-src-f5e396934025920e30b32a3eef21d05548f16898.tar.gz
Allow threads to atomically release rw and sx locks while waiting for an
event. Locking primitives that support this (mtx, rw, and sx) now each include their own foo_sleep() routine. - Rename msleep() to _sleep() and change it's 'struct mtx' object to a 'struct lock_object' pointer. _sleep() uses the recently added lc_unlock() and lc_lock() function pointers for the lock class of the specified lock to release the lock while the thread is suspended. - Add wrappers around _sleep() for mutexes (mtx_sleep()), rw locks (rw_sleep()), and sx locks (sx_sleep()). msleep() still exists and is now identical to mtx_sleep(), but it is deprecated. - Rename SLEEPQ_MSLEEP to SLEEPQ_SLEEP. - Rewrite much of sleep.9 to not be msleep(9) centric. - Flesh out the 'RETURN VALUES' section in sleep.9 and add an 'ERRORS' section. - Add __nonnull(1) to _sleep() and msleep_spin() so that the compiler will warn if you try to pass a NULL wait channel. The functions already have a KASSERT to that effect.
Diffstat (limited to 'sys/kern/kern_synch.c')
-rw-r--r--sys/kern/kern_synch.c61
1 files changed, 33 insertions, 28 deletions
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index 0edd670..25b77e3 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -112,21 +112,22 @@ sleepinit(void)
* call should be restarted if possible, and EINTR is returned if the system
* call should be interrupted by the signal (return EINTR).
*
- * The mutex argument is unlocked before the caller is suspended, and
- * re-locked before msleep returns. If priority includes the PDROP
- * flag the mutex is not re-locked before returning.
+ * The lock argument is unlocked before the caller is suspended, and
+ * re-locked before _sleep() returns. If priority includes the PDROP
+ * flag the lock is not re-locked before returning.
*/
int
-msleep(ident, mtx, priority, wmesg, timo)
+_sleep(ident, lock, priority, wmesg, timo)
void *ident;
- struct mtx *mtx;
+ struct lock_object *lock;
int priority, timo;
const char *wmesg;
{
struct thread *td;
struct proc *p;
- int catch, rval, flags, pri;
- WITNESS_SAVE_DECL(mtx);
+ struct lock_class *class;
+ int catch, flags, lock_state, pri, rval;
+ WITNESS_SAVE_DECL(lock_witness);
td = curthread;
p = td->td_proc;
@@ -134,12 +135,16 @@ msleep(ident, mtx, priority, wmesg, timo)
if (KTRPOINT(td, KTR_CSW))
ktrcsw(1, 0);
#endif
- WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, mtx == NULL ? NULL :
- &mtx->mtx_object, "Sleeping on \"%s\"", wmesg);
- KASSERT(timo != 0 || mtx_owned(&Giant) || mtx != NULL ||
- ident == &lbolt, ("sleeping without a mutex"));
+ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, lock,
+ "Sleeping on \"%s\"", wmesg);
+ KASSERT(timo != 0 || mtx_owned(&Giant) || lock != NULL ||
+ ident == &lbolt, ("sleeping without a lock"));
KASSERT(p != NULL, ("msleep1"));
KASSERT(ident != NULL && TD_IS_RUNNING(td), ("msleep"));
+ if (lock != NULL)
+ class = LOCK_CLASS(lock);
+ else
+ class = NULL;
if (cold) {
/*
@@ -150,8 +155,8 @@ msleep(ident, mtx, priority, wmesg, timo)
* splx(s);" to give interrupts a chance, but there is
* no way to give interrupts a chance now.
*/
- if (mtx != NULL && priority & PDROP)
- mtx_unlock(mtx);
+ if (lock != NULL && priority & PDROP)
+ class->lc_unlock(lock);
return (0);
}
catch = priority & PCATCH;
@@ -168,20 +173,21 @@ msleep(ident, mtx, priority, wmesg, timo)
if (ident == &pause_wchan)
flags = SLEEPQ_PAUSE;
else
- flags = SLEEPQ_MSLEEP;
+ flags = SLEEPQ_SLEEP;
if (catch)
flags |= SLEEPQ_INTERRUPTIBLE;
sleepq_lock(ident);
- CTR5(KTR_PROC, "msleep: thread %ld (pid %ld, %s) on %s (%p)",
+ CTR5(KTR_PROC, "sleep: thread %ld (pid %ld, %s) on %s (%p)",
td->td_tid, p->p_pid, p->p_comm, wmesg, ident);
DROP_GIANT();
- if (mtx != NULL) {
- mtx_assert(mtx, MA_OWNED | MA_NOTRECURSED);
- WITNESS_SAVE(&mtx->mtx_object, mtx);
- mtx_unlock(mtx);
- }
+ if (lock != NULL) {
+ WITNESS_SAVE(lock, lock_witness);
+ lock_state = class->lc_unlock(lock);
+ } else
+ /* GCC needs to follow the Yellow Brick Road */
+ lock_state = -1;
/*
* We put ourselves on the sleep queue and start our timeout
@@ -192,8 +198,7 @@ msleep(ident, mtx, priority, wmesg, timo)
* stopped, then td will no longer be on a sleep queue upon
* return from cursig().
*/
- sleepq_add(ident, ident == &lbolt ? NULL : &mtx->mtx_object, wmesg,
- flags, 0);
+ sleepq_add(ident, ident == &lbolt ? NULL : lock, wmesg, flags, 0);
if (timo)
sleepq_set_timeout(ident, timo);
@@ -222,9 +227,9 @@ msleep(ident, mtx, priority, wmesg, timo)
ktrcsw(0, 0);
#endif
PICKUP_GIANT();
- if (mtx != NULL && !(priority & PDROP)) {
- mtx_lock(mtx);
- WITNESS_RESTORE(&mtx->mtx_object, mtx);
+ if (lock != NULL && !(priority & PDROP)) {
+ class->lc_lock(lock, lock_state);
+ WITNESS_RESTORE(lock, lock_witness);
}
return (rval);
}
@@ -271,7 +276,7 @@ msleep_spin(ident, mtx, wmesg, timo)
/*
* We put ourselves on the sleep queue and start our timeout.
*/
- sleepq_add(ident, &mtx->mtx_object, wmesg, SLEEPQ_MSLEEP, 0);
+ sleepq_add(ident, &mtx->mtx_object, wmesg, SLEEPQ_SLEEP, 0);
if (timo)
sleepq_set_timeout(ident, timo);
@@ -336,7 +341,7 @@ wakeup(ident)
{
sleepq_lock(ident);
- sleepq_broadcast(ident, SLEEPQ_MSLEEP, -1, 0);
+ sleepq_broadcast(ident, SLEEPQ_SLEEP, -1, 0);
}
/*
@@ -350,7 +355,7 @@ wakeup_one(ident)
{
sleepq_lock(ident);
- sleepq_signal(ident, SLEEPQ_MSLEEP, -1, 0);
+ sleepq_signal(ident, SLEEPQ_SLEEP, -1, 0);
}
/*
OpenPOWER on IntegriCloud