The previous commit wasn't entirely correct. At least one goto to the

out: label in psignal() did not grab sched_lock before trying to release
it.  Also, the previous version had several cases where it grabbed
sched_lock before jumping to out: unneccessarily, so rework this a bit.
The runfast: and out: labels must be called with sched_lock released, and
the run: label must be called with it held.  Appropriate mtx_assert()'s
have been added that should catch any bugs that may still be in this
code.

Noticed by:	bde
This commit is contained in:
John Baldwin 2001-01-02 18:54:09 +00:00
parent 542e394c1c
commit 3e6831f510
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=70603

View File

@ -1123,8 +1123,10 @@ psignal(p, sig)
* be noticed when the process returns through * be noticed when the process returns through
* trap() or syscall(). * trap() or syscall().
*/ */
if ((p->p_flag & P_SINTR) == 0) if ((p->p_flag & P_SINTR) == 0) {
mtx_exit(&sched_lock, MTX_SPIN);
goto out; goto out;
}
/* /*
* Process is sleeping and traced... make it runnable * Process is sleeping and traced... make it runnable
* so it can discover the signal in issignal() and stop * so it can discover the signal in issignal() and stop
@ -1132,15 +1134,14 @@ psignal(p, sig)
*/ */
if (p->p_flag & P_TRACED) if (p->p_flag & P_TRACED)
goto run; goto run;
mtx_exit(&sched_lock, MTX_SPIN);
/* /*
* If SIGCONT is default (or ignored) and process is * If SIGCONT is default (or ignored) and process is
* asleep, we are finished; the process should not * asleep, we are finished; the process should not
* be awakened. * be awakened.
*/ */
mtx_exit(&sched_lock, MTX_SPIN);
if ((prop & SA_CONT) && action == SIG_DFL) { if ((prop & SA_CONT) && action == SIG_DFL) {
SIGDELSET(p->p_siglist, sig); SIGDELSET(p->p_siglist, sig);
mtx_enter(&sched_lock, MTX_SPIN);
goto out; goto out;
} }
/* /*
@ -1150,10 +1151,8 @@ psignal(p, sig)
* cause the process to run. * cause the process to run.
*/ */
if (prop & SA_STOP) { if (prop & SA_STOP) {
if (action != SIG_DFL) { if (action != SIG_DFL)
mtx_enter(&sched_lock, MTX_SPIN);
goto runfast; goto runfast;
}
/* /*
* If a child holding parent blocked, * If a child holding parent blocked,
* stopping could cause deadlock. * stopping could cause deadlock.
@ -1167,12 +1166,9 @@ psignal(p, sig)
psignal(p->p_pptr, SIGCHLD); psignal(p->p_pptr, SIGCHLD);
stop(p); stop(p);
PROCTREE_LOCK(PT_RELEASE); PROCTREE_LOCK(PT_RELEASE);
mtx_enter(&sched_lock, MTX_SPIN);
goto out; goto out;
} else { } else
mtx_enter(&sched_lock, MTX_SPIN);
goto runfast; goto runfast;
}
/* NOTREACHED */ /* NOTREACHED */
case SSTOP: case SSTOP:
@ -1180,8 +1176,11 @@ psignal(p, sig)
* If traced process is already stopped, * If traced process is already stopped,
* then no further action is necessary. * then no further action is necessary.
*/ */
if (p->p_flag & P_TRACED) if (p->p_flag & P_TRACED) {
mtx_exit(&sched_lock, MTX_SPIN);
goto out; goto out;
}
mtx_exit(&sched_lock, MTX_SPIN);
/* /*
* Kill signal always sets processes running. * Kill signal always sets processes running.
@ -1189,7 +1188,6 @@ psignal(p, sig)
if (sig == SIGKILL) if (sig == SIGKILL)
goto runfast; goto runfast;
mtx_exit(&sched_lock, MTX_SPIN);
if (prop & SA_CONT) { if (prop & SA_CONT) {
/* /*
* If SIGCONT is default (or ignored), we continue the * If SIGCONT is default (or ignored), we continue the
@ -1203,12 +1201,13 @@ psignal(p, sig)
*/ */
if (action == SIG_DFL) if (action == SIG_DFL)
SIGDELSET(p->p_siglist, sig); SIGDELSET(p->p_siglist, sig);
mtx_enter(&sched_lock, MTX_SPIN);
if (action == SIG_CATCH) if (action == SIG_CATCH)
goto runfast; goto runfast;
mtx_enter(&sched_lock, MTX_SPIN);
if (p->p_wchan == 0) if (p->p_wchan == 0)
goto run; goto run;
p->p_stat = SSLEEP; p->p_stat = SSLEEP;
mtx_exit(&sched_lock, MTX_SPIN);
goto out; goto out;
} }
@ -1218,7 +1217,6 @@ psignal(p, sig)
* (If we did the shell could get confused.) * (If we did the shell could get confused.)
*/ */
SIGDELSET(p->p_siglist, sig); SIGDELSET(p->p_siglist, sig);
mtx_enter(&sched_lock, MTX_SPIN);
goto out; goto out;
} }
@ -1231,6 +1229,7 @@ psignal(p, sig)
mtx_enter(&sched_lock, MTX_SPIN); mtx_enter(&sched_lock, MTX_SPIN);
if (p->p_wchan && p->p_flag & P_SINTR) if (p->p_wchan && p->p_flag & P_SINTR)
unsleep(p); unsleep(p);
mtx_exit(&sched_lock, MTX_SPIN);
goto out; goto out;
default: default:
@ -1242,15 +1241,15 @@ psignal(p, sig)
if (p == curproc) { if (p == curproc) {
mtx_exit(&sched_lock, MTX_SPIN); mtx_exit(&sched_lock, MTX_SPIN);
signotify(p); signotify(p);
mtx_enter(&sched_lock, MTX_SPIN);
} }
#ifdef SMP #ifdef SMP
else if (p->p_stat == SRUN) { else if (p->p_stat == SRUN) {
mtx_exit(&sched_lock, MTX_SPIN); mtx_exit(&sched_lock, MTX_SPIN);
forward_signal(p); forward_signal(p);
mtx_enter(&sched_lock, MTX_SPIN);
} }
#endif #endif
else
mtx_exit(&sched_lock, MTX_SPIN);
goto out; goto out;
} }
/*NOTREACHED*/ /*NOTREACHED*/
@ -1259,12 +1258,17 @@ psignal(p, sig)
/* /*
* Raise priority to at least PUSER. * Raise priority to at least PUSER.
*/ */
mtx_enter(&sched_lock, MTX_SPIN);
if (p->p_priority > PUSER) if (p->p_priority > PUSER)
p->p_priority = PUSER; p->p_priority = PUSER;
run: run:
/* If we jump here, sched_lock has to be owned. */
mtx_assert(&sched_lock, MA_OWNED | MA_NOTRECURSED);
setrunnable(p); setrunnable(p);
out:
mtx_exit(&sched_lock, MTX_SPIN); mtx_exit(&sched_lock, MTX_SPIN);
out:
/* If we jump here, sched_lock should not be owned. */
mtx_assert(&sched_lock, MA_NOTOWNED);
splx(s); splx(s);
} }