- Lock CURSIG() with the proc lock to close the signal race with psignal.

- Grab Giant around ktrace points.
- Clean up KTR_PROC tracepoints to not display the value of
  sched_lock.mtx_lock as it isn't really needed anymore and just obfuscates
  the messages.
- Add a few if conditions to replace gotos.
- Ensure that every msleep KTR event ends up with a matching msleep resume
  KTR event (this was broken when we didn't do a mi_switch()).
- Only note via ktrace that we resumed from a switch once rather than twice
  in several places in msleep().
- Remove spl's rom asleep and await as the proc lock and sched_lock provide
  all the needed locking.
- In mawait() add in a needed ktrace point for noting that we are about to
  switch out.
This commit is contained in:
John Baldwin 2001-06-22 23:11:26 +00:00
parent 87f9ffb805
commit 1df95969b5

View File

@ -422,8 +422,7 @@ msleep(ident, mtx, priority, wmesg, timo)
p->p_wmesg = wmesg; p->p_wmesg = wmesg;
p->p_slptime = 0; p->p_slptime = 0;
p->p_pri.pri_level = priority & PRIMASK; p->p_pri.pri_level = priority & PRIMASK;
CTR4(KTR_PROC, "msleep: proc %p (pid %d, %s), schedlock %p", CTR3(KTR_PROC, "msleep: proc %p (pid %d, %s)", p, p->p_pid, p->p_comm);
p, p->p_pid, p->p_comm, (void *) sched_lock.mtx_lock);
TAILQ_INSERT_TAIL(&slpque[LOOKUP(ident)], p, p_slpq); TAILQ_INSERT_TAIL(&slpque[LOOKUP(ident)], p, p_slpq);
if (timo) if (timo)
callout_reset(&p->p_slpcallout, timo, endtsleep, p); callout_reset(&p->p_slpcallout, timo, endtsleep, p);
@ -437,67 +436,56 @@ msleep(ident, mtx, priority, wmesg, timo)
* stopped, p->p_wchan will be 0 upon return from CURSIG. * stopped, p->p_wchan will be 0 upon return from CURSIG.
*/ */
if (catch) { if (catch) {
CTR4(KTR_PROC, CTR3(KTR_PROC, "msleep caught: proc %p (pid %d, %s)", p,
"msleep caught: proc %p (pid %d, %s), schedlock %p", p->p_pid, p->p_comm);
p, p->p_pid, p->p_comm, (void *) sched_lock.mtx_lock);
p->p_sflag |= PS_SINTR; p->p_sflag |= PS_SINTR;
mtx_unlock_spin(&sched_lock); mtx_unlock_spin(&sched_lock);
if ((sig = CURSIG(p))) { PROC_LOCK(p);
mtx_lock_spin(&sched_lock); sig = CURSIG(p);
mtx_lock_spin(&sched_lock);
PROC_UNLOCK_NOSWITCH(p);
if (sig != 0) {
if (p->p_wchan) if (p->p_wchan)
unsleep(p); unsleep(p);
p->p_stat = SRUN; } else if (p->p_wchan == NULL)
goto resume;
}
mtx_lock_spin(&sched_lock);
if (p->p_wchan == NULL) {
catch = 0; catch = 0;
goto resume;
}
} else } else
sig = 0; sig = 0;
p->p_stat = SSLEEP; if (p->p_wchan != NULL) {
p->p_stats->p_ru.ru_nvcsw++; p->p_stat = SSLEEP;
mi_switch(); p->p_stats->p_ru.ru_nvcsw++;
CTR4(KTR_PROC, mi_switch();
"msleep resume: proc %p (pid %d, %s), schedlock %p", }
p, p->p_pid, p->p_comm, (void *) sched_lock.mtx_lock); CTR3(KTR_PROC, "msleep resume: proc %p (pid %d, %s)", p, p->p_pid,
resume: p->p_comm);
KASSERT(p->p_stat == SRUN, ("running but not SRUN"));
p->p_sflag &= ~PS_SINTR; p->p_sflag &= ~PS_SINTR;
if (p->p_sflag & PS_TIMEOUT) { if (p->p_sflag & PS_TIMEOUT) {
p->p_sflag &= ~PS_TIMEOUT; p->p_sflag &= ~PS_TIMEOUT;
if (sig == 0) { if (sig == 0)
#ifdef KTRACE
if (KTRPOINT(p, KTR_CSW))
ktrcsw(p->p_tracep, 0, 0);
#endif
rval = EWOULDBLOCK; rval = EWOULDBLOCK;
mtx_unlock_spin(&sched_lock);
goto out;
}
} else if (timo) } else if (timo)
callout_stop(&p->p_slpcallout); callout_stop(&p->p_slpcallout);
mtx_unlock_spin(&sched_lock); mtx_unlock_spin(&sched_lock);
if (catch && (sig != 0 || (sig = CURSIG(p)))) { if (rval == 0 && catch) {
#ifdef KTRACE
if (KTRPOINT(p, KTR_CSW))
ktrcsw(p->p_tracep, 0, 0);
#endif
PROC_LOCK(p); PROC_LOCK(p);
if (SIGISMEMBER(p->p_sigacts->ps_sigintr, sig)) /* XXX: shouldn't we always be calling CURSIG() */
rval = EINTR; if (sig != 0 || (sig = CURSIG(p))) {
else if (SIGISMEMBER(p->p_sigacts->ps_sigintr, sig))
rval = ERESTART; rval = EINTR;
else
rval = ERESTART;
}
PROC_UNLOCK(p); PROC_UNLOCK(p);
goto out;
} }
out: PICKUP_GIANT();
#ifdef KTRACE #ifdef KTRACE
mtx_lock(&Giant);
if (KTRPOINT(p, KTR_CSW)) if (KTRPOINT(p, KTR_CSW))
ktrcsw(p->p_tracep, 0, 0); ktrcsw(p->p_tracep, 0, 0);
mtx_unlock(&Giant);
#endif #endif
PICKUP_GIANT();
if (mtx != NULL) { if (mtx != NULL) {
mtx_lock(mtx); mtx_lock(mtx);
WITNESS_RESTORE(&mtx->mtx_object, mtx); WITNESS_RESTORE(&mtx->mtx_object, mtx);
@ -525,16 +513,12 @@ int
asleep(void *ident, int priority, const char *wmesg, int timo) asleep(void *ident, int priority, const char *wmesg, int timo)
{ {
struct proc *p = curproc; struct proc *p = curproc;
int s;
/* /*
* obtain sched_lock while manipulating sleep structures and slpque.
*
* Remove preexisting wait condition (if any) and place process * Remove preexisting wait condition (if any) and place process
* on appropriate slpque, but do not put process to sleep. * on appropriate slpque, but do not put process to sleep.
*/ */
s = splhigh();
mtx_lock_spin(&sched_lock); mtx_lock_spin(&sched_lock);
if (p->p_wchan != NULL) if (p->p_wchan != NULL)
@ -550,7 +534,6 @@ asleep(void *ident, int priority, const char *wmesg, int timo)
} }
mtx_unlock_spin(&sched_lock); mtx_unlock_spin(&sched_lock);
splx(s);
return(0); return(0);
} }
@ -572,7 +555,6 @@ mawait(struct mtx *mtx, int priority, int timo)
{ {
struct proc *p = curproc; struct proc *p = curproc;
int rval = 0; int rval = 0;
int s;
WITNESS_SAVE_DECL(mtx); WITNESS_SAVE_DECL(mtx);
WITNESS_SLEEP(0, &mtx->mtx_object); WITNESS_SLEEP(0, &mtx->mtx_object);
@ -588,12 +570,14 @@ mawait(struct mtx *mtx, int priority, int timo)
mtx = NULL; mtx = NULL;
} }
s = splhigh();
if (p->p_wchan != NULL) { if (p->p_wchan != NULL) {
int sig; int sig;
int catch; int catch;
#ifdef KTRACE
if (p && KTRPOINT(p, KTR_CSW))
ktrcsw(p->p_tracep, 1, 0);
#endif
/* /*
* The call to mawait() can override defaults specified in * The call to mawait() can override defaults specified in
* the original asleep(). * the original asleep().
@ -616,57 +600,45 @@ mawait(struct mtx *mtx, int priority, int timo)
if (catch) { if (catch) {
p->p_sflag |= PS_SINTR; p->p_sflag |= PS_SINTR;
mtx_unlock_spin(&sched_lock); mtx_unlock_spin(&sched_lock);
if ((sig = CURSIG(p))) { PROC_LOCK(p);
mtx_lock_spin(&sched_lock); sig = CURSIG(p);
mtx_lock_spin(&sched_lock);
PROC_UNLOCK_NOSWITCH(p);
if (sig != 0) {
if (p->p_wchan) if (p->p_wchan)
unsleep(p); unsleep(p);
p->p_stat = SRUN; } else if (p->p_wchan == NULL)
goto resume;
}
mtx_lock_spin(&sched_lock);
if (p->p_wchan == NULL) {
catch = 0; catch = 0;
goto resume;
}
} }
p->p_stat = SSLEEP; if (p->p_wchan != NULL) {
p->p_stats->p_ru.ru_nvcsw++; p->p_stat = SSLEEP;
mi_switch(); p->p_stats->p_ru.ru_nvcsw++;
resume: mi_switch();
}
splx(s); KASSERT(p->p_stat == SRUN, ("running but not SRUN"));
p->p_sflag &= ~PS_SINTR; p->p_sflag &= ~PS_SINTR;
if (p->p_sflag & PS_TIMEOUT) { if (p->p_sflag & PS_TIMEOUT) {
p->p_sflag &= ~PS_TIMEOUT; p->p_sflag &= ~PS_TIMEOUT;
if (sig == 0) { if (sig == 0)
#ifdef KTRACE
if (KTRPOINT(p, KTR_CSW))
ktrcsw(p->p_tracep, 0, 0);
#endif
rval = EWOULDBLOCK; rval = EWOULDBLOCK;
mtx_unlock_spin(&sched_lock);
goto out;
}
} else if (timo) } else if (timo)
callout_stop(&p->p_slpcallout); callout_stop(&p->p_slpcallout);
mtx_unlock_spin(&sched_lock); mtx_unlock_spin(&sched_lock);
if (rval == 0 && catch) {
if (catch && (sig != 0 || (sig = CURSIG(p)))) {
#ifdef KTRACE
if (KTRPOINT(p, KTR_CSW))
ktrcsw(p->p_tracep, 0, 0);
#endif
PROC_LOCK(p); PROC_LOCK(p);
if (SIGISMEMBER(p->p_sigacts->ps_sigintr, sig)) if (sig != 0 || (sig = CURSIG(p))) {
rval = EINTR; if (SIGISMEMBER(p->p_sigacts->ps_sigintr, sig))
else rval = EINTR;
rval = ERESTART; else
rval = ERESTART;
}
PROC_UNLOCK(p); PROC_UNLOCK(p);
goto out;
} }
#ifdef KTRACE #ifdef KTRACE
mtx_lock(&Giant);
if (KTRPOINT(p, KTR_CSW)) if (KTRPOINT(p, KTR_CSW))
ktrcsw(p->p_tracep, 0, 0); ktrcsw(p->p_tracep, 0, 0);
mtx_unlock(&Giant);
#endif #endif
} else { } else {
/* /*
@ -680,7 +652,6 @@ mawait(struct mtx *mtx, int priority, int timo)
mi_switch(); mi_switch();
} }
mtx_unlock_spin(&sched_lock); mtx_unlock_spin(&sched_lock);
splx(s);
} }
/* /*
@ -689,9 +660,9 @@ mawait(struct mtx *mtx, int priority, int timo)
* mawait() is still effectively a NOP but the above mi_switch() code * mawait() is still effectively a NOP but the above mi_switch() code
* is triggered as a safety. * is triggered as a safety.
*/ */
p->p_asleep.as_priority = 0; if (rval == 0)
p->p_asleep.as_priority = 0;
out:
PICKUP_GIANT(); PICKUP_GIANT();
if (mtx != NULL) { if (mtx != NULL) {
mtx_lock(mtx); mtx_lock(mtx);
@ -716,9 +687,8 @@ endtsleep(arg)
int s; int s;
p = (struct proc *)arg; p = (struct proc *)arg;
CTR4(KTR_PROC, CTR3(KTR_PROC, "endtsleep: proc %p (pid %d, %s)", p, p->p_pid,
"endtsleep: proc %p (pid %d, %s), schedlock %p", p->p_comm);
p, p->p_pid, p->p_comm, (void *) sched_lock.mtx_lock);
s = splhigh(); s = splhigh();
mtx_lock_spin(&sched_lock); mtx_lock_spin(&sched_lock);
if (p->p_wchan) { if (p->p_wchan) {
@ -772,9 +742,8 @@ wakeup(ident)
p->p_wchan = NULL; p->p_wchan = NULL;
if (p->p_stat == SSLEEP) { if (p->p_stat == SSLEEP) {
/* OPTIMIZED EXPANSION OF setrunnable(p); */ /* OPTIMIZED EXPANSION OF setrunnable(p); */
CTR4(KTR_PROC, CTR3(KTR_PROC, "wakeup: proc %p (pid %d, %s)",
"wakeup: proc %p (pid %d, %s), schedlock %p", p, p->p_pid, p->p_comm);
p, p->p_pid, p->p_comm, (void *) sched_lock.mtx_lock);
if (p->p_slptime > 1) if (p->p_slptime > 1)
updatepri(p); updatepri(p);
p->p_slptime = 0; p->p_slptime = 0;
@ -818,9 +787,8 @@ wakeup_one(ident)
p->p_wchan = NULL; p->p_wchan = NULL;
if (p->p_stat == SSLEEP) { if (p->p_stat == SSLEEP) {
/* OPTIMIZED EXPANSION OF setrunnable(p); */ /* OPTIMIZED EXPANSION OF setrunnable(p); */
CTR4(KTR_PROC, CTR3(KTR_PROC, "wakeup1: proc %p (pid %d, %s)",
"wakeup1: proc %p (pid %d, %s), schedlock %p", p, p->p_pid, p->p_comm);
p, p->p_pid, p->p_comm, (void *) sched_lock.mtx_lock);
if (p->p_slptime > 1) if (p->p_slptime > 1)
updatepri(p); updatepri(p);
p->p_slptime = 0; p->p_slptime = 0;
@ -911,8 +879,8 @@ mi_switch()
*/ */
cnt.v_swtch++; cnt.v_swtch++;
PCPU_SET(switchtime, new_switchtime); PCPU_SET(switchtime, new_switchtime);
CTR4(KTR_PROC, "mi_switch: old proc %p (pid %d, %s), schedlock %p", CTR3(KTR_PROC, "mi_switch: old proc %p (pid %d, %s)", p, p->p_pid,
p, p->p_pid, p->p_comm, (void *) sched_lock.mtx_lock); p->p_comm);
sched_nest = sched_lock.mtx_recurse; sched_nest = sched_lock.mtx_recurse;
curproc->p_lastcpu = curproc->p_oncpu; curproc->p_lastcpu = curproc->p_oncpu;
curproc->p_oncpu = NOCPU; curproc->p_oncpu = NOCPU;
@ -921,8 +889,8 @@ mi_switch()
curproc->p_oncpu = PCPU_GET(cpuid); curproc->p_oncpu = PCPU_GET(cpuid);
sched_lock.mtx_recurse = sched_nest; sched_lock.mtx_recurse = sched_nest;
sched_lock.mtx_lock = (uintptr_t)curproc; sched_lock.mtx_lock = (uintptr_t)curproc;
CTR4(KTR_PROC, "mi_switch: new proc %p (pid %d, %s), schedlock %p", CTR3(KTR_PROC, "mi_switch: new proc %p (pid %d, %s)", p, p->p_pid,
p, p->p_pid, p->p_comm, (void *) sched_lock.mtx_lock); p->p_comm);
if (PCPU_GET(switchtime.tv_sec) == 0) if (PCPU_GET(switchtime.tv_sec) == 0)
microuptime(PCPU_PTR(switchtime)); microuptime(PCPU_PTR(switchtime));
PCPU_SET(switchticks, ticks); PCPU_SET(switchticks, ticks);