- 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:
parent
87f9ffb805
commit
1df95969b5
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user