summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_synch.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2007-05-08 21:49:59 +0000
committerjhb <jhb@FreeBSD.org>2007-05-08 21:49:59 +0000
commitb5754be873ffc482e02f0ca0302ed02455308b6e (patch)
tree322b0315af31f7940110eaa9dddf0b0069170f03 /sys/kern/kern_synch.c
parent23cec608a68684526dc8d307c87222af3aa2e0bf (diff)
downloadFreeBSD-src-b5754be873ffc482e02f0ca0302ed02455308b6e.zip
FreeBSD-src-b5754be873ffc482e02f0ca0302ed02455308b6e.tar.gz
Fix a potential LOR with sx_sleep() and cv_wait() with sx locks by
1) adding the thread to the sleepq via sleepq_add() before dropping the lock, and 2) dropping the sleepq lock around calls to lc_unlock() for sleepable locks (i.e. locks that use sleepq's in their implementation).
Diffstat (limited to 'sys/kern/kern_synch.c')
-rw-r--r--sys/kern/kern_synch.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index 6e23d0d..d61dddf 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -182,7 +182,7 @@ _sleep(ident, lock, priority, wmesg, timo)
td->td_tid, p->p_pid, p->p_comm, wmesg, ident);
DROP_GIANT();
- if (lock != NULL) {
+ if (lock != NULL && !(class->lc_flags & LC_SLEEPABLE)) {
WITNESS_SAVE(lock, lock_witness);
lock_state = class->lc_unlock(lock);
} else
@@ -201,6 +201,12 @@ _sleep(ident, lock, priority, wmesg, timo)
sleepq_add(ident, ident == &lbolt ? NULL : lock, wmesg, flags, 0);
if (timo)
sleepq_set_timeout(ident, timo);
+ if (lock != NULL && class->lc_flags & LC_SLEEPABLE) {
+ sleepq_release(ident);
+ WITNESS_SAVE(lock, lock_witness);
+ lock_state = class->lc_unlock(lock);
+ sleepq_lock(ident);
+ }
/*
* Adjust this thread's priority, if necessary.
OpenPOWER on IntegriCloud