summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2006-02-23 00:13:58 +0000
committerdavidxu <davidxu@FreeBSD.org>2006-02-23 00:13:58 +0000
commite29c8e080b595587aafe2e1d02c5eb9f9f322a51 (patch)
tree7e38ae2e71791b901f46413e77ea39d2b4ba7ae0 /sys
parentff94f53a5d7abb067a90f6013082aaa99474583d (diff)
downloadFreeBSD-src-e29c8e080b595587aafe2e1d02c5eb9f9f322a51.zip
FreeBSD-src-e29c8e080b595587aafe2e1d02c5eb9f9f322a51.tar.gz
Fix a sleep queue race for KSE thread.
Reviewed by: jhb
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_condvar.c24
-rw-r--r--sys/kern/kern_synch.c22
-rw-r--r--sys/kern/subr_sleepqueue.c32
3 files changed, 25 insertions, 53 deletions
diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c
index f430ea8..7377981 100644
--- a/sys/kern/kern_condvar.c
+++ b/sys/kern/kern_condvar.c
@@ -192,18 +192,6 @@ cv_wait_sig(struct cv *cvp, struct mtx *mp)
sleepq_lock(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);
- 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);
@@ -315,18 +303,6 @@ cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo)
sleepq_lock(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);
- 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);
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index f988946..d2c6acc 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -164,22 +164,11 @@ msleep(ident, mtx, priority, wmesg, timo)
if (TD_ON_SLEEPQ(td))
sleepq_remove(td, td->td_wchan);
+ flags = SLEEPQ_MSLEEP;
+ if (catch)
+ flags |= SLEEPQ_INTERRUPTIBLE;
+
sleepq_lock(ident);
- if (catch) {
- /*
- * 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);
- rval = thread_sleep_check(td);
- mtx_unlock_spin(&sched_lock);
- if (rval != 0) {
- sleepq_release(ident);
- if (mtx != NULL && priority & PDROP)
- mtx_unlock(mtx);
- return (rval);
- }
- }
CTR5(KTR_PROC, "msleep: thread %p (pid %ld, %s) on %s (%p)",
(void *)td, (long)p->p_pid, p->p_comm, wmesg, ident);
@@ -199,9 +188,6 @@ msleep(ident, mtx, priority, wmesg, timo)
* stopped, then td will no longer be on a sleep queue upon
* return from cursig().
*/
- flags = SLEEPQ_MSLEEP;
- if (catch)
- flags |= SLEEPQ_INTERRUPTIBLE;
sleepq_add(ident, mtx, wmesg, flags);
if (timo)
sleepq_set_timeout(ident, timo);
diff --git a/sys/kern/subr_sleepqueue.c b/sys/kern/subr_sleepqueue.c
index 464cf28..c269806 100644
--- a/sys/kern/subr_sleepqueue.c
+++ b/sys/kern/subr_sleepqueue.c
@@ -387,23 +387,33 @@ sleepq_catch_signals(void *wchan)
mtx_unlock(&ps->ps_mtx);
}
- if (ret) {
- PROC_UNLOCK(p);
+ if (ret == 0) {
+ mtx_lock_spin(&sc->sc_lock);
/*
- * If there were pending signals and this thread is still on
- * the sleep queue, remove it from the sleep queue.
+ * Lock sched_lock before unlocking proc lock,
+ * without this, we could lose a race.
*/
- mtx_lock_spin(&sc->sc_lock);
- sq = sleepq_lookup(wchan);
mtx_lock_spin(&sched_lock);
- if (TD_ON_SLEEPQ(td))
- sleepq_resume_thread(sq, td, -1);
- td->td_flags &= ~TDF_SINTR;
+ PROC_UNLOCK(p);
+ if (!(td->td_flags & TDF_INTERRUPT))
+ return (0);
+ /* KSE threads tried unblocking us. */
+ ret = td->td_intrval;
+ mtx_unlock_spin(&sched_lock);
+ MPASS(ret == EINTR || ret == ERESTART);
} else {
- mtx_lock_spin(&sc->sc_lock);
- mtx_lock_spin(&sched_lock);
PROC_UNLOCK(p);
+ /*
+ * If there were pending signals and this thread is still
+ * on the sleep queue, remove it from the sleep queue.
+ */
+ mtx_lock_spin(&sc->sc_lock);
}
+ sq = sleepq_lookup(wchan);
+ mtx_lock_spin(&sched_lock);
+ if (TD_ON_SLEEPQ(td))
+ sleepq_resume_thread(sq, td, -1);
+ td->td_flags &= ~TDF_SINTR;
return (ret);
}
OpenPOWER on IntegriCloud