Provide helper macros to detect 'non-silent SBDRY' state and to
calculate appropriate return value for stops. Simplify the code by using them. Fix typo in sig_suspend_threads(). The thread which sleep must be aborted is td2. (*) In issignal(), when handling stopping signal for thread in TD_SBDRY_INTR state, do not stop, this is wrong and fires assert. This is yet another place where execution should be forced out of SBDRY-protected region. For such case, return -1 from issignal() and translate it to corresponding error code in sleepq_catch_signals(). Assert that other consumers of cursig() are not affected by the new return value. (*) Micro-optimize, mostly VFS and VOP methods, by avoiding calling the functions when SIGDEFERSTOP_NOP non-change is requested. (**) Reported and tested by: pho (*) Requested by: bde (**) Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Approved by: re (gjb)
This commit is contained in:
parent
c861dc4640
commit
2ff8e9c636
@ -1251,6 +1251,7 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, ksiginfo_t *ksi,
|
||||
mtx_lock(&ps->ps_mtx);
|
||||
sig = cursig(td);
|
||||
mtx_unlock(&ps->ps_mtx);
|
||||
KASSERT(sig >= 0, ("sig %d", sig));
|
||||
if (sig != 0 && SIGISMEMBER(waitset, sig)) {
|
||||
if (sigqueue_get(&td->td_sigqueue, sig, ksi) != 0 ||
|
||||
sigqueue_get(&p->p_sigqueue, sig, ksi) != 0) {
|
||||
@ -1512,8 +1513,10 @@ kern_sigsuspend(struct thread *td, sigset_t mask)
|
||||
/* void */;
|
||||
thread_suspend_check(0);
|
||||
mtx_lock(&p->p_sigacts->ps_mtx);
|
||||
while ((sig = cursig(td)) != 0)
|
||||
while ((sig = cursig(td)) != 0) {
|
||||
KASSERT(sig >= 0, ("sig %d", sig));
|
||||
has_sig += postsig(sig);
|
||||
}
|
||||
mtx_unlock(&p->p_sigacts->ps_mtx);
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
@ -2476,11 +2479,9 @@ sig_suspend_threads(struct thread *td, struct proc *p, int sending)
|
||||
*/
|
||||
KASSERT(!TD_IS_SUSPENDED(td2),
|
||||
("thread with deferred stops suspended"));
|
||||
if ((td2->td_flags & (TDF_SERESTART |
|
||||
TDF_SEINTR)) != 0 && sending) {
|
||||
wakeup_swapper |= sleepq_abort(td,
|
||||
(td2->td_flags & TDF_SERESTART)
|
||||
!= 0 ? ERESTART : EINTR);
|
||||
if (TD_SBDRY_INTR(td2) && sending) {
|
||||
wakeup_swapper |= sleepq_abort(td2,
|
||||
TD_SBDRY_ERRNO(td2));
|
||||
}
|
||||
} else if (!TD_IS_SUSPENDED(td2)) {
|
||||
thread_suspend_one(td2);
|
||||
@ -2628,7 +2629,7 @@ sigdeferstop_curr_flags(int cflags)
|
||||
* accesses below.
|
||||
*/
|
||||
int
|
||||
sigdeferstop(int mode)
|
||||
sigdeferstop_impl(int mode)
|
||||
{
|
||||
struct thread *td;
|
||||
int cflags, nflags;
|
||||
@ -2655,11 +2656,11 @@ sigdeferstop(int mode)
|
||||
panic("sigdeferstop: invalid mode %x", mode);
|
||||
break;
|
||||
}
|
||||
if (cflags != nflags) {
|
||||
thread_lock(td);
|
||||
td->td_flags = (td->td_flags & ~cflags) | nflags;
|
||||
thread_unlock(td);
|
||||
}
|
||||
if (cflags == nflags)
|
||||
return (SIGDEFERSTOP_VAL_NCHG);
|
||||
thread_lock(td);
|
||||
td->td_flags = (td->td_flags & ~cflags) | nflags;
|
||||
thread_unlock(td);
|
||||
return (cflags);
|
||||
}
|
||||
|
||||
@ -2670,11 +2671,12 @@ sigdeferstop(int mode)
|
||||
* either via ast() or a subsequent interruptible sleep.
|
||||
*/
|
||||
void
|
||||
sigallowstop(int prev)
|
||||
sigallowstop_impl(int prev)
|
||||
{
|
||||
struct thread *td;
|
||||
int cflags;
|
||||
|
||||
KASSERT(prev != SIGDEFERSTOP_VAL_NCHG, ("failed sigallowstop"));
|
||||
KASSERT((prev & ~(TDF_SBDRY | TDF_SEINTR | TDF_SERESTART)) == 0,
|
||||
("sigallowstop: incorrect previous mode %x", prev));
|
||||
td = curthread;
|
||||
@ -2835,6 +2837,11 @@ issignal(struct thread *td)
|
||||
(p->p_pgrp->pg_jobc == 0 &&
|
||||
prop & SA_TTYSTOP))
|
||||
break; /* == ignore */
|
||||
if (TD_SBDRY_INTR(td)) {
|
||||
KASSERT((td->td_flags & TDF_SBDRY) != 0,
|
||||
("lost TDF_SBDRY"));
|
||||
return (-1);
|
||||
}
|
||||
mtx_unlock(&ps->ps_mtx);
|
||||
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK,
|
||||
&p->p_mtx.lock_object, "Catching SIGSTOP");
|
||||
|
@ -894,7 +894,7 @@ thread_suspend_check(int return_instead)
|
||||
{
|
||||
struct thread *td;
|
||||
struct proc *p;
|
||||
int wakeup_swapper, r;
|
||||
int wakeup_swapper;
|
||||
|
||||
td = curthread;
|
||||
p = td->td_proc;
|
||||
@ -927,21 +927,10 @@ thread_suspend_check(int return_instead)
|
||||
if ((td->td_flags & TDF_SBDRY) != 0) {
|
||||
KASSERT(return_instead,
|
||||
("TDF_SBDRY set for unsafe thread_suspend_check"));
|
||||
switch (td->td_flags & (TDF_SEINTR | TDF_SERESTART)) {
|
||||
case 0:
|
||||
r = 0;
|
||||
break;
|
||||
case TDF_SEINTR:
|
||||
r = EINTR;
|
||||
break;
|
||||
case TDF_SERESTART:
|
||||
r = ERESTART;
|
||||
break;
|
||||
default:
|
||||
panic("both TDF_SEINTR and TDF_SERESTART");
|
||||
break;
|
||||
}
|
||||
return (r);
|
||||
KASSERT((td->td_flags & (TDF_SEINTR | TDF_SERESTART)) !=
|
||||
(TDF_SEINTR | TDF_SERESTART),
|
||||
("both TDF_SEINTR and TDF_SERESTART"));
|
||||
return (TD_SBDRY_INTR(td) ? TD_SBDRY_ERRNO(td) : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -453,7 +453,16 @@ sleepq_catch_signals(void *wchan, int pri)
|
||||
ps = p->p_sigacts;
|
||||
mtx_lock(&ps->ps_mtx);
|
||||
sig = cursig(td);
|
||||
if (sig == 0) {
|
||||
if (sig == -1) {
|
||||
mtx_unlock(&ps->ps_mtx);
|
||||
KASSERT((td->td_flags & TDF_SBDRY) != 0, ("lost TDF_SBDRY"));
|
||||
KASSERT(TD_SBDRY_INTR(td),
|
||||
("lost TDF_SERESTART of TDF_SEINTR"));
|
||||
KASSERT((td->td_flags & (TDF_SEINTR | TDF_SERESTART)) !=
|
||||
(TDF_SEINTR | TDF_SERESTART),
|
||||
("both TDF_SEINTR and TDF_SERESTART"));
|
||||
ret = TD_SBDRY_ERRNO(td);
|
||||
} else if (sig == 0) {
|
||||
mtx_unlock(&ps->ps_mtx);
|
||||
ret = thread_suspend_check(1);
|
||||
MPASS(ret == 0 || ret == EINTR || ret == ERESTART);
|
||||
|
@ -511,6 +511,11 @@ do { \
|
||||
#define TD_SET_RUNQ(td) (td)->td_state = TDS_RUNQ
|
||||
#define TD_SET_CAN_RUN(td) (td)->td_state = TDS_CAN_RUN
|
||||
|
||||
#define TD_SBDRY_INTR(td) \
|
||||
(((td)->td_flags & (TDF_SEINTR | TDF_SERESTART)) != 0)
|
||||
#define TD_SBDRY_ERRNO(td) \
|
||||
(((td)->td_flags & TDF_SEINTR) != 0 ? EINTR : ERESTART)
|
||||
|
||||
/*
|
||||
* Process structure.
|
||||
*/
|
||||
|
@ -337,9 +337,29 @@ extern struct mtx sigio_lock;
|
||||
#define SIGDEFERSTOP_EINTR 3 /* ignore STOPs, return EINTR */
|
||||
#define SIGDEFERSTOP_ERESTART 4 /* ignore STOPs, return ERESTART */
|
||||
|
||||
#define SIGDEFERSTOP_VAL_NCHG (-1) /* placeholder indicating no state change */
|
||||
int sigdeferstop_impl(int mode);
|
||||
void sigallowstop_impl(int prev);
|
||||
|
||||
static inline int
|
||||
sigdeferstop(int mode)
|
||||
{
|
||||
|
||||
if (mode == SIGDEFERSTOP_NOP)
|
||||
return (SIGDEFERSTOP_VAL_NCHG);
|
||||
return (sigdeferstop_impl(mode));
|
||||
}
|
||||
|
||||
static inline void
|
||||
sigallowstop(int prev)
|
||||
{
|
||||
|
||||
if (prev == SIGDEFERSTOP_VAL_NCHG)
|
||||
return;
|
||||
sigallowstop_impl(prev);
|
||||
}
|
||||
|
||||
int cursig(struct thread *td);
|
||||
int sigdeferstop(int mode);
|
||||
void sigallowstop(int prev);
|
||||
void execsigs(struct proc *p);
|
||||
void gsignal(int pgid, int sig, ksiginfo_t *ksi);
|
||||
void killproc(struct proc *p, char *why);
|
||||
|
Loading…
Reference in New Issue
Block a user