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 j...@.
  
  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)
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to