diff options
author | rstone <rstone@FreeBSD.org> | 2011-04-26 20:34:30 +0000 |
---|---|---|
committer | rstone <rstone@FreeBSD.org> | 2011-04-26 20:34:30 +0000 |
commit | 8a5b424a2c62c14118be6d66ab220b91ae0b4c9d (patch) | |
tree | 23e16ab18aab2d5f48a85672be928ff55083d475 /sys/kern | |
parent | efe1808e9f275c15c3014215e1ad0a85a9aae675 (diff) | |
download | FreeBSD-src-8a5b424a2c62c14118be6d66ab220b91ae0b4c9d.zip FreeBSD-src-8a5b424a2c62c14118be6d66ab220b91ae0b4c9d.tar.gz |
If the 4BSD scheduler tries to schedule a thread that has been pinned or
bound to an AP before SMP has started, the system will panic when we try
to touch per-CPU state for that AP because that state has not been
initialized yet. Fix this in the same way as ULE: place all threads in
the global run queue before SMP has started.
Reviewed by: jhb
MFC after: 1 month
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/sched_4bsd.c | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c index 3129222..9424f73 100644 --- a/sys/kern/sched_4bsd.c +++ b/sys/kern/sched_4bsd.c @@ -1246,25 +1246,27 @@ sched_add(struct thread *td, int flags) } TD_SET_RUNQ(td); - if (td->td_pinned != 0) { - cpu = td->td_lastcpu; - 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 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 if (ts->ts_flags & TSF_AFFINITY) { - /* Find a valid CPU for our cpuset */ - cpu = sched_pickcpu(td); + /* + * If SMP is started and the thread is pinned or otherwise limited to + * a specific set of CPUs, queue the thread to a per-CPU run queue. + * Otherwise, queue the thread to the global run queue. + * + * If SMP has not yet been started we must use the global run queue + * as per-CPU state may not be initialized yet and we may crash if we + * try to access the per-CPU run queues. + */ + if (smp_started && (td->td_pinned != 0 || td->td_flags & TDF_BOUND || + ts->ts_flags & TSF_AFFINITY)) { + if (td->td_pinned != 0) + cpu = td->td_lastcpu; + 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]; + } else + /* Find a valid CPU for our cpuset */ + cpu = sched_pickcpu(td); ts->ts_runq = &runq_pcpu[cpu]; single_cpu = 1; CTR3(KTR_RUNQ, |