- 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)
This commit is contained in:
parent
04a57d2c83
commit
b7edba7704
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=177471
@ -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)) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
@ -108,22 +106,10 @@ userret(struct thread *td, struct trapframe *frame)
|
||||
if (td->td_pflags & TDP_GEOM)
|
||||
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);
|
||||
|
@ -309,7 +309,7 @@ do { \
|
||||
#define TDF_TIMOFAIL 0x00001000 /* Timeout from sleep after we were awake. */
|
||||
#define TDF_UNUSED2000 0x00002000 /* --available-- */
|
||||
#define TDF_UPIBLOCKED 0x00004000 /* Thread blocked on user PI mutex. */
|
||||
#define TDF_UNUSED15 0x00008000 /* --available-- */
|
||||
#define TDF_NEEDSUSPCHK 0x00008000 /* Thread may need to suspend. */
|
||||
#define TDF_NEEDRESCHED 0x00010000 /* Thread needs to yield. */
|
||||
#define TDF_NEEDSIGCHK 0x00020000 /* Thread may need signal delivery. */
|
||||
#define TDF_XSIG 0x00040000 /* Thread is exchanging signal under trace */
|
||||
|
Loading…
Reference in New Issue
Block a user