Patch to fix cv_wait return values
John Baldwin
jhb at FreeBSD.org
Mon Jul 19 10:53:10 PDT 2004
I have a patch to try to sync up the semantics of the return values of the
cv_wait() functions with msleep(). The patch is at
http://people.FreeBSD.org/~jhb/patches/cv_retval.patch and is inline below.
If people could test it ok and verify that the patch is correct I'd
appreciate it. Thanks.
--- //depot/projects/smpng/sys/kern/kern_condvar.c 2004/06/29 02:54:29
+++ //depot/user/jhb/lock/kern/kern_condvar.c 2004/07/09 18:16:47
@@ -170,12 +170,28 @@
* 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_WEXIT) && 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 @@
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 @@
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_WEXIT) && 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 @@
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);
--
John Baldwin <jhb at FreeBSD.org> <>< http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve" = http://www.FreeBSD.org
More information about the freebsd-threads
mailing list