summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_condvar.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2004-08-19 11:31:42 +0000
committerjhb <jhb@FreeBSD.org>2004-08-19 11:31:42 +0000
commit9e08178eb7f76d4c0238edff1e39930e0d6ee70e (patch)
tree0e4978383f95ccaee9fad964201d8694bc8eaf63 /sys/kern/kern_condvar.c
parent4b7b5c6f6a763532ffe2c98abd2a233bb1484224 (diff)
downloadFreeBSD-src-9e08178eb7f76d4c0238edff1e39930e0d6ee70e.zip
FreeBSD-src-9e08178eb7f76d4c0238edff1e39930e0d6ee70e.tar.gz
Now that the return value semantics of cv's for multithreaded processes
have been unified with that of msleep(9), further refine the sleepq interface and consolidate some duplicated code: - Move the pre-sleep checks for theaded processes into a thread_sleep_check() function in kern_thread.c. - Move all handling of TDF_SINTR to be internal to subr_sleepqueue.c. Specifically, if a thread is awakened by something other than a signal while checking for signals before going to sleep, clear TDF_SINTR in sleepq_catch_signals(). This removes a sched_lock lock/unlock combo in that edge case during an interruptible sleep. Also, fix sleepq_check_signals() to properly handle the condition if TDF_SINTR is clear rather than requiring the callers of the sleepq API to notice this edge case and call a non-_sig variant of sleepq_wait(). - Clarify the flags arguments to sleepq_add(), sleepq_signal() and sleepq_broadcast() by creating an explicit submask for sleepq types. Also, add an explicit SLEEPQ_MSLEEP type rather than a magic number of 0. Also, add a SLEEPQ_INTERRUPTIBLE flag for use with sleepq_add() and move the setting of TDF_SINTR to sleepq_add() if this flag is set rather than sleepq_catch_signals(). Note that it is the caller's responsibility to ensure that sleepq_catch_signals() is called if and only if this flag is passed to the preceeding sleepq_add(). Note that this also removes a sched_lock lock/unlock pair from sleepq_catch_signals(). It also ensures that for an interruptible sleep, TDF_SINTR is always set when TD_ON_SLEEPQ() is true.
Diffstat (limited to 'sys/kern/kern_condvar.c')
-rw-r--r--sys/kern/kern_condvar.c55
1 files changed, 16 insertions, 39 deletions
diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c
index ff619ec..fc0f799 100644
--- a/sys/kern/kern_condvar.c
+++ b/sys/kern/kern_condvar.c
@@ -153,7 +153,6 @@ cv_wait_sig(struct cv *cvp, struct mtx *mp)
td = curthread;
p = td->td_proc;
- rval = 0;
#ifdef KTRACE
if (KTRPOINT(td, KTR_CSW))
ktrcsw(1, 0);
@@ -180,32 +179,21 @@ cv_wait_sig(struct cv *cvp, struct mtx *mp)
* thread or if our thread is marked as interrupted.
*/
mtx_lock_spin(&sched_lock);
- if (p->p_flag & P_SA || p->p_numthreads > 1) {
- if ((p->p_flag & P_SINGLE_EXIT) && p->p_singlethread != td)
- rval = EINTR;
- else if (td->td_flags & TDF_INTERRUPT)
- rval = td->td_intrval;
- if (rval != 0) {
- mtx_unlock_spin(&sched_lock);
- sleepq_release(cvp);
- return (rval);
- }
- }
+ rval = thread_sleep_check(td);
mtx_unlock_spin(&sched_lock);
+ if (rval != 0) {
+ sleepq_release(cvp);
+ return (rval);
+ }
cvp->cv_waiters++;
DROP_GIANT();
mtx_unlock(mp);
- sleepq_add(sq, cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR);
+ sleepq_add(sq, cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR |
+ SLEEPQ_INTERRUPTIBLE);
sig = sleepq_catch_signals(cvp);
- if (sig == 0 && !TD_ON_SLEEPQ(td)) {
- mtx_lock_spin(&sched_lock);
- td->td_flags &= ~TDF_SINTR;
- mtx_unlock_spin(&sched_lock);
- sleepq_wait(cvp);
- } else
- rval = sleepq_wait_sig(cvp);
+ rval = sleepq_wait_sig(cvp);
if (rval == 0)
rval = sleepq_calc_signal_retval(sig);
@@ -320,33 +308,22 @@ cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo)
* thread or if our thread is marked as interrupted.
*/
mtx_lock_spin(&sched_lock);
- if (p->p_flag & P_SA || p->p_numthreads > 1) {
- if ((p->p_flag & P_SINGLE_EXIT) && p->p_singlethread != td)
- rval = EINTR;
- else if (td->td_flags & TDF_INTERRUPT)
- rval = td->td_intrval;
- if (rval != 0) {
- mtx_unlock_spin(&sched_lock);
- sleepq_release(cvp);
- return (rval);
- }
- }
+ rval = thread_sleep_check(td);
mtx_unlock_spin(&sched_lock);
+ if (rval != 0) {
+ sleepq_release(cvp);
+ return (rval);
+ }
cvp->cv_waiters++;
DROP_GIANT();
mtx_unlock(mp);
- sleepq_add(sq, cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR);
+ sleepq_add(sq, cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR |
+ SLEEPQ_INTERRUPTIBLE);
sleepq_set_timeout(cvp, timo);
sig = sleepq_catch_signals(cvp);
- if (sig == 0 && !TD_ON_SLEEPQ(td)) {
- mtx_lock_spin(&sched_lock);
- td->td_flags &= ~TDF_SINTR;
- mtx_unlock_spin(&sched_lock);
- rval = sleepq_timedwait(cvp);
- } else
- rval = sleepq_timedwait_sig(cvp, sig != 0);
+ rval = sleepq_timedwait_sig(cvp, sig != 0);
if (rval == 0)
rval = sleepq_calc_signal_retval(sig);
OpenPOWER on IntegriCloud