parent
527eee2d40
commit
71fad9fdee
@ -119,7 +119,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
|
||||
struct procsig procsig;
|
||||
struct pstats pstats;
|
||||
struct ucred ucred;
|
||||
struct thread mainthread;
|
||||
struct thread mtd;
|
||||
struct proc proc;
|
||||
struct proc pproc;
|
||||
struct timeval tv;
|
||||
@ -134,7 +134,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
|
||||
}
|
||||
if (proc.p_state != PRS_ZOMBIE) {
|
||||
if (KREAD(kd, (u_long)TAILQ_FIRST(&proc.p_threads),
|
||||
&mainthread)) {
|
||||
&mtd)) {
|
||||
_kvm_err(kd, kd->program,
|
||||
"can't read thread at %x",
|
||||
TAILQ_FIRST(&proc.p_threads));
|
||||
@ -273,8 +273,8 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
|
||||
nopgrp:
|
||||
kp->ki_tdev = NODEV;
|
||||
}
|
||||
if ((proc.p_state != PRS_ZOMBIE) && mainthread.td_wmesg)
|
||||
(void)kvm_read(kd, (u_long)mainthread.td_wmesg,
|
||||
if ((proc.p_state != PRS_ZOMBIE) && mtd.td_wmesg)
|
||||
(void)kvm_read(kd, (u_long)mtd.td_wmesg,
|
||||
kp->ki_wmesg, WMESGLEN);
|
||||
|
||||
#ifdef sparc
|
||||
@ -313,11 +313,11 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
|
||||
kp->ki_comm[MAXCOMLEN] = 0;
|
||||
}
|
||||
if ((proc.p_state != PRS_ZOMBIE) &&
|
||||
(mainthread.td_blocked != 0)) {
|
||||
(mtd.td_blocked != 0)) {
|
||||
kp->ki_kiflag |= KI_MTXBLOCK;
|
||||
if (mainthread.td_mtxname)
|
||||
if (mtd.td_mtxname)
|
||||
(void)kvm_read(kd,
|
||||
(u_long)mainthread.td_mtxname,
|
||||
(u_long)mtd.td_mtxname,
|
||||
kp->ki_mtxname, MTXNAMELEN);
|
||||
kp->ki_mtxname[MTXNAMELEN] = 0;
|
||||
}
|
||||
@ -335,33 +335,36 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
|
||||
kp->ki_swtime = proc.p_swtime;
|
||||
kp->ki_flag = proc.p_flag;
|
||||
kp->ki_sflag = proc.p_sflag;
|
||||
kp->ki_wchan = mainthread.td_wchan;
|
||||
kp->ki_wchan = mtd.td_wchan;
|
||||
kp->ki_traceflag = proc.p_traceflag;
|
||||
if (proc.p_state == PRS_NORMAL) {
|
||||
if ((mainthread.td_state == TDS_RUNQ) ||
|
||||
(mainthread.td_state == TDS_RUNNING)) {
|
||||
if (TD_ON_RUNQ(&mtd) ||
|
||||
TD_CAN_RUN(&mtd) ||
|
||||
TD_IS_RUNNING(&mtd)) {
|
||||
kp->ki_stat = SRUN;
|
||||
} else if (mainthread.td_state == TDS_SLP) {
|
||||
kp->ki_stat = SSLEEP;
|
||||
} else if (P_SHOULDSTOP(&proc)) {
|
||||
kp->ki_stat = SSTOP;
|
||||
} else if (mainthread.td_state == TDS_MTX) {
|
||||
kp->ki_stat = SMTX;
|
||||
} else {
|
||||
kp->ki_stat = SWAIT;
|
||||
} else if (mtd.td_state == TDS_INHIBITED) {
|
||||
if (P_SHOULDSTOP(&proc)) {
|
||||
kp->ki_stat = SSTOP;
|
||||
} else if (TD_IS_SLEEPING(&mtd)) {
|
||||
kp->ki_stat = SSLEEP;
|
||||
} else if (TD_ON_MUTEX(&mtd)) {
|
||||
kp->ki_stat = SMTX;
|
||||
} else {
|
||||
kp->ki_stat = SWAIT;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
kp->ki_stat = SIDL;
|
||||
}
|
||||
kp->ki_pri.pri_class = proc.p_ksegrp.kg_pri_class;
|
||||
kp->ki_pri.pri_user = proc.p_ksegrp.kg_user_pri;
|
||||
kp->ki_pri.pri_level = mainthread.td_priority;
|
||||
kp->ki_pri.pri_native = mainthread.td_base_pri;
|
||||
kp->ki_pri.pri_level = mtd.td_priority;
|
||||
kp->ki_pri.pri_native = mtd.td_base_pri;
|
||||
kp->ki_nice = proc.p_ksegrp.kg_nice;
|
||||
kp->ki_lock = proc.p_lock;
|
||||
kp->ki_rqindex = proc.p_kse.ke_rqindex;
|
||||
kp->ki_oncpu = proc.p_kse.ke_oncpu;
|
||||
kp->ki_lastcpu = mainthread.td_lastcpu;
|
||||
kp->ki_lastcpu = mtd.td_lastcpu;
|
||||
} else {
|
||||
kp->ki_stat = SZOMB;
|
||||
}
|
||||
|
@ -180,6 +180,7 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
|
||||
* Make this runnable after we are finished with it.
|
||||
*/
|
||||
mtx_lock_spin(&sched_lock);
|
||||
TD_SET_CAN_RUN(td2);
|
||||
setrunqueue(FIRST_THREAD_IN_PROC(p2));
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
|
||||
|
@ -566,18 +566,13 @@ linprocfs_doprocstatus(PFS_FILL_ARGS)
|
||||
break;
|
||||
}
|
||||
switch(td2->td_state) {
|
||||
case TDS_SLP:
|
||||
case TDS_MTX:
|
||||
case TDS_INHIBITED:
|
||||
state = "S (sleeping)";
|
||||
break;
|
||||
case TDS_RUNQ:
|
||||
case TDS_RUNNING:
|
||||
state = "R (running)";
|
||||
break;
|
||||
case TDS_NEW:
|
||||
case TDS_UNQUEUED:
|
||||
case TDS_IWAIT:
|
||||
case TDS_SURPLUS:
|
||||
default:
|
||||
state = "? (unknown)";
|
||||
break;
|
||||
|
@ -112,7 +112,7 @@ db_ps(dummy1, dummy2, dummy3, dummy4)
|
||||
state = "wait";
|
||||
break;
|
||||
case PRS_ZOMBIE:
|
||||
state = "zomp";
|
||||
state = "zomb";
|
||||
break;
|
||||
default:
|
||||
state = "Unkn";
|
||||
@ -123,33 +123,56 @@ db_ps(dummy1, dummy2, dummy3, dummy4)
|
||||
p->p_ucred != NULL ? p->p_ucred->cr_ruid : 0, pp->p_pid,
|
||||
p->p_pgrp != NULL ? p->p_pgrp->pg_id : 0, p->p_flag,
|
||||
state);
|
||||
if (p->p_flag & P_KSES) {
|
||||
if (p->p_flag & P_KSES)
|
||||
db_printf("(threaded) %s\n", p->p_comm);
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
db_printf( ". . . . . . . "
|
||||
". thread %p . . . ", td);
|
||||
if (td->td_wchan != NULL) {
|
||||
db_printf("SLP %6s %8p\n", td->td_wmesg,
|
||||
(void *)td->td_wchan);
|
||||
} else if (td->td_state == TDS_MTX) {
|
||||
db_printf("MTX %6s %8p\n", td->td_mtxname,
|
||||
(void *)td->td_blocked);
|
||||
} else {
|
||||
db_printf("--not blocked--\n");
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
if (p->p_flag & P_KSES)
|
||||
db_printf( " thread %p ", td);
|
||||
if (TD_ON_SLEEPQ(td)) {
|
||||
if (td->td_flags & TDF_CVWAITQ)
|
||||
db_printf("[CVQ ");
|
||||
else
|
||||
db_printf("[SLPQ ");
|
||||
db_printf(" %6s %8p]", td->td_wmesg,
|
||||
(void *)td->td_wchan);
|
||||
}
|
||||
switch (td->td_state) {
|
||||
case TDS_INHIBITED:
|
||||
if (TD_ON_MUTEX(td)) {
|
||||
db_printf("[MTX %6s %8p]",
|
||||
td->td_mtxname,
|
||||
(void *)td->td_blocked);
|
||||
}
|
||||
if (TD_IS_SLEEPING(td)) {
|
||||
db_printf("[SLP]");
|
||||
}
|
||||
if (TD_IS_SWAPPED(td)) {
|
||||
db_printf("[SWAP]");
|
||||
}
|
||||
if (TD_IS_SUSPENDED(td)) {
|
||||
db_printf("[SUSP]");
|
||||
}
|
||||
if (TD_AWAITING_INTR(td)) {
|
||||
db_printf("[IWAIT]");
|
||||
}
|
||||
break;
|
||||
case TDS_CAN_RUN:
|
||||
db_printf("[Can run]");
|
||||
break;
|
||||
case TDS_RUNQ:
|
||||
db_printf("[RUNQ]");
|
||||
break;
|
||||
case TDS_RUNNING:
|
||||
db_printf("[CPU %d]", td->td_kse->ke_oncpu);
|
||||
break;
|
||||
default:
|
||||
panic("unknown thread state");
|
||||
}
|
||||
} else {
|
||||
td = FIRST_THREAD_IN_PROC(p);
|
||||
if (td != NULL && td->td_wchan != NULL) {
|
||||
db_printf(" %-6s %8p", td->td_wmesg,
|
||||
(void *)td->td_wchan);
|
||||
} else if (td != NULL && td->td_state == TDS_MTX) {
|
||||
db_printf(" %6s %8p", td->td_mtxname,
|
||||
(void *)td->td_blocked);
|
||||
} else {
|
||||
db_printf(" ");
|
||||
}
|
||||
db_printf(" %s\n", p->p_comm);
|
||||
if (p->p_flag & P_KSES)
|
||||
db_printf("\n");
|
||||
else
|
||||
db_printf(" %s\n", p->p_comm);
|
||||
|
||||
}
|
||||
/* PROC_UNLOCK(p); */
|
||||
|
||||
|
@ -352,7 +352,7 @@ procfs_doprocctl(PFS_FILL_ARGS)
|
||||
mtx_lock_spin(&sched_lock);
|
||||
/* XXXKSE: */
|
||||
p->p_flag &= ~P_STOPPED_SIG;
|
||||
setrunnable(FIRST_THREAD_IN_PROC(p));
|
||||
thread_unsuspend(p);
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
} else
|
||||
psignal(p, nm->nm_val);
|
||||
|
@ -97,8 +97,7 @@ procfs_ioctl(PFS_IOCTL_ARGS)
|
||||
if (P_SHOULDSTOP(p)) {
|
||||
p->p_xstat = sig;
|
||||
p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG);
|
||||
FOREACH_THREAD_IN_PROC(p, td)
|
||||
setrunnable(td); /* XXX Totally bogus */
|
||||
thread_unsuspend(p);
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
} else {
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
|
@ -362,6 +362,7 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
|
||||
* Make this runnable after we are finished with it.
|
||||
*/
|
||||
mtx_lock_spin(&sched_lock);
|
||||
TD_SET_CAN_RUN(FIRST_THREAD_IN_PROC(p2));
|
||||
setrunqueue(FIRST_THREAD_IN_PROC(p2));
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
PROC_UNLOCK(p2);
|
||||
|
@ -716,6 +716,7 @@ kick_init(const void *udata __unused)
|
||||
|
||||
td = FIRST_THREAD_IN_PROC(initproc);
|
||||
mtx_lock_spin(&sched_lock);
|
||||
TD_SET_CAN_RUN(td);
|
||||
setrunqueue(td); /* XXXKSE */
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
}
|
||||
|
@ -48,7 +48,7 @@
|
||||
*/
|
||||
#define CV_ASSERT(cvp, mp, td) do { \
|
||||
KASSERT((td) != NULL, ("%s: curthread NULL", __func__)); \
|
||||
KASSERT((td)->td_state == TDS_RUNNING, ("%s: not TDS_RUNNING", __func__)); \
|
||||
KASSERT(TD_IS_RUNNING(td), ("%s: not TDS_RUNNING", __func__)); \
|
||||
KASSERT((cvp) != NULL, ("%s: cvp NULL", __func__)); \
|
||||
KASSERT((mp) != NULL, ("%s: mp NULL", __func__)); \
|
||||
mtx_assert((mp), MA_OWNED | MA_NOTRECURSED); \
|
||||
@ -68,12 +68,14 @@
|
||||
("%s: Multiple mutexes", __func__)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CV_SIGNAL_VALIDATE(cvp) do { \
|
||||
if (!TAILQ_EMPTY(&(cvp)->cv_waitq)) { \
|
||||
KASSERT(mtx_owned((cvp)->cv_mtx), \
|
||||
("%s: Mutex not owned", __func__)); \
|
||||
("%s: Mutex not owned", __func__)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define CV_WAIT_VALIDATE(cvp, mp)
|
||||
#define CV_SIGNAL_VALIDATE(cvp)
|
||||
@ -148,9 +150,9 @@ static __inline void
|
||||
cv_switch(struct thread *td)
|
||||
{
|
||||
|
||||
td->td_state = TDS_SLP;
|
||||
td->td_proc->p_stats->p_ru.ru_nvcsw++;
|
||||
cv_check_upcall(td);
|
||||
TD_SET_SLEEPING(td);
|
||||
td->td_proc->p_stats->p_ru.ru_nvcsw++;
|
||||
mi_switch();
|
||||
CTR3(KTR_PROC, "cv_switch: resume thread %p (pid %d, %s)", td,
|
||||
td->td_proc->p_pid, td->td_proc->p_comm);
|
||||
@ -171,22 +173,23 @@ cv_switch_catch(struct thread *td)
|
||||
* both) could occur while we were stopped. A SIGCONT would cause us to
|
||||
* be marked as TDS_SLP without resuming us, thus we must be ready for
|
||||
* sleep when cursig is called. If the wakeup happens while we're
|
||||
* stopped, td->td_wchan will be 0 upon return from cursig.
|
||||
* stopped, td->td_wchan will be 0 upon return from cursig,
|
||||
* and TD_ON_SLEEPQ() will return false.
|
||||
*/
|
||||
td->td_flags |= TDF_SINTR;
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
p = td->td_proc;
|
||||
PROC_LOCK(p);
|
||||
sig = cursig(td); /* XXXKSE */
|
||||
sig = cursig(td);
|
||||
if (thread_suspend_check(1))
|
||||
sig = SIGSTOP;
|
||||
mtx_lock_spin(&sched_lock);
|
||||
PROC_UNLOCK(p);
|
||||
if (sig != 0) {
|
||||
if (td->td_wchan != NULL)
|
||||
if (TD_ON_SLEEPQ(td))
|
||||
cv_waitq_remove(td);
|
||||
td->td_state = TDS_RUNNING; /* XXXKSE */
|
||||
} else if (td->td_wchan != NULL) {
|
||||
TD_SET_RUNNING(td);
|
||||
} else if (TD_ON_SLEEPQ(td)) {
|
||||
cv_switch(td);
|
||||
}
|
||||
td->td_flags &= ~TDF_SINTR;
|
||||
@ -202,6 +205,7 @@ cv_waitq_add(struct cv *cvp, struct thread *td)
|
||||
{
|
||||
|
||||
td->td_flags |= TDF_CVWAITQ;
|
||||
TD_SET_ON_SLEEPQ(td);
|
||||
td->td_wchan = cvp;
|
||||
td->td_wmesg = cvp->cv_description;
|
||||
td->td_ksegrp->kg_slptime = 0; /* XXXKSE */
|
||||
@ -389,10 +393,10 @@ cv_timedwait(struct cv *cvp, struct mtx *mp, int timo)
|
||||
* between msleep and endtsleep.
|
||||
* Go back to sleep.
|
||||
*/
|
||||
td->td_flags |= TDF_TIMEOUT;
|
||||
td->td_state = TDS_SLP;
|
||||
TD_SET_SLEEPING(td);
|
||||
td->td_proc->p_stats->p_ru.ru_nivcsw++;
|
||||
mi_switch();
|
||||
td->td_flags &= ~TDF_TIMOFAIL;
|
||||
}
|
||||
|
||||
if (td->td_proc->p_flag & P_WEXIT)
|
||||
@ -467,10 +471,10 @@ cv_timedwait_sig(struct cv *cvp, struct mtx *mp, int timo)
|
||||
* between msleep and endtsleep.
|
||||
* Go back to sleep.
|
||||
*/
|
||||
td->td_flags |= TDF_TIMEOUT;
|
||||
td->td_state = TDS_SLP;
|
||||
TD_SET_SLEEPING(td);
|
||||
td->td_proc->p_stats->p_ru.ru_nivcsw++;
|
||||
mi_switch();
|
||||
td->td_flags &= ~TDF_TIMOFAIL;
|
||||
}
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
|
||||
@ -507,35 +511,14 @@ static __inline void
|
||||
cv_wakeup(struct cv *cvp)
|
||||
{
|
||||
struct thread *td;
|
||||
struct ksegrp *kg;
|
||||
|
||||
mtx_assert(&sched_lock, MA_OWNED);
|
||||
td = TAILQ_FIRST(&cvp->cv_waitq);
|
||||
KASSERT(td->td_wchan == cvp, ("%s: bogus wchan", __func__));
|
||||
KASSERT(td->td_flags & TDF_CVWAITQ, ("%s: not on waitq", __func__));
|
||||
TAILQ_REMOVE(&cvp->cv_waitq, td, td_slpq);
|
||||
td->td_flags &= ~TDF_CVWAITQ;
|
||||
td->td_wchan = 0;
|
||||
if (td->td_state == TDS_SLP) {
|
||||
/* OPTIMIZED EXPANSION OF setrunnable(td); */
|
||||
CTR3(KTR_PROC, "cv_wakeup: thread %p (pid %d, %s)",
|
||||
td, td->td_proc->p_pid, td->td_proc->p_comm);
|
||||
kg = td->td_ksegrp;
|
||||
if (kg->kg_slptime > 1) /* XXXKSE */
|
||||
updatepri(kg);
|
||||
kg->kg_slptime = 0;
|
||||
if (td->td_proc->p_sflag & PS_INMEM) {
|
||||
setrunqueue(td);
|
||||
maybe_resched(td);
|
||||
} else {
|
||||
td->td_state = TDS_SWAPPED;
|
||||
if ((td->td_proc->p_sflag & PS_SWAPPINGIN) == 0) {
|
||||
td->td_proc->p_sflag |= PS_SWAPINREQ;
|
||||
wakeup(&proc0);
|
||||
}
|
||||
}
|
||||
/* END INLINE EXPANSION */
|
||||
}
|
||||
cv_waitq_remove(td);
|
||||
TD_CLR_SLEEPING(td);
|
||||
setrunnable(td);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -583,13 +566,12 @@ cv_waitq_remove(struct thread *td)
|
||||
{
|
||||
struct cv *cvp;
|
||||
|
||||
mtx_lock_spin(&sched_lock);
|
||||
mtx_assert(&sched_lock, MA_OWNED);
|
||||
if ((cvp = td->td_wchan) != NULL && td->td_flags & TDF_CVWAITQ) {
|
||||
TAILQ_REMOVE(&cvp->cv_waitq, td, td_slpq);
|
||||
td->td_flags &= ~TDF_CVWAITQ;
|
||||
td->td_wchan = NULL;
|
||||
TD_CLR_ON_SLEEPQ(td);
|
||||
}
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -602,29 +584,17 @@ cv_timedwait_end(void *arg)
|
||||
struct thread *td;
|
||||
|
||||
td = arg;
|
||||
CTR3(KTR_PROC, "cv_timedwait_end: thread %p (pid %d, %s)", td, td->td_proc->p_pid,
|
||||
td->td_proc->p_comm);
|
||||
CTR3(KTR_PROC, "cv_timedwait_end: thread %p (pid %d, %s)",
|
||||
td, td->td_proc->p_pid, td->td_proc->p_comm);
|
||||
mtx_lock_spin(&sched_lock);
|
||||
if (td->td_flags & TDF_TIMEOUT) {
|
||||
td->td_flags &= ~TDF_TIMEOUT;
|
||||
if (td->td_proc->p_sflag & PS_INMEM) {
|
||||
setrunqueue(td);
|
||||
maybe_resched(td);
|
||||
} else {
|
||||
td->td_state = TDS_SWAPPED;
|
||||
if ((td->td_proc->p_sflag & PS_SWAPPINGIN) == 0) {
|
||||
td->td_proc->p_sflag |= PS_SWAPINREQ;
|
||||
wakeup(&proc0);
|
||||
}
|
||||
}
|
||||
} else if (td->td_wchan != NULL) {
|
||||
if (td->td_state == TDS_SLP) /* XXXKSE */
|
||||
setrunnable(td);
|
||||
else
|
||||
cv_waitq_remove(td);
|
||||
if (TD_ON_SLEEPQ(td)) {
|
||||
cv_waitq_remove(td);
|
||||
td->td_flags |= TDF_TIMEOUT;
|
||||
} else
|
||||
} else {
|
||||
td->td_flags |= TDF_TIMOFAIL;
|
||||
}
|
||||
TD_CLR_SLEEPING(td);
|
||||
setrunnable(td);
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
}
|
||||
|
||||
@ -637,16 +607,14 @@ cv_abort(struct thread *td)
|
||||
{
|
||||
|
||||
CTR3(KTR_PROC, "cv_abort: thread %p (pid %d, %s)", td,
|
||||
td->td_proc->p_pid,
|
||||
td->td_proc->p_comm);
|
||||
td->td_proc->p_pid, td->td_proc->p_comm);
|
||||
mtx_lock_spin(&sched_lock);
|
||||
if ((td->td_flags & (TDF_SINTR|TDF_TIMEOUT)) == TDF_SINTR) {
|
||||
if (td->td_wchan != NULL) {
|
||||
if (td->td_state == TDS_SLP)
|
||||
setrunnable(td);
|
||||
else
|
||||
cv_waitq_remove(td);
|
||||
if (TD_ON_SLEEPQ(td)) {
|
||||
cv_waitq_remove(td);
|
||||
}
|
||||
TD_CLR_SLEEPING(td);
|
||||
setrunnable(td);
|
||||
}
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
}
|
||||
|
@ -711,6 +711,7 @@ fork1(td, flags, procp)
|
||||
if ((flags & RFSTOPPED) == 0) {
|
||||
mtx_lock_spin(&sched_lock);
|
||||
p2->p_state = PRS_NORMAL;
|
||||
TD_SET_CAN_RUN(td2);
|
||||
setrunqueue(td2);
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ idle_setup(void *dummy)
|
||||
p->p_flag |= P_NOLOAD;
|
||||
p->p_state = PRS_NORMAL;
|
||||
td = FIRST_THREAD_IN_PROC(p);
|
||||
td->td_state = TDS_UNQUEUED;
|
||||
td->td_state = TDS_CAN_RUN;
|
||||
td->td_kse->ke_flags |= KEF_IDLEKSE;
|
||||
#ifdef SMP
|
||||
}
|
||||
@ -112,7 +112,7 @@ idle_proc(void *dummy)
|
||||
|
||||
mtx_lock_spin(&sched_lock);
|
||||
p->p_stats->p_ru.ru_nvcsw++;
|
||||
td->td_state = TDS_UNQUEUED;
|
||||
td->td_state = TDS_CAN_RUN;
|
||||
mi_switch();
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ ithread_create(struct ithd **ithread, int vector, int flags,
|
||||
td = FIRST_THREAD_IN_PROC(p); /* XXXKSE */
|
||||
td->td_ksegrp->kg_pri_class = PRI_ITHD;
|
||||
td->td_priority = PRI_MAX_ITHD;
|
||||
td->td_state = TDS_IWAIT;
|
||||
TD_SET_IWAIT(td);
|
||||
ithd->it_td = td;
|
||||
td->td_ithd = ithd;
|
||||
if (ithread != NULL)
|
||||
@ -229,7 +229,8 @@ ithread_destroy(struct ithd *ithread)
|
||||
}
|
||||
ithread->it_flags |= IT_DEAD;
|
||||
mtx_lock_spin(&sched_lock);
|
||||
if (td->td_state == TDS_IWAIT) {
|
||||
if (TD_AWAITING_INTR(td)) {
|
||||
TD_CLR_IWAIT(td);
|
||||
setrunqueue(td);
|
||||
}
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
@ -326,7 +327,7 @@ ithread_remove_handler(void *cookie)
|
||||
* handler as being dead and let the ithread do the actual removal.
|
||||
*/
|
||||
mtx_lock_spin(&sched_lock);
|
||||
if (ithread->it_td->td_state != TDS_IWAIT) {
|
||||
if (!TD_AWAITING_INTR(ithread->it_td)) {
|
||||
handler->ih_flags |= IH_DEAD;
|
||||
|
||||
/*
|
||||
@ -388,16 +389,17 @@ ithread_schedule(struct ithd *ithread, int do_switch)
|
||||
*/
|
||||
ithread->it_need = 1;
|
||||
mtx_lock_spin(&sched_lock);
|
||||
if (td->td_state == TDS_IWAIT) {
|
||||
if (TD_AWAITING_INTR(td)) {
|
||||
CTR2(KTR_INTR, "%s: setrunqueue %d", __func__, p->p_pid);
|
||||
TD_CLR_IWAIT(td);
|
||||
setrunqueue(td);
|
||||
if (do_switch &&
|
||||
(ctd->td_critnest == 1) ) {
|
||||
KASSERT((ctd->td_state == TDS_RUNNING),
|
||||
KASSERT((TD_IS_RUNNING(ctd)),
|
||||
("ithread_schedule: Bad state for curthread."));
|
||||
ctd->td_proc->p_stats->p_ru.ru_nivcsw++;
|
||||
if (ctd->td_kse->ke_flags & KEF_IDLEKSE)
|
||||
ctd->td_state = TDS_UNQUEUED;
|
||||
ctd->td_state = TDS_CAN_RUN; /* XXXKSE */
|
||||
mi_switch();
|
||||
} else {
|
||||
curthread->td_kse->ke_flags |= KEF_NEEDRESCHED;
|
||||
@ -552,7 +554,7 @@ ithread_loop(void *arg)
|
||||
*/
|
||||
if (ithd->it_enable != NULL)
|
||||
ithd->it_enable(ithd->it_vector);
|
||||
td->td_state = TDS_IWAIT; /* we're idle */
|
||||
TD_SET_IWAIT(td); /* we're idle */
|
||||
p->p_stats->p_ru.ru_nvcsw++;
|
||||
CTR2(KTR_INTR, "%s: pid %d: done", __func__, p->p_pid);
|
||||
mi_switch();
|
||||
|
@ -95,7 +95,7 @@ thread_ctor(void *mem, int size, void *arg)
|
||||
("size mismatch: %d != %d\n", size, (int)sizeof(struct thread)));
|
||||
|
||||
td = (struct thread *)mem;
|
||||
td->td_state = TDS_NEW;
|
||||
td->td_state = TDS_INACTIVE;
|
||||
td->td_flags |= TDF_UNBOUND;
|
||||
cached_threads--; /* XXXSMP */
|
||||
active_threads++; /* XXXSMP */
|
||||
@ -117,8 +117,9 @@ thread_dtor(void *mem, int size, void *arg)
|
||||
#ifdef INVARIANTS
|
||||
/* Verify that this thread is in a safe state to free. */
|
||||
switch (td->td_state) {
|
||||
case TDS_SLP:
|
||||
case TDS_MTX:
|
||||
case TDS_INHIBITED:
|
||||
case TDS_RUNNING:
|
||||
case TDS_CAN_RUN:
|
||||
case TDS_RUNQ:
|
||||
/*
|
||||
* We must never unlink a thread that is in one of
|
||||
@ -126,10 +127,7 @@ thread_dtor(void *mem, int size, void *arg)
|
||||
*/
|
||||
panic("bad state for thread unlinking");
|
||||
/* NOTREACHED */
|
||||
case TDS_UNQUEUED:
|
||||
case TDS_NEW:
|
||||
case TDS_RUNNING:
|
||||
case TDS_SURPLUS:
|
||||
case TDS_INACTIVE:
|
||||
break;
|
||||
default:
|
||||
panic("bad thread state");
|
||||
@ -316,7 +314,7 @@ thread_exit(void)
|
||||
KASSERT(!mtx_owned(&Giant), ("dying thread owns giant"));
|
||||
|
||||
if (ke->ke_tdspare != NULL) {
|
||||
thread_free(ke->ke_tdspare);
|
||||
thread_stash(ke->ke_tdspare);
|
||||
ke->ke_tdspare = NULL;
|
||||
}
|
||||
cpu_thread_exit(td); /* XXXSMP */
|
||||
@ -345,14 +343,11 @@ thread_exit(void)
|
||||
*/
|
||||
if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
|
||||
if (p->p_numthreads == p->p_suspcount) {
|
||||
TAILQ_REMOVE(&p->p_suspended,
|
||||
p->p_singlethread, td_runq);
|
||||
setrunqueue(p->p_singlethread);
|
||||
p->p_suspcount--;
|
||||
thread_unsuspend_one(p->p_singlethread);
|
||||
}
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
td->td_state = TDS_SURPLUS;
|
||||
td->td_state = TDS_INACTIVE;
|
||||
td->td_proc = NULL;
|
||||
td->td_ksegrp = NULL;
|
||||
td->td_last_kse = NULL;
|
||||
@ -379,7 +374,7 @@ thread_link(struct thread *td, struct ksegrp *kg)
|
||||
struct proc *p;
|
||||
|
||||
p = kg->kg_proc;
|
||||
td->td_state = TDS_NEW;
|
||||
td->td_state = TDS_INACTIVE;
|
||||
td->td_proc = p;
|
||||
td->td_ksegrp = kg;
|
||||
td->td_last_kse = NULL;
|
||||
@ -427,6 +422,7 @@ thread_schedule_upcall(struct thread *td, struct kse *ke)
|
||||
cpu_set_upcall(td2, ke->ke_pcb);
|
||||
td2->td_ucred = crhold(td->td_ucred);
|
||||
td2->td_flags = TDF_UNBOUND|TDF_UPCALLING;
|
||||
TD_SET_CAN_RUN(td2);
|
||||
setrunqueue(td2);
|
||||
return (td2);
|
||||
}
|
||||
@ -607,38 +603,32 @@ thread_single(int force_exit)
|
||||
p->p_flag |= P_STOPPED_SINGLE;
|
||||
p->p_singlethread = td;
|
||||
while ((p->p_numthreads - p->p_suspcount) != 1) {
|
||||
mtx_lock_spin(&sched_lock);
|
||||
FOREACH_THREAD_IN_PROC(p, td2) {
|
||||
if (td2 == td)
|
||||
continue;
|
||||
switch(td2->td_state) {
|
||||
case TDS_SUSPENDED:
|
||||
if (force_exit == SINGLE_EXIT) {
|
||||
mtx_lock_spin(&sched_lock);
|
||||
TAILQ_REMOVE(&p->p_suspended,
|
||||
td, td_runq);
|
||||
p->p_suspcount--;
|
||||
setrunqueue(td); /* Should suicide. */
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
if (TD_IS_INHIBITED(td2)) {
|
||||
if (TD_IS_SUSPENDED(td2)) {
|
||||
if (force_exit == SINGLE_EXIT) {
|
||||
thread_unsuspend_one(td2);
|
||||
}
|
||||
}
|
||||
case TDS_SLP:
|
||||
if (td2->td_flags & TDF_CVWAITQ)
|
||||
cv_abort(td2);
|
||||
else
|
||||
abortsleep(td2);
|
||||
break;
|
||||
/* case TDS RUNNABLE: XXXKSE maybe raise priority? */
|
||||
default: /* needed to avoid an error */
|
||||
break;
|
||||
if ( TD_IS_SLEEPING(td2)) {
|
||||
if (td2->td_flags & TDF_CVWAITQ)
|
||||
cv_waitq_remove(td2);
|
||||
else
|
||||
unsleep(td2);
|
||||
break;
|
||||
}
|
||||
if (TD_CAN_RUN(td2))
|
||||
setrunqueue(td2);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Wake us up when everyone else has suspended.
|
||||
* In the mean time we suspend as well.
|
||||
*/
|
||||
mtx_lock_spin(&sched_lock);
|
||||
TAILQ_INSERT_TAIL(&p->p_suspended, td, td_runq);
|
||||
td->td_state = TDS_SUSPENDED;
|
||||
p->p_suspcount++;
|
||||
thread_suspend_one(td);
|
||||
mtx_unlock(&Giant);
|
||||
PROC_UNLOCK(p);
|
||||
mi_switch();
|
||||
@ -745,16 +735,11 @@ thread_suspend_check(int return_instead)
|
||||
mtx_lock_spin(&sched_lock);
|
||||
}
|
||||
mtx_assert(&Giant, MA_NOTOWNED);
|
||||
p->p_suspcount++;
|
||||
td->td_state = TDS_SUSPENDED;
|
||||
TAILQ_INSERT_TAIL(&p->p_suspended, td, td_runq);
|
||||
thread_suspend_one(td);
|
||||
PROC_UNLOCK(p);
|
||||
if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
|
||||
if (p->p_numthreads == p->p_suspcount) {
|
||||
TAILQ_REMOVE(&p->p_suspended,
|
||||
p->p_singlethread, td_runq);
|
||||
p->p_suspcount--;
|
||||
setrunqueue(p->p_singlethread);
|
||||
thread_unsuspend_one(p->p_singlethread);
|
||||
}
|
||||
}
|
||||
p->p_stats->p_ru.ru_nivcsw++;
|
||||
@ -772,8 +757,15 @@ thread_suspend_one(struct thread *td)
|
||||
|
||||
mtx_assert(&sched_lock, MA_OWNED);
|
||||
p->p_suspcount++;
|
||||
td->td_state = TDS_SUSPENDED;
|
||||
TD_SET_SUSPENDED(td);
|
||||
TAILQ_INSERT_TAIL(&p->p_suspended, td, td_runq);
|
||||
/*
|
||||
* Hack: If we are suspending but are on the sleep queue
|
||||
* then we are in msleep or the cv equivalent. We
|
||||
* want to look like we have two Inhibitors.
|
||||
*/
|
||||
if (TD_ON_SLEEPQ(td))
|
||||
TD_SET_SLEEPING(td);
|
||||
}
|
||||
|
||||
void
|
||||
@ -783,16 +775,9 @@ thread_unsuspend_one(struct thread *td)
|
||||
|
||||
mtx_assert(&sched_lock, MA_OWNED);
|
||||
TAILQ_REMOVE(&p->p_suspended, td, td_runq);
|
||||
TD_CLR_SUSPENDED(td);
|
||||
p->p_suspcount--;
|
||||
if (td->td_wchan != NULL) {
|
||||
td->td_state = TDS_SLP;
|
||||
} else {
|
||||
if (td->td_ksegrp->kg_slptime > 1) {
|
||||
updatepri(td->td_ksegrp);
|
||||
td->td_ksegrp->kg_slptime = 0;
|
||||
}
|
||||
setrunqueue(td);
|
||||
}
|
||||
setrunnable(td);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -840,9 +825,7 @@ thread_single_end(void)
|
||||
if ((p->p_numthreads != 1) && (!P_SHOULDSTOP(p))) {
|
||||
mtx_lock_spin(&sched_lock);
|
||||
while (( td = TAILQ_FIRST(&p->p_suspended))) {
|
||||
TAILQ_REMOVE(&p->p_suspended, td, td_runq);
|
||||
p->p_suspcount--;
|
||||
setrunqueue(td);
|
||||
thread_unsuspend_one(td);
|
||||
}
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
}
|
||||
|
@ -76,6 +76,7 @@ kthread_create(void (*func)(void *), void *arg,
|
||||
{
|
||||
int error;
|
||||
va_list ap;
|
||||
struct thread *td;
|
||||
struct proc *p2;
|
||||
|
||||
if (!proc0.p_stats /* || proc0.p_stats->p_start.tv_sec == 0 */)
|
||||
@ -103,13 +104,15 @@ kthread_create(void (*func)(void *), void *arg,
|
||||
va_end(ap);
|
||||
|
||||
/* call the processes' main()... */
|
||||
cpu_set_fork_handler(FIRST_THREAD_IN_PROC(p2), func, arg);
|
||||
td = FIRST_THREAD_IN_PROC(p2);
|
||||
cpu_set_fork_handler(td, func, arg);
|
||||
TD_SET_CAN_RUN(td);
|
||||
|
||||
/* Delay putting it on the run queue until now. */
|
||||
mtx_lock_spin(&sched_lock);
|
||||
p2->p_sflag |= PS_INMEM;
|
||||
if (!(flags & RFSTOPPED)) {
|
||||
setrunqueue(FIRST_THREAD_IN_PROC(p2));
|
||||
setrunqueue(td);
|
||||
}
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
|
||||
|
@ -119,11 +119,9 @@ propagate_priority(struct thread *td)
|
||||
return;
|
||||
}
|
||||
|
||||
KASSERT(td->td_state != TDS_SURPLUS, ("Mutex owner SURPLUS"));
|
||||
MPASS(td->td_proc != NULL);
|
||||
MPASS(td->td_proc->p_magic == P_MAGIC);
|
||||
KASSERT(td->td_state != TDS_SLP,
|
||||
("sleeping thread owns a mutex"));
|
||||
KASSERT(!TD_IS_SLEEPING(td), ("sleeping thread owns a mutex"));
|
||||
if (td->td_priority <= pri) /* lower is higher priority */
|
||||
return;
|
||||
|
||||
@ -131,7 +129,7 @@ propagate_priority(struct thread *td)
|
||||
/*
|
||||
* If lock holder is actually running, just bump priority.
|
||||
*/
|
||||
if (td->td_state == TDS_RUNNING) {
|
||||
if (TD_IS_RUNNING(td)) {
|
||||
td->td_priority = pri;
|
||||
return;
|
||||
}
|
||||
@ -150,7 +148,7 @@ propagate_priority(struct thread *td)
|
||||
* but try anyhow.
|
||||
* We should have a special call to do this more efficiently.
|
||||
*/
|
||||
if (td->td_state == TDS_RUNQ) {
|
||||
if (TD_ON_RUNQ(td)) {
|
||||
MPASS(td->td_blocked == NULL);
|
||||
remrunqueue(td);
|
||||
td->td_priority = pri;
|
||||
@ -165,7 +163,7 @@ propagate_priority(struct thread *td)
|
||||
/*
|
||||
* If we aren't blocked on a mutex, we should be.
|
||||
*/
|
||||
KASSERT(td->td_state == TDS_MTX, (
|
||||
KASSERT(TD_ON_MUTEX(td), (
|
||||
"process %d(%s):%d holds %s but isn't blocked on a mutex\n",
|
||||
td->td_proc->p_pid, td->td_proc->p_comm, td->td_state,
|
||||
m->mtx_object.lo_name));
|
||||
@ -619,7 +617,7 @@ _mtx_lock_sleep(struct mtx *m, int opts, const char *file, int line)
|
||||
*/
|
||||
td->td_blocked = m;
|
||||
td->td_mtxname = m->mtx_object.lo_name;
|
||||
td->td_state = TDS_MTX;
|
||||
TD_SET_MUTEX(td);
|
||||
propagate_priority(td);
|
||||
|
||||
if (LOCK_LOG_TEST(&m->mtx_object, opts))
|
||||
@ -763,6 +761,7 @@ _mtx_unlock_sleep(struct mtx *m, int opts, const char *file, int line)
|
||||
m, td1);
|
||||
|
||||
td1->td_blocked = NULL;
|
||||
TD_CLR_MUTEX(td1);
|
||||
setrunqueue(td1);
|
||||
|
||||
if (td->td_critnest == 1 && td1->td_priority < pri) {
|
||||
|
@ -854,7 +854,7 @@ fill_kinfo_proc(p, kp)
|
||||
strncpy(kp->ki_wmesg, td->td_wmesg,
|
||||
sizeof(kp->ki_wmesg) - 1);
|
||||
}
|
||||
if (td->td_state == TDS_MTX) {
|
||||
if (TD_ON_MUTEX(td)) {
|
||||
kp->ki_kiflag |= KI_MTXBLOCK;
|
||||
strncpy(kp->ki_mtxname, td->td_mtxname,
|
||||
sizeof(kp->ki_mtxname) - 1);
|
||||
@ -862,14 +862,14 @@ fill_kinfo_proc(p, kp)
|
||||
}
|
||||
|
||||
if (p->p_state == PRS_NORMAL) { /* XXXKSE very approximate */
|
||||
if ((td->td_state == TDS_RUNQ) ||
|
||||
(td->td_state == TDS_RUNNING)) {
|
||||
if ((TD_ON_RUNQ(td)) ||
|
||||
(TD_IS_RUNNING(td))) {
|
||||
kp->ki_stat = SRUN;
|
||||
} else if (td->td_state == TDS_SLP) {
|
||||
} else if (TD_IS_SLEEPING(td)) {
|
||||
kp->ki_stat = SSLEEP;
|
||||
} else if (P_SHOULDSTOP(p)) {
|
||||
kp->ki_stat = SSTOP;
|
||||
} else if (td->td_state == TDS_MTX) {
|
||||
} else if (TD_ON_MUTEX(td)) {
|
||||
kp->ki_stat = SMTX;
|
||||
} else {
|
||||
kp->ki_stat = SWAIT;
|
||||
|
@ -1410,12 +1410,11 @@ psignal(p, sig)
|
||||
*/
|
||||
mtx_lock_spin(&sched_lock);
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
if (td->td_wchan && (td->td_flags & TDF_SINTR)) {
|
||||
if (TD_ON_SLEEPQ(td) && (td->td_flags & TDF_SINTR)) {
|
||||
if (td->td_flags & TDF_CVWAITQ)
|
||||
cv_waitq_remove(td);
|
||||
cv_abort(td);
|
||||
else
|
||||
unsleep(td);
|
||||
setrunnable(td);
|
||||
abortsleep(td);
|
||||
}
|
||||
}
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
@ -1447,7 +1446,7 @@ psignal(p, sig)
|
||||
goto out;
|
||||
mtx_lock_spin(&sched_lock);
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
if (td->td_state == TDS_SLP &&
|
||||
if (TD_IS_SLEEPING(td) &&
|
||||
(td->td_flags & TDF_SINTR))
|
||||
thread_suspend_one(td);
|
||||
}
|
||||
@ -1522,7 +1521,7 @@ tdsignal(struct thread *td, int sig, sig_t action)
|
||||
if (action == SIG_HOLD) {
|
||||
return;
|
||||
}
|
||||
if (td->td_state == TDS_SLP) {
|
||||
if (TD_IS_SLEEPING(td)) {
|
||||
/*
|
||||
* If thread is sleeping uninterruptibly
|
||||
* we can't interrupt the sleep... the signal will
|
||||
@ -1558,7 +1557,10 @@ tdsignal(struct thread *td, int sig, sig_t action)
|
||||
td->td_priority = PUSER;
|
||||
}
|
||||
}
|
||||
setrunnable(td);
|
||||
if (td->td_flags & TDF_CVWAITQ)
|
||||
cv_abort(td);
|
||||
else
|
||||
abortsleep(td);
|
||||
}
|
||||
#ifdef SMP
|
||||
else {
|
||||
@ -1567,7 +1569,7 @@ tdsignal(struct thread *td, int sig, sig_t action)
|
||||
* other than kicking ourselves if we are running.
|
||||
* It will either never be noticed, or noticed very soon.
|
||||
*/
|
||||
if (td->td_state == TDS_RUNNING && td != curthread) {
|
||||
if (TD_IS_RUNNING(td) && td != curthread) {
|
||||
forward_signal(td);
|
||||
}
|
||||
}
|
||||
@ -1629,7 +1631,7 @@ issignal(td)
|
||||
PROC_UNLOCK(p->p_pptr);
|
||||
mtx_lock_spin(&sched_lock);
|
||||
stop(p); /* uses schedlock too eventually */
|
||||
td->td_state = TDS_UNQUEUED;
|
||||
thread_suspend_one(td);
|
||||
PROC_UNLOCK(p);
|
||||
DROP_GIANT();
|
||||
p->p_stats->p_ru.ru_nivcsw++;
|
||||
@ -1713,9 +1715,7 @@ issignal(td)
|
||||
mtx_lock_spin(&sched_lock);
|
||||
}
|
||||
stop(p);
|
||||
p->p_suspcount++;
|
||||
td->td_state = TDS_SUSPENDED;
|
||||
TAILQ_INSERT_TAIL(&p->p_suspended, td, td_runq);
|
||||
thread_suspend_one(td);
|
||||
PROC_UNLOCK(p);
|
||||
DROP_GIANT();
|
||||
p->p_stats->p_ru.ru_nivcsw++;
|
||||
|
@ -163,7 +163,7 @@ choosethread(void)
|
||||
if (panicstr && ((td->td_proc->p_flag & P_SYSTEM) == 0 &&
|
||||
(td->td_flags & TDF_INPANIC) == 0))
|
||||
goto retry;
|
||||
td->td_state = TDS_RUNNING;
|
||||
TD_SET_RUNNING(td);
|
||||
return (td);
|
||||
}
|
||||
|
||||
@ -229,8 +229,7 @@ remrunqueue(struct thread *td)
|
||||
struct kse *ke;
|
||||
|
||||
mtx_assert(&sched_lock, MA_OWNED);
|
||||
KASSERT ((td->td_state == TDS_RUNQ),
|
||||
("remrunqueue: Bad state on run queue"));
|
||||
KASSERT ((TD_ON_RUNQ(td)), ("remrunqueue: Bad state on run queue"));
|
||||
kg = td->td_ksegrp;
|
||||
ke = td->td_kse;
|
||||
/*
|
||||
@ -238,8 +237,8 @@ remrunqueue(struct thread *td)
|
||||
* threads are BOUND.
|
||||
*/
|
||||
CTR1(KTR_RUNQ, "remrunqueue: td%p", td);
|
||||
td->td_state = TDS_UNQUEUED;
|
||||
kg->kg_runnable--;
|
||||
TD_SET_CAN_RUN(td);
|
||||
if ((td->td_flags & TDF_UNBOUND) == 0) {
|
||||
/* Bring its kse with it, leave the thread attached */
|
||||
runq_remove(&runq, ke);
|
||||
@ -300,8 +299,9 @@ setrunqueue(struct thread *td)
|
||||
|
||||
CTR1(KTR_RUNQ, "setrunqueue: td%p", td);
|
||||
mtx_assert(&sched_lock, MA_OWNED);
|
||||
KASSERT((td->td_state != TDS_RUNQ), ("setrunqueue: bad thread state"));
|
||||
td->td_state = TDS_RUNQ;
|
||||
KASSERT((TD_CAN_RUN(td) || TD_IS_RUNNING(td)),
|
||||
("setrunqueue: bad thread state"));
|
||||
TD_SET_RUNQ(td);
|
||||
kg = td->td_ksegrp;
|
||||
kg->kg_runnable++;
|
||||
if ((td->td_flags & TDF_UNBOUND) == 0) {
|
||||
@ -715,7 +715,7 @@ thread_sanity_check(struct thread *td)
|
||||
}
|
||||
FOREACH_THREAD_IN_GROUP(kg, td2) {
|
||||
if (((td2->td_flags & TDF_UNBOUND) == 0) &&
|
||||
(td2->td_state == TDS_RUNQ)) {
|
||||
(TD_ON_RUNQ(td2))) {
|
||||
assigned++;
|
||||
if (td2->td_kse == NULL) {
|
||||
panic ("BOUND thread with no KSE");
|
||||
|
@ -285,7 +285,7 @@ schedcpu(arg)
|
||||
awake = 1;
|
||||
ke->ke_flags &= ~KEF_DIDRUN;
|
||||
} else if ((ke->ke_state == KES_THREAD) &&
|
||||
(ke->ke_thread->td_state == TDS_RUNNING)) {
|
||||
(TD_IS_RUNNING(ke->ke_thread))) {
|
||||
awake = 1;
|
||||
/* Do not clear KEF_DIDRUN */
|
||||
} else if (ke->ke_flags & KEF_DIDRUN) {
|
||||
@ -361,8 +361,7 @@ schedcpu(arg)
|
||||
(kg->kg_user_pri / RQ_PPQ));
|
||||
|
||||
td->td_priority = kg->kg_user_pri;
|
||||
if (changedqueue &&
|
||||
td->td_state == TDS_RUNQ) {
|
||||
if (changedqueue && TD_ON_RUNQ(td)) {
|
||||
/* this could be optimised */
|
||||
remrunqueue(td);
|
||||
td->td_priority =
|
||||
@ -515,15 +514,17 @@ msleep(ident, mtx, priority, wmesg, timo)
|
||||
}
|
||||
|
||||
KASSERT(p != NULL, ("msleep1"));
|
||||
KASSERT(ident != NULL && td->td_state == TDS_RUNNING, ("msleep"));
|
||||
KASSERT(ident != NULL && TD_IS_RUNNING(td), ("msleep"));
|
||||
|
||||
CTR5(KTR_PROC, "msleep: thread %p (pid %d, %s) on %s (%p)",
|
||||
td, p->p_pid, p->p_comm, wmesg, ident);
|
||||
|
||||
td->td_wchan = ident;
|
||||
td->td_wmesg = wmesg;
|
||||
td->td_ksegrp->kg_slptime = 0;
|
||||
td->td_priority = priority & PRIMASK;
|
||||
CTR5(KTR_PROC, "msleep: thread %p (pid %d, %s) on %s (%p)",
|
||||
td, p->p_pid, p->p_comm, wmesg, ident);
|
||||
TAILQ_INSERT_TAIL(&slpque[LOOKUP(ident)], td, td_slpq);
|
||||
TD_SET_ON_SLEEPQ(td);
|
||||
if (timo)
|
||||
callout_reset(&td->td_slpcallout, timo, endtsleep, td);
|
||||
/*
|
||||
@ -546,20 +547,20 @@ msleep(ident, mtx, priority, wmesg, timo)
|
||||
mtx_lock_spin(&sched_lock);
|
||||
PROC_UNLOCK(p);
|
||||
if (sig != 0) {
|
||||
if (td->td_wchan != NULL)
|
||||
if (TD_ON_SLEEPQ(td))
|
||||
unsleep(td);
|
||||
} else if (td->td_wchan == NULL)
|
||||
} else if (!TD_ON_SLEEPQ(td))
|
||||
catch = 0;
|
||||
} else
|
||||
sig = 0;
|
||||
if (td->td_wchan != NULL) {
|
||||
if (TD_ON_SLEEPQ(td)) {
|
||||
p->p_stats->p_ru.ru_nvcsw++;
|
||||
td->td_state = TDS_SLP;
|
||||
TD_SET_SLEEPING(td);
|
||||
mi_switch();
|
||||
}
|
||||
CTR3(KTR_PROC, "msleep resume: thread %p (pid %d, %s)", td, p->p_pid,
|
||||
p->p_comm);
|
||||
KASSERT(td->td_state == TDS_RUNNING, ("running but not TDS_RUNNING"));
|
||||
KASSERT(TD_IS_RUNNING(td), ("running but not TDS_RUNNING"));
|
||||
td->td_flags &= ~TDF_SINTR;
|
||||
if (td->td_flags & TDF_TIMEOUT) {
|
||||
td->td_flags &= ~TDF_TIMEOUT;
|
||||
@ -577,10 +578,10 @@ msleep(ident, mtx, priority, wmesg, timo)
|
||||
* has a chance to run and the callout may end up waking up
|
||||
* the wrong msleep(). Yuck.
|
||||
*/
|
||||
td->td_flags |= TDF_TIMEOUT;
|
||||
td->td_state = TDS_SLP;
|
||||
TD_SET_SLEEPING(td);
|
||||
p->p_stats->p_ru.ru_nivcsw++;
|
||||
mi_switch();
|
||||
td->td_flags &= ~TDF_TIMOFAIL;
|
||||
}
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
|
||||
@ -621,35 +622,23 @@ endtsleep(arg)
|
||||
{
|
||||
register struct thread *td = arg;
|
||||
|
||||
CTR3(KTR_PROC, "endtsleep: thread %p (pid %d, %s)", td, td->td_proc->p_pid,
|
||||
td->td_proc->p_comm);
|
||||
CTR3(KTR_PROC, "endtsleep: thread %p (pid %d, %s)",
|
||||
td, td->td_proc->p_pid, td->td_proc->p_comm);
|
||||
mtx_lock_spin(&sched_lock);
|
||||
/*
|
||||
* This is the other half of the synchronization with msleep()
|
||||
* described above. If the TDS_TIMEOUT flag is set, we lost the
|
||||
* race and just need to put the process back on the runqueue.
|
||||
*/
|
||||
if ((td->td_flags & TDF_TIMEOUT) != 0) {
|
||||
td->td_flags &= ~TDF_TIMEOUT;
|
||||
if (td->td_proc->p_sflag & PS_INMEM) {
|
||||
setrunqueue(td);
|
||||
maybe_resched(td);
|
||||
} else {
|
||||
td->td_state = TDS_SWAPPED;
|
||||
if ((td->td_proc->p_sflag & PS_SWAPPINGIN) == 0) {
|
||||
td->td_proc->p_sflag |= PS_SWAPINREQ;
|
||||
wakeup(&proc0);
|
||||
}
|
||||
}
|
||||
} else if (td->td_wchan != NULL) {
|
||||
if (td->td_state == TDS_SLP) /* XXXKSE */
|
||||
setrunnable(td);
|
||||
else
|
||||
unsleep(td);
|
||||
if (TD_ON_SLEEPQ(td)) {
|
||||
TAILQ_REMOVE(&slpque[LOOKUP(td->td_wchan)], td, td_slpq);
|
||||
TD_CLR_ON_SLEEPQ(td);
|
||||
td->td_flags |= TDF_TIMEOUT;
|
||||
} else {
|
||||
td->td_flags |= TDF_TIMOFAIL;
|
||||
}
|
||||
TD_CLR_SLEEPING(td);
|
||||
setrunnable(td);
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
}
|
||||
|
||||
@ -664,25 +653,18 @@ void
|
||||
abortsleep(struct thread *td)
|
||||
{
|
||||
|
||||
mtx_lock_spin(&sched_lock);
|
||||
mtx_assert(&sched_lock, MA_OWNED);
|
||||
/*
|
||||
* If the TDF_TIMEOUT flag is set, just leave. A
|
||||
* timeout is scheduled anyhow.
|
||||
*/
|
||||
if ((td->td_flags & (TDF_TIMEOUT | TDF_SINTR)) == TDF_SINTR) {
|
||||
if (td->td_wchan != NULL) {
|
||||
if (td->td_state == TDS_SLP) { /* XXXKSE */
|
||||
setrunnable(td);
|
||||
} else {
|
||||
/*
|
||||
* Probably in a suspended state..
|
||||
* um.. dunno XXXKSE
|
||||
*/
|
||||
unsleep(td);
|
||||
}
|
||||
if (TD_ON_SLEEPQ(td)) {
|
||||
unsleep(td);
|
||||
TD_CLR_SLEEPING(td);
|
||||
setrunnable(td);
|
||||
}
|
||||
}
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -693,9 +675,9 @@ unsleep(struct thread *td)
|
||||
{
|
||||
|
||||
mtx_lock_spin(&sched_lock);
|
||||
if (td->td_wchan != NULL) {
|
||||
if (TD_ON_SLEEPQ(td)) {
|
||||
TAILQ_REMOVE(&slpque[LOOKUP(td->td_wchan)], td, td_slpq);
|
||||
td->td_wchan = NULL;
|
||||
TD_CLR_ON_SLEEPQ(td);
|
||||
}
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
}
|
||||
@ -710,7 +692,6 @@ wakeup(ident)
|
||||
register struct slpquehead *qp;
|
||||
register struct thread *td;
|
||||
struct thread *ntd;
|
||||
struct ksegrp *kg;
|
||||
struct proc *p;
|
||||
|
||||
mtx_lock_spin(&sched_lock);
|
||||
@ -718,30 +699,13 @@ wakeup(ident)
|
||||
restart:
|
||||
for (td = TAILQ_FIRST(qp); td != NULL; td = ntd) {
|
||||
ntd = TAILQ_NEXT(td, td_slpq);
|
||||
p = td->td_proc;
|
||||
if (td->td_wchan == ident) {
|
||||
TAILQ_REMOVE(qp, td, td_slpq);
|
||||
td->td_wchan = NULL;
|
||||
if (td->td_state == TDS_SLP) {
|
||||
/* OPTIMIZED EXPANSION OF setrunnable(p); */
|
||||
CTR3(KTR_PROC, "wakeup: thread %p (pid %d, %s)",
|
||||
td, p->p_pid, p->p_comm);
|
||||
kg = td->td_ksegrp;
|
||||
if (kg->kg_slptime > 1)
|
||||
updatepri(kg);
|
||||
kg->kg_slptime = 0;
|
||||
if (p->p_sflag & PS_INMEM) {
|
||||
setrunqueue(td);
|
||||
maybe_resched(td);
|
||||
} else {
|
||||
td->td_state = TDS_SWAPPED;
|
||||
if ((p->p_sflag & PS_SWAPPINGIN) == 0) {
|
||||
p->p_sflag |= PS_SWAPINREQ;
|
||||
wakeup(&proc0);
|
||||
}
|
||||
}
|
||||
/* END INLINE EXPANSION */
|
||||
}
|
||||
unsleep(td);
|
||||
TD_CLR_SLEEPING(td);
|
||||
setrunnable(td);
|
||||
p = td->td_proc;
|
||||
CTR3(KTR_PROC,"wakeup: thread %p (pid %d, %s)",
|
||||
td, p->p_pid, p->p_comm);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
@ -761,39 +725,19 @@ wakeup_one(ident)
|
||||
register struct thread *td;
|
||||
register struct proc *p;
|
||||
struct thread *ntd;
|
||||
struct ksegrp *kg;
|
||||
|
||||
mtx_lock_spin(&sched_lock);
|
||||
qp = &slpque[LOOKUP(ident)];
|
||||
restart:
|
||||
for (td = TAILQ_FIRST(qp); td != NULL; td = ntd) {
|
||||
ntd = TAILQ_NEXT(td, td_slpq);
|
||||
p = td->td_proc;
|
||||
if (td->td_wchan == ident) {
|
||||
TAILQ_REMOVE(qp, td, td_slpq);
|
||||
td->td_wchan = NULL;
|
||||
if (td->td_state == TDS_SLP) {
|
||||
/* OPTIMIZED EXPANSION OF setrunnable(p); */
|
||||
CTR3(KTR_PROC,"wakeup1: thread %p (pid %d, %s)",
|
||||
td, p->p_pid, p->p_comm);
|
||||
kg = td->td_ksegrp;
|
||||
if (kg->kg_slptime > 1)
|
||||
updatepri(kg);
|
||||
kg->kg_slptime = 0;
|
||||
if (p->p_sflag & PS_INMEM) {
|
||||
setrunqueue(td);
|
||||
maybe_resched(td);
|
||||
break;
|
||||
} else {
|
||||
td->td_state = TDS_SWAPPED;
|
||||
if ((p->p_sflag & PS_SWAPPINGIN) == 0) {
|
||||
p->p_sflag |= PS_SWAPINREQ;
|
||||
wakeup(&proc0);
|
||||
}
|
||||
}
|
||||
/* END INLINE EXPANSION */
|
||||
goto restart;
|
||||
}
|
||||
unsleep(td);
|
||||
TD_CLR_SLEEPING(td);
|
||||
setrunnable(td);
|
||||
p = td->td_proc;
|
||||
CTR3(KTR_PROC,"wakeup1: thread %p (pid %d, %s)",
|
||||
td, p->p_pid, p->p_comm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
@ -816,11 +760,11 @@ mi_switch(void)
|
||||
|
||||
mtx_assert(&sched_lock, MA_OWNED | MA_NOTRECURSED);
|
||||
KASSERT((ke->ke_state == KES_THREAD), ("mi_switch: kse state?"));
|
||||
KASSERT((td->td_state != TDS_RUNQ), ("mi_switch: called by old code"));
|
||||
KASSERT(!TD_ON_RUNQ(td), ("mi_switch: called by old code"));
|
||||
#ifdef INVARIANTS
|
||||
if (td->td_state != TDS_MTX &&
|
||||
td->td_state != TDS_RUNQ &&
|
||||
td->td_state != TDS_RUNNING)
|
||||
if (!TD_ON_MUTEX(td) &&
|
||||
!TD_ON_RUNQ(td) &&
|
||||
!TD_IS_RUNNING(td))
|
||||
mtx_assert(&Giant, MA_NOTOWNED);
|
||||
#endif
|
||||
KASSERT(td->td_critnest == 1,
|
||||
@ -891,7 +835,7 @@ mi_switch(void)
|
||||
* then put it back on the run queue as it has not been suspended
|
||||
* or stopped or any thing else similar.
|
||||
*/
|
||||
if (td->td_state == TDS_RUNNING) {
|
||||
if (TD_IS_RUNNING(td)) {
|
||||
KASSERT(((ke->ke_flags & KEF_IDLEKSE) == 0),
|
||||
("Idle thread in mi_switch with wrong state"));
|
||||
/* Put us back on the run queue (kse and all). */
|
||||
@ -950,39 +894,33 @@ setrunnable(struct thread *td)
|
||||
break;
|
||||
}
|
||||
switch (td->td_state) {
|
||||
case 0:
|
||||
case TDS_RUNNING:
|
||||
case TDS_IWAIT:
|
||||
case TDS_SWAPPED:
|
||||
case TDS_RUNQ:
|
||||
return;
|
||||
case TDS_INHIBITED:
|
||||
/*
|
||||
* If we are only inhibited because we are swapped out
|
||||
* then arange to swap in this process. Otherwise just return.
|
||||
*/
|
||||
if (td->td_inhibitors != TDI_SWAPPED)
|
||||
return;
|
||||
case TDS_CAN_RUN:
|
||||
break;
|
||||
default:
|
||||
printf("state is %d", td->td_state);
|
||||
printf("state is 0x%x", td->td_state);
|
||||
panic("setrunnable(2)");
|
||||
case TDS_SUSPENDED:
|
||||
thread_unsuspend(p);
|
||||
break;
|
||||
case TDS_SLP: /* e.g. when sending signals */
|
||||
if (td->td_flags & TDF_CVWAITQ)
|
||||
cv_waitq_remove(td);
|
||||
else
|
||||
unsleep(td);
|
||||
case TDS_UNQUEUED: /* being put back onto the queue */
|
||||
case TDS_NEW: /* not yet had time to suspend */
|
||||
case TDS_RUNQ: /* not yet had time to suspend */
|
||||
break;
|
||||
}
|
||||
kg = td->td_ksegrp;
|
||||
if (kg->kg_slptime > 1)
|
||||
updatepri(kg);
|
||||
kg->kg_slptime = 0;
|
||||
if ((p->p_sflag & PS_INMEM) == 0) {
|
||||
td->td_state = TDS_SWAPPED;
|
||||
if ((p->p_sflag & PS_SWAPPINGIN) == 0) {
|
||||
p->p_sflag |= PS_SWAPINREQ;
|
||||
wakeup(&proc0);
|
||||
}
|
||||
} else {
|
||||
if (td->td_state != TDS_RUNQ)
|
||||
setrunqueue(td); /* XXXKSE */
|
||||
kg = td->td_ksegrp;
|
||||
if (kg->kg_slptime > 1)
|
||||
updatepri(kg);
|
||||
kg->kg_slptime = 0;
|
||||
setrunqueue(td);
|
||||
maybe_resched(td);
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ thread_ctor(void *mem, int size, void *arg)
|
||||
("size mismatch: %d != %d\n", size, (int)sizeof(struct thread)));
|
||||
|
||||
td = (struct thread *)mem;
|
||||
td->td_state = TDS_NEW;
|
||||
td->td_state = TDS_INACTIVE;
|
||||
td->td_flags |= TDF_UNBOUND;
|
||||
cached_threads--; /* XXXSMP */
|
||||
active_threads++; /* XXXSMP */
|
||||
@ -117,8 +117,9 @@ thread_dtor(void *mem, int size, void *arg)
|
||||
#ifdef INVARIANTS
|
||||
/* Verify that this thread is in a safe state to free. */
|
||||
switch (td->td_state) {
|
||||
case TDS_SLP:
|
||||
case TDS_MTX:
|
||||
case TDS_INHIBITED:
|
||||
case TDS_RUNNING:
|
||||
case TDS_CAN_RUN:
|
||||
case TDS_RUNQ:
|
||||
/*
|
||||
* We must never unlink a thread that is in one of
|
||||
@ -126,10 +127,7 @@ thread_dtor(void *mem, int size, void *arg)
|
||||
*/
|
||||
panic("bad state for thread unlinking");
|
||||
/* NOTREACHED */
|
||||
case TDS_UNQUEUED:
|
||||
case TDS_NEW:
|
||||
case TDS_RUNNING:
|
||||
case TDS_SURPLUS:
|
||||
case TDS_INACTIVE:
|
||||
break;
|
||||
default:
|
||||
panic("bad thread state");
|
||||
@ -316,7 +314,7 @@ thread_exit(void)
|
||||
KASSERT(!mtx_owned(&Giant), ("dying thread owns giant"));
|
||||
|
||||
if (ke->ke_tdspare != NULL) {
|
||||
thread_free(ke->ke_tdspare);
|
||||
thread_stash(ke->ke_tdspare);
|
||||
ke->ke_tdspare = NULL;
|
||||
}
|
||||
cpu_thread_exit(td); /* XXXSMP */
|
||||
@ -345,14 +343,11 @@ thread_exit(void)
|
||||
*/
|
||||
if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
|
||||
if (p->p_numthreads == p->p_suspcount) {
|
||||
TAILQ_REMOVE(&p->p_suspended,
|
||||
p->p_singlethread, td_runq);
|
||||
setrunqueue(p->p_singlethread);
|
||||
p->p_suspcount--;
|
||||
thread_unsuspend_one(p->p_singlethread);
|
||||
}
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
td->td_state = TDS_SURPLUS;
|
||||
td->td_state = TDS_INACTIVE;
|
||||
td->td_proc = NULL;
|
||||
td->td_ksegrp = NULL;
|
||||
td->td_last_kse = NULL;
|
||||
@ -379,7 +374,7 @@ thread_link(struct thread *td, struct ksegrp *kg)
|
||||
struct proc *p;
|
||||
|
||||
p = kg->kg_proc;
|
||||
td->td_state = TDS_NEW;
|
||||
td->td_state = TDS_INACTIVE;
|
||||
td->td_proc = p;
|
||||
td->td_ksegrp = kg;
|
||||
td->td_last_kse = NULL;
|
||||
@ -427,6 +422,7 @@ thread_schedule_upcall(struct thread *td, struct kse *ke)
|
||||
cpu_set_upcall(td2, ke->ke_pcb);
|
||||
td2->td_ucred = crhold(td->td_ucred);
|
||||
td2->td_flags = TDF_UNBOUND|TDF_UPCALLING;
|
||||
TD_SET_CAN_RUN(td2);
|
||||
setrunqueue(td2);
|
||||
return (td2);
|
||||
}
|
||||
@ -607,38 +603,32 @@ thread_single(int force_exit)
|
||||
p->p_flag |= P_STOPPED_SINGLE;
|
||||
p->p_singlethread = td;
|
||||
while ((p->p_numthreads - p->p_suspcount) != 1) {
|
||||
mtx_lock_spin(&sched_lock);
|
||||
FOREACH_THREAD_IN_PROC(p, td2) {
|
||||
if (td2 == td)
|
||||
continue;
|
||||
switch(td2->td_state) {
|
||||
case TDS_SUSPENDED:
|
||||
if (force_exit == SINGLE_EXIT) {
|
||||
mtx_lock_spin(&sched_lock);
|
||||
TAILQ_REMOVE(&p->p_suspended,
|
||||
td, td_runq);
|
||||
p->p_suspcount--;
|
||||
setrunqueue(td); /* Should suicide. */
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
if (TD_IS_INHIBITED(td2)) {
|
||||
if (TD_IS_SUSPENDED(td2)) {
|
||||
if (force_exit == SINGLE_EXIT) {
|
||||
thread_unsuspend_one(td2);
|
||||
}
|
||||
}
|
||||
case TDS_SLP:
|
||||
if (td2->td_flags & TDF_CVWAITQ)
|
||||
cv_abort(td2);
|
||||
else
|
||||
abortsleep(td2);
|
||||
break;
|
||||
/* case TDS RUNNABLE: XXXKSE maybe raise priority? */
|
||||
default: /* needed to avoid an error */
|
||||
break;
|
||||
if ( TD_IS_SLEEPING(td2)) {
|
||||
if (td2->td_flags & TDF_CVWAITQ)
|
||||
cv_waitq_remove(td2);
|
||||
else
|
||||
unsleep(td2);
|
||||
break;
|
||||
}
|
||||
if (TD_CAN_RUN(td2))
|
||||
setrunqueue(td2);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Wake us up when everyone else has suspended.
|
||||
* In the mean time we suspend as well.
|
||||
*/
|
||||
mtx_lock_spin(&sched_lock);
|
||||
TAILQ_INSERT_TAIL(&p->p_suspended, td, td_runq);
|
||||
td->td_state = TDS_SUSPENDED;
|
||||
p->p_suspcount++;
|
||||
thread_suspend_one(td);
|
||||
mtx_unlock(&Giant);
|
||||
PROC_UNLOCK(p);
|
||||
mi_switch();
|
||||
@ -745,16 +735,11 @@ thread_suspend_check(int return_instead)
|
||||
mtx_lock_spin(&sched_lock);
|
||||
}
|
||||
mtx_assert(&Giant, MA_NOTOWNED);
|
||||
p->p_suspcount++;
|
||||
td->td_state = TDS_SUSPENDED;
|
||||
TAILQ_INSERT_TAIL(&p->p_suspended, td, td_runq);
|
||||
thread_suspend_one(td);
|
||||
PROC_UNLOCK(p);
|
||||
if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
|
||||
if (p->p_numthreads == p->p_suspcount) {
|
||||
TAILQ_REMOVE(&p->p_suspended,
|
||||
p->p_singlethread, td_runq);
|
||||
p->p_suspcount--;
|
||||
setrunqueue(p->p_singlethread);
|
||||
thread_unsuspend_one(p->p_singlethread);
|
||||
}
|
||||
}
|
||||
p->p_stats->p_ru.ru_nivcsw++;
|
||||
@ -772,8 +757,15 @@ thread_suspend_one(struct thread *td)
|
||||
|
||||
mtx_assert(&sched_lock, MA_OWNED);
|
||||
p->p_suspcount++;
|
||||
td->td_state = TDS_SUSPENDED;
|
||||
TD_SET_SUSPENDED(td);
|
||||
TAILQ_INSERT_TAIL(&p->p_suspended, td, td_runq);
|
||||
/*
|
||||
* Hack: If we are suspending but are on the sleep queue
|
||||
* then we are in msleep or the cv equivalent. We
|
||||
* want to look like we have two Inhibitors.
|
||||
*/
|
||||
if (TD_ON_SLEEPQ(td))
|
||||
TD_SET_SLEEPING(td);
|
||||
}
|
||||
|
||||
void
|
||||
@ -783,16 +775,9 @@ thread_unsuspend_one(struct thread *td)
|
||||
|
||||
mtx_assert(&sched_lock, MA_OWNED);
|
||||
TAILQ_REMOVE(&p->p_suspended, td, td_runq);
|
||||
TD_CLR_SUSPENDED(td);
|
||||
p->p_suspcount--;
|
||||
if (td->td_wchan != NULL) {
|
||||
td->td_state = TDS_SLP;
|
||||
} else {
|
||||
if (td->td_ksegrp->kg_slptime > 1) {
|
||||
updatepri(td->td_ksegrp);
|
||||
td->td_ksegrp->kg_slptime = 0;
|
||||
}
|
||||
setrunqueue(td);
|
||||
}
|
||||
setrunnable(td);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -840,9 +825,7 @@ thread_single_end(void)
|
||||
if ((p->p_numthreads != 1) && (!P_SHOULDSTOP(p))) {
|
||||
mtx_lock_spin(&sched_lock);
|
||||
while (( td = TAILQ_FIRST(&p->p_suspended))) {
|
||||
TAILQ_REMOVE(&p->p_suspended, td, td_runq);
|
||||
p->p_suspcount--;
|
||||
setrunqueue(td);
|
||||
thread_unsuspend_one(td);
|
||||
}
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
}
|
||||
|
@ -182,9 +182,9 @@ int ksched_setscheduler(register_t *ret, struct ksched *ksched,
|
||||
mtx_lock_spin(&sched_lock);
|
||||
rtp_to_pri(&rtp, kg);
|
||||
FOREACH_THREAD_IN_GROUP(kg, td) { /* XXXKSE */
|
||||
if (td->td_state == TDS_RUNNING) {
|
||||
if (TD_IS_RUNNING(td)) {
|
||||
td->td_kse->ke_flags |= KEF_NEEDRESCHED;
|
||||
} else if (td->td_state == TDS_RUNQ) {
|
||||
} else if (TD_ON_RUNQ(td)) {
|
||||
if (td->td_priority > kg->kg_user_pri) {
|
||||
remrunqueue(td);
|
||||
td->td_priority =
|
||||
@ -215,9 +215,9 @@ int ksched_setscheduler(register_t *ret, struct ksched *ksched,
|
||||
* scheduling info alone.
|
||||
*/
|
||||
FOREACH_THREAD_IN_GROUP(kg, td) {
|
||||
if (td->td_state == TDS_RUNNING) {
|
||||
if (TD_IS_RUNNING(td)) {
|
||||
td->td_kse->ke_flags |= KEF_NEEDRESCHED;
|
||||
} else if (td->td_state == TDS_RUNQ) {
|
||||
} else if (TD_ON_RUNQ(td)) {
|
||||
if (td->td_priority > kg->kg_user_pri) {
|
||||
remrunqueue(td);
|
||||
td->td_priority =
|
||||
|
@ -124,7 +124,7 @@ forward_signal(struct thread *td)
|
||||
* executing so that it executes ast().
|
||||
*/
|
||||
mtx_assert(&sched_lock, MA_OWNED);
|
||||
KASSERT(td->td_state == TDS_RUNNING,
|
||||
KASSERT(TD_IS_RUNNING(td),
|
||||
("forward_signal: thread is not TDS_RUNNING"));
|
||||
|
||||
CTR1(KTR_SMP, "forward_signal(%p)", td->td_proc);
|
||||
|
@ -119,11 +119,9 @@ propagate_priority(struct thread *td)
|
||||
return;
|
||||
}
|
||||
|
||||
KASSERT(td->td_state != TDS_SURPLUS, ("Mutex owner SURPLUS"));
|
||||
MPASS(td->td_proc != NULL);
|
||||
MPASS(td->td_proc->p_magic == P_MAGIC);
|
||||
KASSERT(td->td_state != TDS_SLP,
|
||||
("sleeping thread owns a mutex"));
|
||||
KASSERT(!TD_IS_SLEEPING(td), ("sleeping thread owns a mutex"));
|
||||
if (td->td_priority <= pri) /* lower is higher priority */
|
||||
return;
|
||||
|
||||
@ -131,7 +129,7 @@ propagate_priority(struct thread *td)
|
||||
/*
|
||||
* If lock holder is actually running, just bump priority.
|
||||
*/
|
||||
if (td->td_state == TDS_RUNNING) {
|
||||
if (TD_IS_RUNNING(td)) {
|
||||
td->td_priority = pri;
|
||||
return;
|
||||
}
|
||||
@ -150,7 +148,7 @@ propagate_priority(struct thread *td)
|
||||
* but try anyhow.
|
||||
* We should have a special call to do this more efficiently.
|
||||
*/
|
||||
if (td->td_state == TDS_RUNQ) {
|
||||
if (TD_ON_RUNQ(td)) {
|
||||
MPASS(td->td_blocked == NULL);
|
||||
remrunqueue(td);
|
||||
td->td_priority = pri;
|
||||
@ -165,7 +163,7 @@ propagate_priority(struct thread *td)
|
||||
/*
|
||||
* If we aren't blocked on a mutex, we should be.
|
||||
*/
|
||||
KASSERT(td->td_state == TDS_MTX, (
|
||||
KASSERT(TD_ON_MUTEX(td), (
|
||||
"process %d(%s):%d holds %s but isn't blocked on a mutex\n",
|
||||
td->td_proc->p_pid, td->td_proc->p_comm, td->td_state,
|
||||
m->mtx_object.lo_name));
|
||||
@ -619,7 +617,7 @@ _mtx_lock_sleep(struct mtx *m, int opts, const char *file, int line)
|
||||
*/
|
||||
td->td_blocked = m;
|
||||
td->td_mtxname = m->mtx_object.lo_name;
|
||||
td->td_state = TDS_MTX;
|
||||
TD_SET_MUTEX(td);
|
||||
propagate_priority(td);
|
||||
|
||||
if (LOCK_LOG_TEST(&m->mtx_object, opts))
|
||||
@ -763,6 +761,7 @@ _mtx_unlock_sleep(struct mtx *m, int opts, const char *file, int line)
|
||||
m, td1);
|
||||
|
||||
td1->td_blocked = NULL;
|
||||
TD_CLR_MUTEX(td1);
|
||||
setrunqueue(td1);
|
||||
|
||||
if (td->td_critnest == 1 && td1->td_priority < pri) {
|
||||
|
@ -1206,10 +1206,9 @@ selwakeup(sip)
|
||||
sip->si_thread = NULL;
|
||||
mtx_lock_spin(&sched_lock);
|
||||
if (td->td_wchan == &selwait) {
|
||||
if (td->td_state == TDS_SLP)
|
||||
setrunnable(td);
|
||||
else
|
||||
cv_waitq_remove(td);
|
||||
cv_waitq_remove(td);
|
||||
TD_CLR_SLEEPING(td);
|
||||
setrunnable(td);
|
||||
} else
|
||||
td->td_flags &= ~TDF_SELECT;
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
|
@ -600,6 +600,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
p->p_xstat = data;
|
||||
mtx_lock_spin(&sched_lock);
|
||||
p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG);
|
||||
thread_unsuspend(p);
|
||||
setrunnable(td2); /* XXXKSE */
|
||||
/* Need foreach kse in proc, ... make_kse_queued(). */
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
|
@ -2396,9 +2396,10 @@ ttyinfo(struct tty *tp)
|
||||
stmp = "KSE" ; /* XXXKSE */
|
||||
} else {
|
||||
if (td) {
|
||||
if (td->td_state == TDS_RUNQ) {
|
||||
if (TD_ON_RUNQ(td) ||
|
||||
(TD_IS_RUNNING(td))) {
|
||||
stmp = "running";
|
||||
} else if (td->td_state == TDS_MTX) {
|
||||
} else if (TD_ON_MUTEX(td)) {
|
||||
stmp = td->td_mtxname;
|
||||
} else if (td->td_wmesg) {
|
||||
stmp = td->td_wmesg;
|
||||
@ -2413,7 +2414,7 @@ ttyinfo(struct tty *tp)
|
||||
calcru(pick, &utime, &stime, NULL);
|
||||
/* XXXKSE The TDS_IWAIT line is Dubious */
|
||||
if (pick->p_state == PRS_NEW ||
|
||||
(td && (td->td_state == TDS_IWAIT)) ||
|
||||
(td && (TD_AWAITING_INTR(td))) ||
|
||||
pick->p_state == PRS_ZOMBIE) {
|
||||
ltmp = 0;
|
||||
} else {
|
||||
@ -2424,7 +2425,7 @@ ttyinfo(struct tty *tp)
|
||||
|
||||
ttyprintf(tp, " cmd: %s %d [%s%s] ", pick->p_comm,
|
||||
pick->p_pid,
|
||||
td->td_state == TDS_MTX ? "*" : "",
|
||||
TD_ON_MUTEX(td) ? "*" : "",
|
||||
stmp);
|
||||
|
||||
/* Print user time. */
|
||||
@ -2461,8 +2462,8 @@ do { \
|
||||
struct thread *td; \
|
||||
val = 0; \
|
||||
FOREACH_THREAD_IN_PROC(p, td) { \
|
||||
if (td->td_state == TDS_RUNQ || \
|
||||
td->td_state == TDS_RUNNING) { \
|
||||
if (TD_ON_RUNQ(td) || \
|
||||
TD_IS_RUNNING(td)) { \
|
||||
val = 1; \
|
||||
break; \
|
||||
} \
|
||||
|
@ -1654,10 +1654,14 @@ sched_sync(void)
|
||||
int
|
||||
speedup_syncer()
|
||||
{
|
||||
struct thread *td;
|
||||
|
||||
td = FIRST_THREAD_IN_PROC(updateproc);
|
||||
mtx_lock_spin(&sched_lock);
|
||||
if (FIRST_THREAD_IN_PROC(updateproc)->td_wchan == &lbolt) /* XXXKSE */
|
||||
setrunnable(FIRST_THREAD_IN_PROC(updateproc));
|
||||
if (td->td_wchan == &lbolt) /* XXXKSE */
|
||||
unsleep(td);
|
||||
TD_CLR_SLEEPING(td);
|
||||
setrunnable(td);
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
if (rushjob < syncdelay / 2) {
|
||||
rushjob += 1;
|
||||
|
@ -182,9 +182,9 @@ int ksched_setscheduler(register_t *ret, struct ksched *ksched,
|
||||
mtx_lock_spin(&sched_lock);
|
||||
rtp_to_pri(&rtp, kg);
|
||||
FOREACH_THREAD_IN_GROUP(kg, td) { /* XXXKSE */
|
||||
if (td->td_state == TDS_RUNNING) {
|
||||
if (TD_IS_RUNNING(td)) {
|
||||
td->td_kse->ke_flags |= KEF_NEEDRESCHED;
|
||||
} else if (td->td_state == TDS_RUNQ) {
|
||||
} else if (TD_ON_RUNQ(td)) {
|
||||
if (td->td_priority > kg->kg_user_pri) {
|
||||
remrunqueue(td);
|
||||
td->td_priority =
|
||||
@ -215,9 +215,9 @@ int ksched_setscheduler(register_t *ret, struct ksched *ksched,
|
||||
* scheduling info alone.
|
||||
*/
|
||||
FOREACH_THREAD_IN_GROUP(kg, td) {
|
||||
if (td->td_state == TDS_RUNNING) {
|
||||
if (TD_IS_RUNNING(td)) {
|
||||
td->td_kse->ke_flags |= KEF_NEEDRESCHED;
|
||||
} else if (td->td_state == TDS_RUNQ) {
|
||||
} else if (TD_ON_RUNQ(td)) {
|
||||
if (td->td_priority > kg->kg_user_pri) {
|
||||
remrunqueue(td);
|
||||
td->td_priority =
|
||||
|
106
sys/sys/proc.h
106
sys/sys/proc.h
@ -266,6 +266,7 @@ struct thread {
|
||||
/* Cleared during fork1() or thread_sched_upcall() */
|
||||
#define td_startzero td_flags
|
||||
int td_flags; /* (j) TDF_* flags. */
|
||||
int td_inhibitors; /* (j) Why can not run */
|
||||
struct kse *td_last_kse; /* Where it wants to be if possible. */
|
||||
struct kse *td_kse; /* Current KSE if running. */
|
||||
int td_dupfd; /* (k) Ret value from fdopen. XXX */
|
||||
@ -301,17 +302,11 @@ struct thread {
|
||||
*/
|
||||
struct pcb *td_pcb; /* (k) Kernel VA of pcb and kstack. */
|
||||
enum {
|
||||
TDS_NEW = 0x20,
|
||||
TDS_UNQUEUED,
|
||||
TDS_SLP,
|
||||
TDS_MTX,
|
||||
TDS_INACTIVE = 0x20,
|
||||
TDS_INHIBITED,
|
||||
TDS_CAN_RUN,
|
||||
TDS_RUNQ,
|
||||
TDS_RUNNING,
|
||||
TDS_SUSPENDED, /* would have liked to have run */
|
||||
TDS_IWAIT,
|
||||
TDS_SURPLUS,
|
||||
TDS_SWAPPED,
|
||||
TDS_SUSP_SLP /* on sleep queue AND suspend queue */
|
||||
} td_state;
|
||||
register_t td_retval[2]; /* (k) Syscall aux returns. */
|
||||
struct callout td_slpcallout; /* (h) Callout for sleep. */
|
||||
@ -319,17 +314,68 @@ struct thread {
|
||||
struct vm_object *td_kstack_obj;/* (a) Kstack object. */
|
||||
vm_offset_t td_kstack; /* Kernel VA of kstack. */
|
||||
};
|
||||
/* flags kept in td_flags */
|
||||
#define TDF_UNBOUND 0x000001 /* may give away the kse, uses the kg runq */
|
||||
#define TDF_INPANIC 0x000002 /* Caused a panic, let it drive crashdump */
|
||||
#define TDF_SINTR 0x000008 /* Sleep is interruptible. */
|
||||
#define TDF_TIMEOUT 0x000010 /* Timing out during sleep. */
|
||||
#define TDF_SELECT 0x000040 /* Selecting; wakeup/waiting danger. */
|
||||
#define TDF_CVWAITQ 0x000080 /* Thread is on a cv_waitq (not slpq). */
|
||||
#define TDF_UPCALLING 0x000100 /* This thread is doing an upcall. */
|
||||
/* flags kept in td_flags */
|
||||
#define TDF_UNBOUND 0x000001 /* may give away the kse, uses the kg runq */
|
||||
#define TDF_INPANIC 0x000002 /* Caused a panic, let it drive crashdump */
|
||||
#define TDF_SINTR 0x000008 /* Sleep is interruptible. */
|
||||
#define TDF_TIMEOUT 0x000010 /* Timing out during sleep. */
|
||||
#define TDF_SELECT 0x000040 /* Selecting; wakeup/waiting danger. */
|
||||
#define TDF_CVWAITQ 0x000080 /* Thread is on a cv_waitq (not slpq). */
|
||||
#define TDF_UPCALLING 0x000100 /* This thread is doing an upcall. */
|
||||
#define TDF_ONSLEEPQ 0x000200 /* On the sleep queue */
|
||||
#define TDF_INMSLEEP 0x000400 /* Don't recurse in msleep() */
|
||||
#define TDF_TIMOFAIL 0x001000 /* Timeout from sleep after we were awake. */
|
||||
#define TDF_DEADLKTREAT 0x800000 /* Lock aquisition - deadlock treatment. */
|
||||
#define TDF_TIMOFAIL 0x001000 /* Timeout from sleep after we were awake. */
|
||||
#define TDF_DEADLKTREAT 0x800000 /* Lock aquisition - deadlock treatment. */
|
||||
|
||||
#define TDI_SUSPENDED 0x01 /* on suspension queue */
|
||||
#define TDI_SLEEPING 0x02 /* Actually asleep! */ /* actually tricky */
|
||||
#define TDI_SWAPPED 0x04 /* stack not in mem.. bad juju if run */
|
||||
#define TDI_MUTEX 0x08 /* Stopped on a mutex */
|
||||
#define TDI_IWAIT 0x10 /* Awaiting interrupt */
|
||||
|
||||
#define TD_IS_SLEEPING(td) ((td)->td_inhibitors & TDI_SLEEPING)
|
||||
#define TD_ON_SLEEPQ(td) ((td)->td_wchan != NULL)
|
||||
#define TD_IS_SUSPENDED(td) ((td)->td_inhibitors & TDI_SUSPENDED)
|
||||
#define TD_IS_SWAPPED(td) ((td)->td_inhibitors & TDI_SWAPPED)
|
||||
#define TD_ON_MUTEX(td) ((td)->td_inhibitors & TDI_MUTEX)
|
||||
#define TD_AWAITING_INTR(td) ((td)->td_inhibitors & TDI_IWAIT)
|
||||
#define TD_IS_RUNNING(td) ((td)->td_state == TDS_RUNNING)
|
||||
#define TD_ON_RUNQ(td) ((td)->td_state == TDS_RUNQ)
|
||||
#define TD_CAN_RUN(td) ((td)->td_state == TDS_CAN_RUN)
|
||||
#define TD_IS_INHIBITED(td) ((td)->td_state == TDS_INHIBITED)
|
||||
|
||||
#define TD_SET_INHIB(td, inhib) do { \
|
||||
(td)->td_state = TDS_INHIBITED; \
|
||||
(td)->td_inhibitors |= inhib; \
|
||||
} while (0)
|
||||
|
||||
#define TD_CLR_INHIB(td, inhib) do { \
|
||||
if (((td)->td_inhibitors & inhib) && \
|
||||
(((td)->td_inhibitors &= ~inhib) == 0)) \
|
||||
(td)->td_state = TDS_CAN_RUN; \
|
||||
} while (0)
|
||||
|
||||
#define TD_SET_SLEEPING(td) TD_SET_INHIB((td), TDI_SLEEPING)
|
||||
#define TD_SET_SWAPPED(td) TD_SET_INHIB((td), TDI_SWAPPED)
|
||||
#define TD_SET_MUTEX(td) TD_SET_INHIB((td), TDI_MUTEX)
|
||||
#define TD_SET_SUSPENDED(td) TD_SET_INHIB((td), TDI_SUSPENDED)
|
||||
#define TD_SET_IWAIT(td) TD_SET_INHIB((td), TDI_IWAIT)
|
||||
|
||||
#define TD_CLR_SLEEPING(td) TD_CLR_INHIB((td), TDI_SLEEPING)
|
||||
#define TD_CLR_SWAPPED(td) TD_CLR_INHIB((td), TDI_SWAPPED)
|
||||
#define TD_CLR_MUTEX(td) TD_CLR_INHIB((td), TDI_MUTEX)
|
||||
#define TD_CLR_SUSPENDED(td) TD_CLR_INHIB((td), TDI_SUSPENDED)
|
||||
#define TD_CLR_IWAIT(td) TD_CLR_INHIB((td), TDI_IWAIT)
|
||||
|
||||
#define TD_SET_RUNNING(td) do {(td)->td_state = TDS_RUNNING; } while (0)
|
||||
#define TD_SET_RUNQ(td) do {(td)->td_state = TDS_RUNQ; } while (0)
|
||||
#define TD_SET_CAN_RUN(td) do {(td)->td_state = TDS_CAN_RUN; } while (0)
|
||||
#define TD_SET_ON_SLEEPQ(td) do {(td)->td_flags |= TDF_ONSLEEPQ; } while (0)
|
||||
#define TD_CLR_ON_SLEEPQ(td) do { \
|
||||
(td)->td_flags &= ~TDF_ONSLEEPQ; \
|
||||
(td)->td_wchan = NULL; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Traps for young players:
|
||||
@ -372,15 +418,15 @@ struct kse {
|
||||
enum {
|
||||
KES_IDLE = 0x10,
|
||||
KES_ONRUNQ,
|
||||
KES_UNQUEUED, /* in transit */
|
||||
KES_THREAD /* slaved to thread state */
|
||||
} ke_state; /* (j) S* process status. */
|
||||
KES_UNQUEUED, /* in transit */
|
||||
KES_THREAD /* slaved to thread state */
|
||||
} ke_state; /* (j) S* process status. */
|
||||
void *ke_mailbox; /* the userland mailbox address */
|
||||
struct thread *ke_tdspare; /* spare thread for upcalls */
|
||||
#define ke_endzero ke_dummy
|
||||
|
||||
#define ke_startcopy ke_endzero
|
||||
u_char ke_dummy; /* */
|
||||
u_char ke_dummy;
|
||||
#define ke_endcopy ke_mdstorage
|
||||
|
||||
void *ke_upcall;
|
||||
@ -460,7 +506,7 @@ struct proc {
|
||||
struct plimit *p_limit; /* (m) Process limits. */
|
||||
struct vm_object *p_upages_obj; /* (a) Upages object. */
|
||||
struct procsig *p_procsig; /* (c) Signal actions, state (CPU). */
|
||||
|
||||
|
||||
struct ksegrp p_ksegrp;
|
||||
struct kse p_kse;
|
||||
|
||||
@ -471,11 +517,11 @@ struct proc {
|
||||
int p_flag; /* (c) P_* flags. */
|
||||
int p_sflag; /* (j) PS_* flags. */
|
||||
enum {
|
||||
PRS_NEW = 0, /* In creation */
|
||||
PRS_NORMAL, /* KSEs can be run */
|
||||
PRS_WAIT, /* Waiting on interrupt ? */
|
||||
PRS_NEW = 0, /* In creation */
|
||||
PRS_NORMAL, /* KSEs can be run */
|
||||
PRS_WAIT, /* Waiting on interrupt ? */
|
||||
PRS_ZOMBIE
|
||||
} p_state; /* (j) S* process status. */
|
||||
} p_state; /* (j) S* process status. */
|
||||
pid_t p_pid; /* (b) Process identifier. */
|
||||
LIST_ENTRY(proc) p_hash; /* (d) Hash chain. */
|
||||
LIST_ENTRY(proc) p_pglist; /* (g + e) List of processes in pgrp. */
|
||||
@ -735,9 +781,7 @@ sigonstack(size_t sp)
|
||||
} while (0)
|
||||
|
||||
/* Check whether a thread is safe to be swapped out. */
|
||||
#define thread_safetoswapout(td) \
|
||||
((td)->td_state == TDS_RUNQ || \
|
||||
(td)->td_state == TDS_SLP)
|
||||
#define thread_safetoswapout(td) (TD_IS_SLEEPING(td) || TD_IS_SUSPENDED(td))
|
||||
|
||||
/* Lock and unlock process arguments. */
|
||||
#define PARGS_LOCK(p) mtx_lock(&pargs_ref_lock)
|
||||
|
@ -499,16 +499,18 @@ faultin(p)
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
vm_proc_swapin(p);
|
||||
FOREACH_THREAD_IN_PROC (p, td)
|
||||
FOREACH_THREAD_IN_PROC (p, td) {
|
||||
pmap_swapin_thread(td);
|
||||
TD_CLR_SWAPPED(td);
|
||||
}
|
||||
|
||||
PROC_LOCK(p);
|
||||
mtx_lock_spin(&sched_lock);
|
||||
p->p_sflag &= ~PS_SWAPPINGIN;
|
||||
p->p_sflag |= PS_INMEM;
|
||||
FOREACH_THREAD_IN_PROC (p, td)
|
||||
if (td->td_state == TDS_SWAPPED)
|
||||
setrunqueue(td);
|
||||
if (TD_CAN_RUN(td))
|
||||
setrunnable(td);
|
||||
|
||||
wakeup(&p->p_sflag);
|
||||
|
||||
@ -558,10 +560,11 @@ scheduler(dummy)
|
||||
mtx_lock_spin(&sched_lock);
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
/*
|
||||
* A runnable thread of a process swapped out is in
|
||||
* TDS_SWAPPED.
|
||||
* An otherwise runnable thread of a process
|
||||
* swapped out has only the TDI_SWAPPED bit set.
|
||||
*
|
||||
*/
|
||||
if (td->td_state == TDS_SWAPPED) {
|
||||
if (td->td_inhibitors == TDI_SWAPPED) {
|
||||
kg = td->td_ksegrp;
|
||||
pri = p->p_swtime + kg->kg_slptime;
|
||||
if ((p->p_sflag & PS_SWAPINREQ) == 0) {
|
||||
@ -849,18 +852,20 @@ swapout(p)
|
||||
p->p_vmspace->vm_swrss = vmspace_resident_count(p->p_vmspace);
|
||||
|
||||
PROC_UNLOCK(p);
|
||||
FOREACH_THREAD_IN_PROC (p, td)
|
||||
if (td->td_state == TDS_RUNQ) { /* XXXKSE */
|
||||
FOREACH_THREAD_IN_PROC (p, td) /* shouldn't be possible, but..... */
|
||||
if (TD_ON_RUNQ(td)) { /* XXXKSE */
|
||||
panic("swapping out runnable process");
|
||||
remrunqueue(td); /* XXXKSE */
|
||||
td->td_state = TDS_SWAPPED;
|
||||
}
|
||||
p->p_sflag &= ~PS_INMEM;
|
||||
p->p_sflag |= PS_SWAPPING;
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
|
||||
vm_proc_swapout(p);
|
||||
FOREACH_THREAD_IN_PROC(p, td)
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
pmap_swapout_thread(td);
|
||||
TD_SET_SWAPPED(td);
|
||||
}
|
||||
mtx_lock_spin(&sched_lock);
|
||||
p->p_sflag &= ~PS_SWAPPING;
|
||||
p->p_swtime = 0;
|
||||
|
@ -88,7 +88,6 @@ vmtotal(SYSCTL_HANDLER_ARGS)
|
||||
vm_object_t object;
|
||||
vm_map_t map;
|
||||
int paging;
|
||||
struct ksegrp *kg;
|
||||
struct thread *td;
|
||||
|
||||
totalp = &total;
|
||||
@ -111,42 +110,34 @@ vmtotal(SYSCTL_HANDLER_ARGS)
|
||||
mtx_lock_spin(&sched_lock);
|
||||
switch (p->p_state) {
|
||||
case PRS_NEW:
|
||||
if (p->p_sflag & PS_INMEM)
|
||||
totalp->t_rq++;
|
||||
else
|
||||
totalp->t_sw++;
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
/* Need new statistics XXX */
|
||||
switch (td->td_state) {
|
||||
case TDS_MTX:
|
||||
case TDS_SLP:
|
||||
kg = td->td_ksegrp; /* XXXKSE */
|
||||
if (p->p_sflag & PS_INMEM) {
|
||||
case TDS_INHIBITED:
|
||||
if (TD_ON_MUTEX(td) ||
|
||||
(td->td_inhibitors ==
|
||||
TDI_SWAPPED)) {
|
||||
totalp->t_sw++;
|
||||
} else if (TD_IS_SLEEPING(td) ||
|
||||
TD_AWAITING_INTR(td) ||
|
||||
TD_IS_SUSPENDED(td)) {
|
||||
if (td->td_priority <= PZERO)
|
||||
totalp->t_dw++;
|
||||
else if (kg->kg_slptime
|
||||
< maxslp)
|
||||
else
|
||||
totalp->t_sl++;
|
||||
} else if (kg->kg_slptime < maxslp)
|
||||
totalp->t_sw++;
|
||||
if (kg->kg_slptime >= maxslp) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case TDS_CAN_RUN:
|
||||
totalp->t_sw++;
|
||||
break;
|
||||
case TDS_RUNQ:
|
||||
case TDS_RUNNING:
|
||||
if (p->p_sflag & PS_INMEM)
|
||||
totalp->t_rq++;
|
||||
else
|
||||
totalp->t_sw++;
|
||||
continue;
|
||||
|
||||
case TDS_IWAIT:
|
||||
totalp->t_sl++;
|
||||
totalp->t_rq++;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
|
@ -1155,9 +1155,9 @@ vm_pageout_scan(int pass)
|
||||
mtx_lock_spin(&sched_lock);
|
||||
breakout = 0;
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
if (td->td_state != TDS_RUNQ &&
|
||||
td->td_state != TDS_RUNNING &&
|
||||
td->td_state != TDS_SLP) {
|
||||
if (!TD_ON_RUNQ(td) &&
|
||||
!TD_IS_RUNNING(td) &&
|
||||
!TD_IS_SLEEPING(td)) {
|
||||
breakout = 1;
|
||||
break;
|
||||
}
|
||||
@ -1498,9 +1498,9 @@ vm_daemon()
|
||||
mtx_lock_spin(&sched_lock);
|
||||
breakout = 0;
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
if (td->td_state != TDS_RUNQ &&
|
||||
td->td_state != TDS_RUNNING &&
|
||||
td->td_state != TDS_SLP) {
|
||||
if (!TD_ON_RUNQ(td) &&
|
||||
!TD_IS_RUNNING(td) &&
|
||||
!TD_IS_SLEEPING(td)) {
|
||||
breakout = 1;
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user