diff options
Diffstat (limited to 'sys/kern/kern_switch.c')
-rw-r--r-- | sys/kern/kern_switch.c | 235 |
1 files changed, 130 insertions, 105 deletions
diff --git a/sys/kern/kern_switch.c b/sys/kern/kern_switch.c index b4b8879..37500a1 100644 --- a/sys/kern/kern_switch.c +++ b/sys/kern/kern_switch.c @@ -107,7 +107,11 @@ CTASSERT((RQB_BPW * RQB_LEN) == RQ_NQS); static struct runq runq; SYSINIT(runq, SI_SUB_RUN_QUEUE, SI_ORDER_FIRST, runq_init, &runq) +void panc(char *string1, char *string2); + +#if 0 static void runq_readjust(struct runq *rq, struct kse *ke); +#endif /************************************************************************ * Functions that manipulate runnability from a thread perspective. * ************************************************************************/ @@ -169,9 +173,10 @@ retry: } /* - * Given a KSE (now surplus), either assign a new runable thread to it + * Given a KSE (now surplus or at least loanable), either assign a new + * runable thread to it * (and put it in the run queue) or put it in the ksegrp's idle KSE list. - * Assumes the kse is not linked to any threads any more. (has been cleaned). + * Or aybe give it back to its owner if it's been loaned. */ void kse_reassign(struct kse *ke) @@ -179,23 +184,15 @@ kse_reassign(struct kse *ke) struct ksegrp *kg; struct thread *td; struct thread *owner; + struct thread *original; mtx_assert(&sched_lock, MA_OWNED); kg = ke->ke_ksegrp; owner = ke->ke_bound; + original = ke->ke_thread; KASSERT(!(owner && ((owner->td_kse != ke) || (owner->td_flags & TDF_UNBOUND))), ("kse_reassign: bad thread bound state")); - if (owner && (owner->td_inhibitors == TDI_LOAN)) { - TD_CLR_LOAN(owner); - ke->ke_bound = NULL; - ke->ke_thread = owner; - owner->td_kse = ke; - setrunqueue(owner); - CTR2(KTR_RUNQ, "kse_reassign: ke%p -> td%p (give back)", - ke, owner); - return; - } /* * Find the first unassigned thread @@ -212,29 +209,77 @@ kse_reassign(struct kse *ke) * If we found one assign it the kse, otherwise idle the kse. */ if (td) { + /* + * If the original is bound to us we can only be lent out so + * make a loan, otherwise we just drop the + * original thread. + */ + if (original) { + if (((original->td_flags & TDF_UNBOUND) == 0)) { + /* + * Put the owner on the side + */ + ke->ke_bound = original; + TD_SET_LOAN(original); + } else { + original->td_kse = NULL; + } + } kg->kg_last_assigned = td; td->td_kse = ke; ke->ke_thread = td; runq_add(&runq, ke); - if (owner) - TD_SET_LOAN(owner); + /* + * if we have already borrowed this, + * just pass it to the new thread, + * otherwise, enact the loan. + */ CTR2(KTR_RUNQ, "kse_reassign: ke%p -> td%p", ke, td); - } else if (!owner) { - ke->ke_state = KES_IDLE; - ke->ke_thread = NULL; - TAILQ_INSERT_HEAD(&kg->kg_iq, ke, ke_kgrlist); - kg->kg_idle_kses++; - CTR1(KTR_RUNQ, "kse_reassign: ke%p idled", ke); - } else { + return; + } + if (owner) { /* already loaned out */ + /* effectivly unloan it */ TD_CLR_LOAN(owner); - ke->ke_state = KES_THREAD; ke->ke_thread = owner; - owner->td_kse = ke; - ke->ke_flags |= KEF_ONLOANQ; - TAILQ_INSERT_HEAD(&kg->kg_lq, ke, ke_kgrlist); - kg->kg_loan_kses++; - CTR1(KTR_RUNQ, "kse_reassign: ke%p is on loan queue", ke); + ke->ke_bound = NULL; + if (original) + original->td_kse = NULL; + original = owner; + + if (TD_CAN_RUN(owner)) { + /* + * If the owner thread is now runnable, run it.. + * Let it have its KSE back. + */ + setrunqueue(owner); + CTR2(KTR_RUNQ, "kse_reassign: ke%p -> td%p (give back)", + ke, owner); + return; + } + } + /* + * Presetly NOT loaned out. + * If we are bound, we go on the loanable queue + * otherwise onto the free queue. + */ + if (original) { + if (((original->td_flags & TDF_UNBOUND) == 0)) { + ke->ke_state = KES_THREAD; + ke->ke_flags |= KEF_ONLOANQ; + ke->ke_bound = NULL; + TAILQ_INSERT_HEAD(&kg->kg_lq, ke, ke_kgrlist); + kg->kg_loan_kses++; + CTR1(KTR_RUNQ, "kse_reassign: ke%p on loan queue", ke); + return; + } else { + original->td_kse = NULL; + } } + ke->ke_state = KES_IDLE; + ke->ke_thread = NULL; + TAILQ_INSERT_HEAD(&kg->kg_iq, ke, ke_kgrlist); + kg->kg_idle_kses++; + CTR1(KTR_RUNQ, "kse_reassign: ke%p idled", ke); } int @@ -252,7 +297,7 @@ kserunnable(void) void remrunqueue(struct thread *td) { - struct thread *td2, *td3, *owner; + struct thread *td2, *td3; struct ksegrp *kg; struct kse *ke; @@ -273,6 +318,8 @@ remrunqueue(struct thread *td) ke->ke_state = KES_THREAD; return; } + td3 = TAILQ_PREV(td, threadqueue, td_runq); + TAILQ_REMOVE(&kg->kg_runq, td, td_runq); if (ke) { /* * This thread has been assigned to a KSE. @@ -282,62 +329,12 @@ remrunqueue(struct thread *td) */ td2 = kg->kg_last_assigned; KASSERT((td2 != NULL), ("last assigned has wrong value ")); - td->td_kse = NULL; - if ((td3 = TAILQ_NEXT(td2, td_runq))) { - KASSERT(td3 != td, ("td3 somehow matched td")); - /* - * Give the next unassigned thread to the KSE - * so the number of runnable KSEs remains - * constant. - */ - td3->td_kse = ke; - ke->ke_thread = td3; + if (td2 == td) kg->kg_last_assigned = td3; - runq_readjust(&runq, ke); - } else { - /* - * There is no unassigned thread. - * If we were the last assigned one, - * adjust the last assigned pointer back - * one, which may result in NULL. - */ - if (td == td2) { - kg->kg_last_assigned = - TAILQ_PREV(td, threadqueue, td_runq); - } - runq_remove(&runq, ke); - KASSERT((ke->ke_state != KES_IDLE), - ("kse already idle")); - if (ke->ke_bound) { - owner = ke->ke_bound; - if (owner->td_inhibitors == TDI_LOAN) { - TD_CLR_LOAN(owner); - ke->ke_bound = NULL; - ke->ke_thread = owner; - owner->td_kse = ke; - setrunqueue(owner); - CTR2(KTR_RUNQ, - "remrunqueue: ke%p -> td%p (give back)", - ke, owner); - } else { - TD_CLR_LOAN(owner); - ke->ke_state = KES_THREAD; - ke->ke_thread = owner; - owner->td_kse = ke; - ke->ke_flags |= KEF_ONLOANQ; - TAILQ_INSERT_HEAD(&kg->kg_lq, ke, - ke_kgrlist); - kg->kg_loan_kses++; - } - } else { - ke->ke_state = KES_IDLE; - ke->ke_thread = NULL; - TAILQ_INSERT_HEAD(&kg->kg_iq, ke, ke_kgrlist); - kg->kg_idle_kses++; - } - } + td->td_kse = NULL; + ke->ke_thread = NULL; + kse_reassign(ke); } - TAILQ_REMOVE(&kg->kg_runq, td, td_runq); } void @@ -355,6 +352,15 @@ setrunqueue(struct thread *td) TD_SET_RUNQ(td); kg = td->td_ksegrp; kg->kg_runnable++; + if ((td->td_proc->p_flag & P_KSES) == 0) { + /* + * Common path optimisation: Only one of everything + * and the KSE is always already attached. + * Totally ignore the ksegrp run queue. + */ + runq_add(&runq, td->td_kse); + return; + } if ((td->td_flags & TDF_UNBOUND) == 0) { KASSERT((td->td_kse != NULL), ("queueing BAD thread to run queue")); @@ -365,14 +371,10 @@ setrunqueue(struct thread *td) TAILQ_REMOVE(&kg->kg_lq, ke, ke_kgrlist); kg->kg_loan_kses--; } - /* - * Common path optimisation: Only one of everything - * and the KSE is always already attached. - * Totally ignore the ksegrp run queue. - */ runq_add(&runq, td->td_kse); return; } + /* * Ok, so we are threading with this thread. * We don't have a KSE, see if we can get one.. @@ -394,11 +396,16 @@ setrunqueue(struct thread *td) ke->ke_state = KES_THREAD; kg->kg_idle_kses--; } else if (kg->kg_loan_kses) { + /* + * Failing that see if we can borrow one. + */ ke = TAILQ_FIRST(&kg->kg_lq); TAILQ_REMOVE(&kg->kg_lq, ke, ke_kgrlist); ke->ke_flags &= ~KEF_ONLOANQ; ke->ke_state = KES_THREAD; - TD_SET_LOAN(ke->ke_bound); + TD_SET_LOAN(ke->ke_thread); + ke->ke_bound = ke->ke_thread; + ke->ke_thread = NULL; kg->kg_loan_kses--; } else if (tda && (tda->td_priority > td->td_priority)) { /* @@ -697,6 +704,7 @@ runq_remove(struct runq *rq, struct kse *ke) ke->ke_ksegrp->kg_runq_kses--; } +#if 0 static void runq_readjust(struct runq *rq, struct kse *ke) { @@ -706,19 +714,27 @@ runq_readjust(struct runq *rq, struct kse *ke) runq_add(rq, ke); } } +#endif #if 0 void -thread_sanity_check(struct thread *td) +panc(char *string1, char *string2) +{ + printf("%s", string1); + Debugger(string2); +} + +void +thread_sanity_check(struct thread *td, char *string) { struct proc *p; struct ksegrp *kg; struct kse *ke; - struct thread *td2; + struct thread *td2 = NULL; unsigned int prevpri; - int saw_lastassigned; - int unassigned; - int assigned; + int saw_lastassigned = 0; + int unassigned = 0; + int assigned = 0; p = td->td_proc; kg = td->td_ksegrp; @@ -727,16 +743,16 @@ thread_sanity_check(struct thread *td) if (ke) { if (p != ke->ke_proc) { - panic("wrong proc"); + panc(string, "wrong proc"); } if (ke->ke_thread != td) { - panic("wrong thread"); + panc(string, "wrong thread"); } } if ((p->p_flag & P_KSES) == 0) { if (ke == NULL) { - panic("non KSE thread lost kse"); + panc(string, "non KSE thread lost kse"); } } else { prevpri = 0; @@ -745,22 +761,27 @@ thread_sanity_check(struct thread *td) assigned = 0; TAILQ_FOREACH(td2, &kg->kg_runq, td_runq) { if (td2->td_priority < prevpri) { - panic("thread runqueue unosorted"); + panc(string, "thread runqueue unosorted"); + } + if ((td2->td_state == TDS_RUNQ) && + td2->td_kse && + (td2->td_kse->ke_state != KES_ONRUNQ)) { + panc(string, "KSE wrong state"); } prevpri = td2->td_priority; if (td2->td_kse) { assigned++; if (unassigned) { - panic("unassigned before assigned"); + panc(string, "unassigned before assigned"); } if (kg->kg_last_assigned == NULL) { - panic("lastassigned corrupt"); + panc(string, "lastassigned corrupt"); } if (saw_lastassigned) { - panic("last assigned not last"); + panc(string, "last assigned not last"); } if (td2->td_kse->ke_thread != td2) { - panic("mismatched kse/thread"); + panc(string, "mismatched kse/thread"); } } else { unassigned++; @@ -768,28 +789,32 @@ thread_sanity_check(struct thread *td) if (td2 == kg->kg_last_assigned) { saw_lastassigned = 1; if (td2->td_kse == NULL) { - panic("last assigned not assigned"); + panc(string, "last assigned not assigned"); } } } if (kg->kg_last_assigned && (saw_lastassigned == 0)) { - panic("where on earth does lastassigned point?"); + panc(string, "where on earth does lastassigned point?"); } FOREACH_THREAD_IN_GROUP(kg, td2) { if (((td2->td_flags & TDF_UNBOUND) == 0) && (TD_ON_RUNQ(td2))) { assigned++; if (td2->td_kse == NULL) { - panic ("BOUND thread with no KSE"); + panc(string, "BOUND thread with no KSE"); } } } #if 0 if ((unassigned + assigned) != kg->kg_runnable) { - panic("wrong number in runnable"); + panc(string, "wrong number in runnable"); } #endif } + if (assigned == 12345) { + printf("%p %p %p %p %p %d, %d", + td, td2, ke, kg, p, assigned, saw_lastassigned); + } } #endif |