summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2008-10-23 07:55:38 +0000
committerdavidxu <davidxu@FreeBSD.org>2008-10-23 07:55:38 +0000
commit2062caca2494bf113adefa9ca01f9f5fb24ad7b9 (patch)
tree0f85351fa5ffde7cf121d1e0f3f5e83ff415f868 /sys
parentb20c19bc667aef513fa9f5449df2d4a833e42d3d (diff)
downloadFreeBSD-src-2062caca2494bf113adefa9ca01f9f5fb24ad7b9.zip
FreeBSD-src-2062caca2494bf113adefa9ca01f9f5fb24ad7b9.tar.gz
Actually, for signal and thread suspension, extra process spin lock is
unnecessary, the normal process lock and thread lock are enough. The spin lock is still needed for process and thread exiting to mimic single sched_lock.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_sig.c29
-rw-r--r--sys/kern/kern_thr.c3
-rw-r--r--sys/kern/kern_thread.c20
-rw-r--r--sys/kern/subr_sleepqueue.c25
-rw-r--r--sys/kern/sys_process.c2
-rw-r--r--sys/sys/proc.h4
6 files changed, 22 insertions, 61 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index f4cf8ad..e9a0ac8 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -2115,19 +2115,15 @@ tdsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
* Otherwise, process goes back to sleep state.
*/
p->p_flag &= ~P_STOPPED_SIG;
- PROC_SLOCK(p);
if (p->p_numthreads == p->p_suspcount) {
- PROC_SUNLOCK(p);
p->p_flag |= P_CONTINUED;
p->p_xstat = SIGCONT;
PROC_LOCK(p->p_pptr);
childproc_continued(p);
PROC_UNLOCK(p->p_pptr);
- PROC_SLOCK(p);
}
if (action == SIG_DFL) {
thread_unsuspend(p);
- PROC_SUNLOCK(p);
sigqueue_delete(sigqueue, sig);
goto out;
}
@@ -2136,14 +2132,12 @@ tdsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
* The process wants to catch it so it needs
* to run at least one thread, but which one?
*/
- PROC_SUNLOCK(p);
goto runfast;
}
/*
* The signal is not ignored or caught.
*/
thread_unsuspend(p);
- PROC_SUNLOCK(p);
goto out;
}
@@ -2167,12 +2161,10 @@ tdsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
* It may run a bit until it hits a thread_suspend_check().
*/
wakeup_swapper = 0;
- PROC_SLOCK(p);
thread_lock(td);
if (TD_ON_SLEEPQ(td) && (td->td_flags & TDF_SINTR))
wakeup_swapper = sleepq_abort(td, intrval);
thread_unlock(td);
- PROC_SUNLOCK(p);
if (wakeup_swapper)
kick_proc0();
goto out;
@@ -2193,7 +2185,6 @@ tdsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
goto out;
p->p_flag |= P_STOPPED_SIG;
p->p_xstat = sig;
- PROC_SLOCK(p);
sig_suspend_threads(td, p, 1);
if (p->p_numthreads == p->p_suspcount) {
/*
@@ -2204,10 +2195,8 @@ tdsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
* should never be equal to p_suspcount.
*/
thread_stopped(p);
- PROC_SUNLOCK(p);
sigqueue_delete_proc(p, p->p_xstat);
- } else
- PROC_SUNLOCK(p);
+ }
goto out;
}
} else {
@@ -2222,12 +2211,8 @@ tdsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
*/
runfast:
tdsigwakeup(td, sig, action, intrval);
- PROC_SLOCK(p);
thread_unsuspend(p);
- PROC_SUNLOCK(p);
out:
- /* If we jump here, proc slock should not be owned. */
- PROC_SLOCK_ASSERT(p, MA_NOTOWNED);
return (ret);
}
@@ -2247,7 +2232,6 @@ tdsigwakeup(struct thread *td, int sig, sig_t action, int intrval)
PROC_LOCK_ASSERT(p, MA_OWNED);
prop = sigprop(sig);
- PROC_SLOCK(p);
thread_lock(td);
/*
* Bring the priority of a thread up if we want it to get
@@ -2271,7 +2255,6 @@ tdsigwakeup(struct thread *td, int sig, sig_t action, int intrval)
*/
if ((prop & SA_CONT) && action == SIG_DFL) {
thread_unlock(td);
- PROC_SUNLOCK(p);
sigqueue_delete(&p->p_sigqueue, sig);
/*
* It may be on either list in this state.
@@ -2300,7 +2283,6 @@ tdsigwakeup(struct thread *td, int sig, sig_t action, int intrval)
#endif
}
out:
- PROC_SUNLOCK(p);
thread_unlock(td);
if (wakeup_swapper)
kick_proc0();
@@ -2312,7 +2294,6 @@ sig_suspend_threads(struct thread *td, struct proc *p, int sending)
struct thread *td2;
PROC_LOCK_ASSERT(p, MA_OWNED);
- PROC_SLOCK_ASSERT(p, MA_OWNED);
FOREACH_THREAD_IN_PROC(p, td2) {
thread_lock(td2);
@@ -2344,11 +2325,9 @@ ptracestop(struct thread *td, int sig)
td->td_dbgflags |= TDB_XSIG;
td->td_xsig = sig;
- PROC_SLOCK(p);
while ((p->p_flag & P_TRACED) && (td->td_dbgflags & TDB_XSIG)) {
if (p->p_flag & P_SINGLE_EXIT) {
td->td_dbgflags &= ~TDB_XSIG;
- PROC_SUNLOCK(p);
return (sig);
}
/*
@@ -2370,7 +2349,6 @@ stopme:
goto stopme;
}
}
- PROC_SUNLOCK(p);
return (td->td_xsig);
}
@@ -2511,10 +2489,8 @@ issignal(td)
&p->p_mtx.lock_object, "Catching SIGSTOP");
p->p_flag |= P_STOPPED_SIG;
p->p_xstat = sig;
- PROC_SLOCK(p);
sig_suspend_threads(td, p, 0);
thread_suspend_switch(td);
- PROC_SUNLOCK(p);
mtx_lock(&ps->ps_mtx);
break;
} else if (prop & SA_IGNORE) {
@@ -2556,18 +2532,15 @@ thread_stopped(struct proc *p)
int n;
PROC_LOCK_ASSERT(p, MA_OWNED);
- PROC_SLOCK_ASSERT(p, MA_OWNED);
n = p->p_suspcount;
if (p == curproc)
n++;
if ((p->p_flag & P_STOPPED_SIG) && (n == p->p_numthreads)) {
- PROC_SUNLOCK(p);
p->p_flag &= ~P_WAITED;
PROC_LOCK(p->p_pptr);
childproc_stopped(p, (p->p_flag & P_TRACED) ?
CLD_TRAPPED : CLD_STOPPED);
PROC_UNLOCK(p->p_pptr);
- PROC_SLOCK(p);
}
}
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index b460bd3..51f0f05 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -283,7 +283,6 @@ thr_exit(struct thread *td, struct thr_exit_args *uap)
PROC_LOCK(p);
sigqueue_flush(&td->td_sigqueue);
- PROC_SLOCK(p);
/*
* Shutting down last thread in the proc. This will actually
@@ -291,10 +290,10 @@ thr_exit(struct thread *td, struct thr_exit_args *uap)
*/
if (p->p_numthreads != 1) {
thread_stopped(p);
+ PROC_SLOCK(p);
thread_exit();
/* NOTREACHED */
}
- PROC_SUNLOCK(p);
PROC_UNLOCK(p);
return (0);
}
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index 3bde08e..01f806c 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -543,7 +543,6 @@ thread_single(int mode)
p->p_flag &= ~P_SINGLE_BOUNDARY;
}
p->p_flag |= P_STOPPED_SINGLE;
- PROC_SLOCK(p);
p->p_singlethread = td;
if (mode == SINGLE_EXIT)
remaining = p->p_numthreads;
@@ -642,7 +641,6 @@ stopme:
p->p_flag &= ~(P_STOPPED_SINGLE | P_SINGLE_EXIT);
thread_unthread(td);
}
- PROC_SUNLOCK(p);
return (0);
}
@@ -716,15 +714,16 @@ thread_suspend_check(int return_instead)
if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td))
sigqueue_flush(&td->td_sigqueue);
- PROC_SLOCK(p);
thread_stopped(p);
/*
* If the process is waiting for us to exit,
* this thread should just suicide.
* Assumes that P_SINGLE_EXIT implies P_STOPPED_SINGLE.
*/
- if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td))
+ if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td)) {
+ PROC_SLOCK(p);
thread_exit();
+ }
if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
if (p->p_numthreads == p->p_suspcount + 1) {
thread_lock(p->p_singlethread);
@@ -735,8 +734,8 @@ thread_suspend_check(int return_instead)
kick_proc0();
}
}
- PROC_UNLOCK(p);
thread_lock(td);
+ PROC_UNLOCK(p);
/*
* When a thread suspends, it just
* gets taken off all queues.
@@ -746,7 +745,6 @@ thread_suspend_check(int return_instead)
p->p_boundary_count++;
td->td_flags |= TDF_BOUNDARY;
}
- PROC_SUNLOCK(p);
mi_switch(SW_INVOL | SWT_SUSPEND, NULL);
if (return_instead == 0)
td->td_flags &= ~TDF_BOUNDARY;
@@ -766,25 +764,22 @@ thread_suspend_switch(struct thread *td)
p = td->td_proc;
KASSERT(!TD_IS_SUSPENDED(td), ("already suspended"));
PROC_LOCK_ASSERT(p, MA_OWNED);
- PROC_SLOCK_ASSERT(p, MA_OWNED);
/*
* We implement thread_suspend_one in stages here to avoid
* dropping the proc lock while the thread lock is owned.
*/
thread_stopped(p);
p->p_suspcount++;
- PROC_UNLOCK(p);
thread_lock(td);
+ PROC_UNLOCK(p);
td->td_flags &= ~TDF_NEEDSUSPCHK;
TD_SET_SUSPENDED(td);
sched_sleep(td, 0);
- PROC_SUNLOCK(p);
DROP_GIANT();
mi_switch(SW_VOL | SWT_SUSPEND, NULL);
thread_unlock(td);
PICKUP_GIANT();
PROC_LOCK(p);
- PROC_SLOCK(p);
}
void
@@ -792,7 +787,6 @@ thread_suspend_one(struct thread *td)
{
struct proc *p = td->td_proc;
- PROC_SLOCK_ASSERT(p, MA_OWNED);
THREAD_LOCK_ASSERT(td, MA_OWNED);
KASSERT(!TD_IS_SUSPENDED(td), ("already suspended"));
p->p_suspcount++;
@@ -806,7 +800,6 @@ thread_unsuspend_one(struct thread *td)
{
struct proc *p = td->td_proc;
- PROC_SLOCK_ASSERT(p, MA_OWNED);
THREAD_LOCK_ASSERT(td, MA_OWNED);
KASSERT(TD_IS_SUSPENDED(td), ("Thread not suspended"));
TD_CLR_SUSPENDED(td);
@@ -824,7 +817,6 @@ thread_unsuspend(struct proc *p)
int wakeup_swapper;
PROC_LOCK_ASSERT(p, MA_OWNED);
- PROC_SLOCK_ASSERT(p, MA_OWNED);
wakeup_swapper = 0;
if (!P_SHOULDSTOP(p)) {
FOREACH_THREAD_IN_PROC(p, td) {
@@ -863,7 +855,6 @@ thread_single_end(void)
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
p->p_flag &= ~(P_STOPPED_SINGLE | P_SINGLE_EXIT | P_SINGLE_BOUNDARY);
- PROC_SLOCK(p);
p->p_singlethread = NULL;
wakeup_swapper = 0;
/*
@@ -881,7 +872,6 @@ thread_single_end(void)
thread_unlock(td);
}
}
- PROC_SUNLOCK(p);
if (wakeup_swapper)
kick_proc0();
}
diff --git a/sys/kern/subr_sleepqueue.c b/sys/kern/subr_sleepqueue.c
index f9bac9b..751fa64 100644
--- a/sys/kern/subr_sleepqueue.c
+++ b/sys/kern/subr_sleepqueue.c
@@ -395,6 +395,8 @@ sleepq_catch_signals(void *wchan, int pri)
sleepq_switch(wchan, pri);
return (0);
}
+
+catch_sig:
thread_unlock(td);
mtx_unlock_spin(&sc->sc_lock);
CTR3(KTR_PROC, "sleepq catching signals: thread %p (pid %ld, %s)",
@@ -414,20 +416,19 @@ 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);
PROC_UNLOCK(p);
+
+ mtx_lock_spin(&sc->sc_lock);
thread_lock(td);
- PROC_SUNLOCK(p);
- if (ret == 0) {
- sleepq_switch(wchan, pri);
- return (0);
- }
+ if (ret != 0)
+ goto out;
+ if ((td->td_flags & (TDF_NEEDSIGCHK | TDF_NEEDSUSPCHK)) != 0)
+ goto catch_sig;
+
+ sleepq_switch(wchan, pri);
+ return (0);
+
+out:
/*
* There were pending signals and this thread is still
* on the sleep queue, remove it from the sleep queue.
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index ceae8de..c67af8c 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -795,10 +795,8 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
* you should use PT_SUSPEND to suspend it before
* continuing process.
*/
- PROC_SLOCK(p);
p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG|P_WAITED);
thread_unsuspend(p);
- PROC_SUNLOCK(p);
} else {
if (data)
psignal(p, data);
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index b326ba7..4983474 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -500,8 +500,8 @@ struct proc {
u_char p_pfsflags; /* (c) Procfs flags. */
struct nlminfo *p_nlminfo; /* (?) Only used by/for lockd. */
struct kaioinfo *p_aioinfo; /* (c) ASYNC I/O info. */
- struct thread *p_singlethread;/* (c + j) If single threading this is it */
- int p_suspcount; /* (j) Num threads in suspended mode. */
+ struct thread *p_singlethread;/* (c) If single threading this is it */
+ int p_suspcount; /* (c) Num threads in suspended mode. */
struct thread *p_xthread; /* (c) Trap thread */
int p_boundary_count;/* (c) Num threads at user boundary */
int p_pendingcnt; /* how many signals are pending */
OpenPOWER on IntegriCloud