From 274f8f48e8ea67b8132777924be1a5ab005a7d81 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 10 Aug 2004 17:42:59 +0000 Subject: [PATCH] Synchronize the extra SA threading checks and return value handling of condition variables with that of msleep(). Reviewed by: davidxu --- sys/kern/kern_condvar.c | 74 ++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c index 64a82240b5aa..ff619ec2db40 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);