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