Fix a bug with sched_affinity() where it checks td_pinned of another
thread in a racy manner, which can lead to attempting to migrate a thread that is pinned to a CPU. Instead, have sched_switch() determine which CPU a thread should run on if the current one is not allowed. KASSERT in sched_bind() that the thread is not yet pinned to a CPU. KASSERT in sched_switch() that only migratable threads or those moving due to a sched_bind() are changing CPUs. sched_affinity code came from jhb@. MFC after: 2 weeks
This commit is contained in:
parent
91c265b83d
commit
0f7a0ebd59
@ -1797,10 +1797,16 @@ sched_switch(struct thread *td, struct thread *newtd, int flags)
|
||||
srqflag = (flags & SW_PREEMPT) ?
|
||||
SRQ_OURSELF|SRQ_YIELDING|SRQ_PREEMPTED :
|
||||
SRQ_OURSELF|SRQ_YIELDING;
|
||||
if (THREAD_CAN_MIGRATE(td) && !THREAD_CAN_SCHED(td, ts->ts_cpu))
|
||||
ts->ts_cpu = sched_pickcpu(td, 0);
|
||||
if (ts->ts_cpu == cpuid)
|
||||
tdq_runq_add(tdq, td, srqflag);
|
||||
else
|
||||
else {
|
||||
KASSERT(THREAD_CAN_MIGRATE(td) ||
|
||||
(ts->ts_flags & TSF_BOUND) != 0,
|
||||
("Thread %p shouldn't migrate", td));
|
||||
mtx = sched_switch_migrate(tdq, td, srqflag);
|
||||
}
|
||||
} else {
|
||||
/* This thread must be going to sleep. */
|
||||
TDQ_LOCK(tdq);
|
||||
@ -2383,7 +2389,6 @@ sched_affinity(struct thread *td)
|
||||
{
|
||||
#ifdef SMP
|
||||
struct td_sched *ts;
|
||||
int cpu;
|
||||
|
||||
THREAD_LOCK_ASSERT(td, MA_OWNED);
|
||||
ts = td->td_sched;
|
||||
@ -2397,17 +2402,13 @@ sched_affinity(struct thread *td)
|
||||
if (!TD_IS_RUNNING(td))
|
||||
return;
|
||||
td->td_flags |= TDF_NEEDRESCHED;
|
||||
if (!THREAD_CAN_MIGRATE(td))
|
||||
return;
|
||||
/*
|
||||
* Assign the new cpu and force a switch before returning to
|
||||
* userspace. If the target thread is not running locally send
|
||||
* an ipi to force the issue.
|
||||
* Force a switch before returning to userspace. If the
|
||||
* target thread is not running locally send an ipi to force
|
||||
* the issue.
|
||||
*/
|
||||
cpu = ts->ts_cpu;
|
||||
ts->ts_cpu = sched_pickcpu(td, 0);
|
||||
if (cpu != PCPU_GET(cpuid))
|
||||
ipi_cpu(cpu, IPI_PREEMPT);
|
||||
if (td != curthread)
|
||||
ipi_cpu(ts->ts_cpu, IPI_PREEMPT);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2424,6 +2425,7 @@ sched_bind(struct thread *td, int cpu)
|
||||
ts = td->td_sched;
|
||||
if (ts->ts_flags & TSF_BOUND)
|
||||
sched_unbind(td);
|
||||
KASSERT(THREAD_CAN_MIGRATE(td), ("%p must be migratable", td));
|
||||
ts->ts_flags |= TSF_BOUND;
|
||||
sched_pin();
|
||||
if (PCPU_GET(cpuid) == cpu)
|
||||
|
Loading…
x
Reference in New Issue
Block a user