diff options
author | jhb <jhb@FreeBSD.org> | 2004-08-19 11:31:42 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2004-08-19 11:31:42 +0000 |
commit | 9e08178eb7f76d4c0238edff1e39930e0d6ee70e (patch) | |
tree | 0e4978383f95ccaee9fad964201d8694bc8eaf63 /sys/kern/kern_condvar.c | |
parent | 4b7b5c6f6a763532ffe2c98abd2a233bb1484224 (diff) | |
download | FreeBSD-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.c | 55 |
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); |