diff options
author | jhb <jhb@FreeBSD.org> | 2004-08-10 17:42:59 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2004-08-10 17:42:59 +0000 |
commit | 15d4b7d98976d7d09a3d371553d20db7335b1201 (patch) | |
tree | bd2ed9387076d3103e0ad939d2631f757584906e /sys/kern | |
parent | 70cf64bec6da3afac373b7fb024de49045689191 (diff) | |
download | FreeBSD-src-15d4b7d98976d7d09a3d371553d20db7335b1201.zip FreeBSD-src-15d4b7d98976d7d09a3d371553d20db7335b1201.tar.gz |
Synchronize the extra SA threading checks and return value handling of
condition variables with that of msleep().
Reviewed by: davidxu
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_condvar.c | 74 |
1 files changed, 50 insertions, 24 deletions
diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c index 64a8224..ff619ec 100644 --- a/sys/kern/kern_condvar.c +++ b/sys/kern/kern_condvar.c @@ -170,12 +170,28 @@ cv_wait_sig(struct cv *cvp, struct mtx *mp) * procs or panic below, in case this is the idle process and * already asleep. */ - return 0; + return (0); } sq = sleepq_lookup(cvp); - /* XXX: Missing the threading checks from msleep! */ + /* + * Don't bother sleeping if we are exiting and not the exiting + * 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); + } + } + mtx_unlock_spin(&sched_lock); cvp->cv_waiters++; DROP_GIANT(); @@ -183,20 +199,16 @@ cv_wait_sig(struct cv *cvp, struct mtx *mp) sleepq_add(sq, cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR); sig = sleepq_catch_signals(cvp); - /* - * XXX: Missing magic return value handling for no signal - * caught but thread woken up during check. - */ - rval = sleepq_wait_sig(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); if (rval == 0) rval = sleepq_calc_signal_retval(sig); - /* XXX: Part of missing threading checks? */ - PROC_LOCK(p); - if (p->p_flag & P_WEXIT) - rval = EINTR; - PROC_UNLOCK(p); - #ifdef KTRACE if (KTRPOINT(td, KTR_CSW)) ktrcsw(0, 0); @@ -303,6 +315,24 @@ cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo) sq = sleepq_lookup(cvp); + /* + * Don't bother sleeping if we are exiting and not the exiting + * 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); + } + } + mtx_unlock_spin(&sched_lock); + cvp->cv_waiters++; DROP_GIANT(); mtx_unlock(mp); @@ -310,20 +340,16 @@ cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo) sleepq_add(sq, cvp, mp, cvp->cv_description, SLEEPQ_CONDVAR); sleepq_set_timeout(cvp, timo); sig = sleepq_catch_signals(cvp); - /* - * XXX: Missing magic return value handling for no signal - * caught but thread woken up during check. - */ - rval = sleepq_timedwait_sig(cvp, sig != 0); + 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); if (rval == 0) rval = sleepq_calc_signal_retval(sig); - /* XXX: Part of missing threading checks? */ - PROC_LOCK(p); - if (p->p_flag & P_WEXIT) - rval = EINTR; - PROC_UNLOCK(p); - #ifdef KTRACE if (KTRPOINT(td, KTR_CSW)) ktrcsw(0, 0); |