summaryrefslogtreecommitdiff
path: root/sys/kern/subr_sleepqueue.c
diff options
context:
space:
mode:
authorDavid Xu <davidxu@FreeBSD.org>2008-11-05 03:01:23 +0000
committerDavid Xu <davidxu@FreeBSD.org>2008-11-05 03:01:23 +0000
commit7b4a950a7df886f19bea7d2f57ef8f7ef81b7428 (patch)
tree50003b0f3882d55b6d31a3135664f3a2abd73c56 /sys/kern/subr_sleepqueue.c
parentcef3930d7c33bf6e86b486fc0a5c0cd9742caf8a (diff)
Notes
Diffstat (limited to 'sys/kern/subr_sleepqueue.c')
-rw-r--r--sys/kern/subr_sleepqueue.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/sys/kern/subr_sleepqueue.c b/sys/kern/subr_sleepqueue.c
index 97511e0914d5..8ce6c0a08c0a 100644
--- a/sys/kern/subr_sleepqueue.c
+++ b/sys/kern/subr_sleepqueue.c
@@ -395,7 +395,6 @@ sleepq_catch_signals(void *wchan, int pri)
sleepq_switch(wchan, pri);
return (0);
}
-
thread_unlock(td);
mtx_unlock_spin(&sc->sc_lock);
CTR3(KTR_PROC, "sleepq catching signals: thread %p (pid %ld, %s)",
@@ -415,15 +414,16 @@ sleepq_catch_signals(void *wchan, int pri)
ret = ERESTART;
mtx_unlock(&ps->ps_mtx);
}
-
+ /*
+ * Lock the per-process spinlock prior to dropping the PROC_LOCK
+ * to avoid a signal delivery race. PROC_LOCK, PROC_SLOCK, and
+ * thread_lock() are currently held in tdsignal().
+ */
+ PROC_SLOCK(p);
mtx_lock_spin(&sc->sc_lock);
- thread_lock(td);
PROC_UNLOCK(p);
- if (ret == 0) {
- sleepq_switch(wchan, pri);
- return (0);
- }
-
+ thread_lock(td);
+ PROC_SUNLOCK(p);
/*
* There were pending signals and this thread is still
* on the sleep queue, remove it from the sleep queue.