summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_synch.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-08-07 21:00:13 +0000
committerjhb <jhb@FreeBSD.org>2008-08-07 21:00:13 +0000
commite306c86e1b6376905ae8d21091509cbe1f61fba8 (patch)
tree5341583d2eecb5e89baa3cba762d2f3739e4856a /sys/kern/kern_synch.c
parent9f16e510b9a765d8caed7f31ebaf16b600540db4 (diff)
downloadFreeBSD-src-e306c86e1b6376905ae8d21091509cbe1f61fba8.zip
FreeBSD-src-e306c86e1b6376905ae8d21091509cbe1f61fba8.tar.gz
Permit Giant to be passed as the explicit interlock either to
msleep/mtx_sleep or the various cv_*wait*() routines. Currently, the "unlock" behavior of PDROP and cv_wait_unlock() with Giant is not permitted as it is will be confusing since Giant is fully unrecursed and unlocked during a thread sleep. This is handy for subsystems which wish to allow unlocked drivers to continue to use Giant such as CAM, the new TTY layer, and the new USB stack. CAM currently uses a hack that I told Scott to use because I really didn't want to permit this behavior, and the TTY and USB patches both have various patches to permit this. MFC after: 2 weeks
Diffstat (limited to 'sys/kern/kern_synch.c')
-rw-r--r--sys/kern/kern_synch.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index 6c10ba4..ef682f4 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -140,6 +140,9 @@ _sleep(void *ident, struct lock_object *lock, int priority,
ident == &lbolt, ("sleeping without a lock"));
KASSERT(p != NULL, ("msleep1"));
KASSERT(ident != NULL && TD_IS_RUNNING(td), ("msleep"));
+ if (priority & PDROP)
+ KASSERT(lock != NULL && lock != &Giant.lock_object,
+ ("PDROP requires a non-Giant lock"));
if (lock != NULL)
class = LOCK_CLASS(lock);
else
@@ -182,7 +185,8 @@ _sleep(void *ident, struct lock_object *lock, int priority,
td->td_tid, p->p_pid, td->td_name, wmesg, ident);
DROP_GIANT();
- if (lock != NULL && !(class->lc_flags & LC_SLEEPABLE)) {
+ if (lock != NULL && lock != &Giant.lock_object &&
+ !(class->lc_flags & LC_SLEEPABLE)) {
WITNESS_SAVE(lock, lock_witness);
lock_state = class->lc_unlock(lock);
} else
@@ -222,7 +226,7 @@ _sleep(void *ident, struct lock_object *lock, int priority,
ktrcsw(0, 0);
#endif
PICKUP_GIANT();
- if (lock != NULL && !(priority & PDROP)) {
+ if (lock != NULL && lock != &Giant.lock_object && !(priority & PDROP)) {
class->lc_lock(lock, lock_state);
WITNESS_RESTORE(lock, lock_witness);
}
OpenPOWER on IntegriCloud