svn commit: r212115 - head/sys/kern

Matthew D Fleming mdf at FreeBSD.org
Wed Sep 1 20:32:48 UTC 2010


Author: mdf
Date: Wed Sep  1 20:32:47 2010
New Revision: 212115
URL: http://svn.freebsd.org/changeset/base/212115

Log:
  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 at .
  
  MFC after:	2 weeks

Modified:
  head/sys/kern/sched_ule.c

Modified: head/sys/kern/sched_ule.c
==============================================================================
--- head/sys/kern/sched_ule.c	Wed Sep  1 20:25:36 2010	(r212114)
+++ head/sys/kern/sched_ule.c	Wed Sep  1 20:32:47 2010	(r212115)
@@ -1797,10 +1797,16 @@ sched_switch(struct thread *td, struct t
 		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)


More information about the svn-src-head mailing list