summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2008-03-21 08:23:25 +0000
committerjeff <jeff@FreeBSD.org>2008-03-21 08:23:25 +0000
commitba540b27d633327453067e692e5ccb2095d417c1 (patch)
tree85009349e539f1265173b5d33889d0fca5031c61 /sys/kern
parent8420f5505a178be36939d61d6e9da31e0f2eb05a (diff)
downloadFreeBSD-src-ba540b27d633327453067e692e5ccb2095d417c1.zip
FreeBSD-src-ba540b27d633327453067e692e5ccb2095d417c1.tar.gz
- Add a new td flag TDF_NEEDSUSPCHK that is set whenever a thread needs
to enter thread_suspend_check(). - Set TDF_ASTPENDING along with TDF_NEEDSUSPCHK so we can move the thread_suspend_check() to ast() rather than userret(). - Check TDF_NEEDSUSPCHK in the sleepq_catch_signals() optimization so that we don't miss a suspend request. If this is set use the expensive signal path. - Set NEEDSUSPCHK when creating a new thread in thr in case the creating thread is due to be suspended as well but has not yet. Reviewed by: davidxu (Authored original patch)
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_sig.c1
-rw-r--r--sys/kern/kern_thr.c2
-rw-r--r--sys/kern/kern_thread.c4
-rw-r--r--sys/kern/subr_sleepqueue.c2
-rw-r--r--sys/kern/subr_trap.c28
5 files changed, 18 insertions, 19 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index eee71f1..6fc597b 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -2286,6 +2286,7 @@ sig_suspend_threads(struct thread *td, struct proc *p, int sending)
FOREACH_THREAD_IN_PROC(p, td2) {
thread_lock(td2);
+ td2->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK;
if ((TD_IS_SLEEPING(td2) || TD_IS_SWAPPED(td2)) &&
(td2->td_flags & TDF_SINTR) &&
!TD_IS_SUSPENDED(td2)) {
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index 3d410b5..61d9a88 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -235,6 +235,8 @@ create_thread(struct thread *td, mcontext_t *ctx,
/* let the scheduler know about these things. */
sched_fork_thread(td, newtd);
thread_unlock(td);
+ if (P_SHOULDSTOP(p))
+ newtd->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK;
PROC_UNLOCK(p);
thread_lock(newtd);
if (rtp != NULL) {
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index 65fdae4..8745e5e 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -549,7 +549,7 @@ thread_single(int mode)
if (td2 == td)
continue;
thread_lock(td2);
- td2->td_flags |= TDF_ASTPENDING;
+ td2->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK;
if (TD_IS_INHIBITED(td2)) {
switch (mode) {
case SINGLE_EXIT:
@@ -751,6 +751,7 @@ thread_suspend_switch(struct thread *td)
p->p_suspcount++;
PROC_UNLOCK(p);
thread_lock(td);
+ td->td_flags &= ~TDF_NEEDSUSPCHK;
TD_SET_SUSPENDED(td);
sched_sleep(td, 0);
PROC_SUNLOCK(p);
@@ -771,6 +772,7 @@ thread_suspend_one(struct thread *td)
THREAD_LOCK_ASSERT(td, MA_OWNED);
KASSERT(!TD_IS_SUSPENDED(td), ("already suspended"));
p->p_suspcount++;
+ td->td_flags &= ~TDF_NEEDSUSPCHK;
TD_SET_SUSPENDED(td);
sched_sleep(td, 0);
}
diff --git a/sys/kern/subr_sleepqueue.c b/sys/kern/subr_sleepqueue.c
index e12ef6e..bc3f1d8 100644
--- a/sys/kern/subr_sleepqueue.c
+++ b/sys/kern/subr_sleepqueue.c
@@ -391,7 +391,7 @@ sleepq_catch_signals(void *wchan, int pri)
* directly.
*/
thread_lock(td);
- if ((td->td_flags & TDF_NEEDSIGCHK) == 0) {
+ if ((td->td_flags & (TDF_NEEDSIGCHK | TDF_NEEDSUSPCHK)) == 0) {
sleepq_switch(wchan, pri);
return (0);
}
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index 1701fba..a92abd2 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -96,11 +96,9 @@ userret(struct thread *td, struct trapframe *frame)
thread_unlock(td);
PROC_UNLOCK(p);
#endif
-
#ifdef KTRACE
KTRUSERRET(td);
#endif
-
/*
* If this thread tickled GEOM, we need to wait for the giggling to
* stop before we return to userland
@@ -109,21 +107,9 @@ userret(struct thread *td, struct trapframe *frame)
g_waitidle();
/*
- * We need to check to see if we have to exit or wait due to a
- * single threading requirement or some other STOP condition.
- * Don't bother doing all the work if the stop bits are not set
- * at this time.. If we miss it, we miss it.. no big deal.
- */
- if (P_SHOULDSTOP(p)) {
- PROC_LOCK(p);
- thread_suspend_check(0); /* Can suspend or kill */
- PROC_UNLOCK(p);
- }
- /*
* Charge system time if profiling.
*/
if (p->p_flag & P_PROFIL) {
-
addupc_task(td, TRAPF_PC(frame), td->td_pticks * psratio);
}
/*
@@ -172,9 +158,8 @@ ast(struct trapframe *framep)
*/
thread_lock(td);
flags = td->td_flags;
- td->td_flags &= ~(TDF_ASTPENDING | TDF_NEEDSIGCHK |
- TDF_NEEDRESCHED | TDF_ALRMPEND | TDF_PROFPEND |
- TDF_MACPEND);
+ td->td_flags &= ~(TDF_ASTPENDING | TDF_NEEDSIGCHK | TDF_NEEDSUSPCHK |
+ TDF_NEEDRESCHED | TDF_ALRMPEND | TDF_PROFPEND | TDF_MACPEND);
thread_unlock(td);
PCPU_INC(cnt.v_trap);
@@ -242,6 +227,15 @@ ast(struct trapframe *framep)
mtx_unlock(&p->p_sigacts->ps_mtx);
PROC_UNLOCK(p);
}
+ /*
+ * We need to check to see if we have to exit or wait due to a
+ * single threading requirement or some other STOP condition.
+ */
+ if (flags & TDF_NEEDSUSPCHK) {
+ PROC_LOCK(p);
+ thread_suspend_check(0);
+ PROC_UNLOCK(p);
+ }
userret(td, framep);
mtx_assert(&Giant, MA_NOTOWNED);
OpenPOWER on IntegriCloud