Fix sched_stop_secondary_cpus() to properly drain CPUs
authormatthew <matthew@openbsd.org>
Sun, 13 Jul 2014 21:44:58 +0000 (21:44 +0000)
committermatthew <matthew@openbsd.org>
Sun, 13 Jul 2014 21:44:58 +0000 (21:44 +0000)
TAILQ_FOREACH() isn't safe to use in sched_chooseproc() to iterate
over the run queues because within the loop body we remove the threads
from their run queues and reinsert them elsewhere.  As a result, we
end up only draining the first thread of each run queue rather than
all of them.

ok kettenis

sys/kern/kern_sched.c

index 32e8527..6717726 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_sched.c,v 1.32 2014/05/04 05:03:26 guenther Exp $        */
+/*     $OpenBSD: kern_sched.c,v 1.33 2014/07/13 21:44:58 matthew Exp $ */
 /*
  * Copyright (c) 2007, 2008 Artur Grabowski <art@openbsd.org>
  *
@@ -272,7 +272,7 @@ sched_chooseproc(void)
        if (spc->spc_schedflags & SPCF_SHOULDHALT) {
                if (spc->spc_whichqs) {
                        for (queue = 0; queue < SCHED_NQS; queue++) {
-                               TAILQ_FOREACH(p, &spc->spc_qs[queue], p_runq) {
+                               while ((p = TAILQ_FIRST(&spc->spc_qs[queue]))) {
                                        remrunqueue(p);
                                        p->p_cpu = sched_choosecpu(p);
                                        setrunqueue(p);