summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/waitq.c
diff options
context:
space:
mode:
authorakolb <none@none>2007-09-04 15:02:11 -0700
committerakolb <none@none>2007-09-04 15:02:11 -0700
commitb7e32555fc1a5af52617bd619aa97d5e6868f7ef (patch)
treed886959e6f76e4e6fd193eb4eff663148662a4cf /usr/src/uts/common/os/waitq.c
parentfe13b8ce8dfbfa2bdfc6fe9d3cc6fd5d9714f1b1 (diff)
downloadillumos-joyent-b7e32555fc1a5af52617bd619aa97d5e6868f7ef.tar.gz
6598427 waitq_runall() doesn't like being interrupted
Diffstat (limited to 'usr/src/uts/common/os/waitq.c')
-rw-r--r--usr/src/uts/common/os/waitq.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/usr/src/uts/common/os/waitq.c b/usr/src/uts/common/os/waitq.c
index 802d7afdc4..276026a02e 100644
--- a/usr/src/uts/common/os/waitq.c
+++ b/usr/src/uts/common/os/waitq.c
@@ -266,10 +266,11 @@ waitq_dequeue(waitq_t *wq, kthread_t *t)
DTRACE_SCHED1(cpucaps__wakeup, kthread_t *, t);
/*
- * Change thread to transition state without dropping
- * the wait queue lock.
+ * Change thread to transition state and drop the wait queue lock. The
+ * thread will remain locked since its t_lockp points to the
+ * transition_lock.
*/
- THREAD_TRANSITION_NOLOCK(t);
+ THREAD_TRANSITION(t);
}
/*
@@ -297,8 +298,6 @@ waitq_setrun(kthread_t *t)
if (wq == NULL)
panic("waitq_setrun: thread %p is not on waitq", t);
waitq_dequeue(wq, t);
-
- disp_lock_exit_high(&wq->wq_lock);
CL_SETRUN(t);
}
@@ -311,9 +310,13 @@ waitq_takeone(waitq_t *wq)
kthread_t *t;
disp_lock_enter(&wq->wq_lock);
+ /*
+ * waitq_dequeue drops wait queue lock but leaves the CPU at high PIL.
+ */
if ((t = wq->wq_first) != NULL)
waitq_dequeue(wq, wq->wq_first);
- disp_lock_exit(&wq->wq_lock);
+ else
+ disp_lock_exit(&wq->wq_lock);
return (t);
}
@@ -328,8 +331,14 @@ waitq_runfirst(waitq_t *wq)
t = waitq_takeone(wq);
if (t != NULL) {
+ /*
+ * t should have transition lock held.
+ * CL_SETRUN() will replace it with dispq lock and keep it held.
+ * thread_unlock() will drop dispq lock and restore PIL.
+ */
+ ASSERT(THREAD_LOCK_HELD(t));
CL_SETRUN(t);
- thread_unlock(t); /* drops dispq lock */
+ thread_unlock(t);
}
return (t);
}