Date: Sun, 27 Jul 2008 13:13:22 GMT From: John Baldwin <jhb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 146044 for review Message-ID: <200807271313.m6RDDMwY003107@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=146044 Change 146044 by jhb@jhb_zion on 2008/07/27 13:12:26 Better affinity handing: - Set a flag on the thread when a cpuset is applied if the set doesn't include all CPUs. This lets us avoid invoking sched_pickcpu() in the common case in sched_add(). - Handle threads executing on other CPUs and threads that are on a runqueue in sched_affinity(). Affected files ... .. //depot/projects/smpng/sys/kern/sched_4bsd.c#76 edit Differences ... ==== //depot/projects/smpng/sys/kern/sched_4bsd.c#76 (text+ko) ==== @@ -97,6 +97,7 @@ /* flags kept in td_flags */ #define TDF_DIDRUN TDF_SCHED0 /* thread actually ran. */ #define TDF_BOUND TDF_SCHED1 /* Bound to one CPU. */ +#define TDF_AFFINITY TDF_SCHED2 /* Has a non-"full" CPU set. */ #define SKE_RUNQ_PCPU(ts) \ ((ts)->ts_runq != 0 && (ts)->ts_runq != &runq) @@ -1165,34 +1166,25 @@ static int sched_pickcpu(struct thread *td) { - int best, cpu, fullset; + int best, cpu; mtx_assert(&sched_lock, MA_OWNED); - fullset = 1; best = NOCPU; for (cpu = 0; cpu <= mp_maxid; cpu++) { if (CPU_ABSENT(cpu)) continue; - if (!THREAD_CAN_SCHED(td, cpu)) { - /* - * At least one available CPU isn't in our - * set, so it isn't a "full" set. - */ - fullset = 0; + if (!THREAD_CAN_SCHED(td, cpu)) continue; - } if (best == NOCPU) best = cpu; else if (runq_length[cpu] < runq_length[best]) best = cpu; } + KASSERT(best != NOCPU, ("no valid CPUs")); - if (fullset) - return (NOCPU); - else - return (best); + return (best); } #endif @@ -1232,25 +1224,25 @@ single_cpu = 1; CTR3(KTR_RUNQ, "sched_add: Put td_sched:%p(td:%p) on cpu%d runq", ts, td, cpu); - } else if ((td)->td_flags & TDF_BOUND) { + } else if (td->td_flags & TDF_BOUND) { /* Find CPU from bound runq */ KASSERT(SKE_RUNQ_PCPU(ts),("sched_add: bound td_sched not on cpu runq")); cpu = ts->ts_runq - &runq_pcpu[0]; single_cpu = 1; CTR3(KTR_RUNQ, "sched_add: Put td_sched:%p(td:%p) on cpu%d runq", ts, td, cpu); - } else { + } else if (td->td_flags & TDF_AFFINITY) { /* Find a valid CPU for our cpuset */ cpu = sched_pickcpu(td); - if (cpu == NOCPU) { - CTR2(KTR_RUNQ, + ts->ts_runq = &runq_pcpu[cpu]; + single_cpu = 1; + CTR3(KTR_RUNQ, + "sched_add: Put td_sched:%p(td:%p) on cpu%d runq", ts, td, cpu); + } else { + CTR2(KTR_RUNQ, "sched_add: adding td_sched:%p (td:%p) to gbl runq", ts, td); - ts->ts_runq = &runq; - } else { - single_cpu = 1; - CTR3(KTR_RUNQ, - "sched_add: Put td_sched:%p(td:%p) on cpu%d runq", ts, td, cpu); - } + cpu = NOCPU; + ts->ts_runq = &runq; } if (single_cpu && (cpu != PCPU_GET(cpuid))) { @@ -1577,16 +1569,56 @@ sched_affinity(struct thread *td) { #ifdef SMP + struct td_sched *ts; + int cpu; + + THREAD_LOCK_ASSERT(td, MA_OWNED); - THREAD_LOCK_ASSERT(td, MA_OWNED); + /* + * Set the TDF_AFFINITY flag if there is at least one CPU this + * thread can't run on. + */ + td->td_flags &= ~TDF_AFFINITY; + for (cpu = 0; cpu <= mp_maxid; cpu++) { + if (CPU_ABSENT(cpu)) + continue; + if (!THREAD_CAN_SCHED(td, cpu)) { + td->td_flags |= TDF_AFFINITY; + break; + } + } /* - * See if our current CPU is in the set. If not, force a - * context switch. + * If this thread can run on all CPUs, nothing else to do. */ - if (THREAD_CAN_SCHED(td, PCPU_GET(cpuid))) + if (!(td->td_flags & TDF_AFFINITY)) return; - mi_switch(SW_VOL, NULL); + switch (td->td_state) { + case TDS_RUNQ: + /* + * If we are on a per-CPU runqueue that is in the set, + * then nothing needs to be done. + */ + ts = td->td_sched; + if (ts->ts_runq != &runq && + THREAD_CAN_SCHED(td, ts->ts_runq - runq_pcpu)) + return; + + /* Put this thread on a valid per-CPU runqueue. */ + sched_rem(td); + sched_add(td, SRQ_BORING); + break; + case TDS_RUNNING: + /* + * See if our current CPU is in the set. If not, force a + * context switch. + */ + if (THREAD_CAN_SCHED(td, td->td_oncpu)) + return; + + mi_switch(SW_VOL, NULL); + break; + } #endif }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200807271313.m6RDDMwY003107>