kernel - Fix startup race in usched_dfly
authorMatthew Dillon <dillon@apollo.backplane.com>
Sun, 26 Aug 2018 18:52:59 +0000 (11:52 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 29 Aug 2018 15:27:26 +0000 (08:27 -0700)
* Use a master configuration lock for usched_dfly's thread
  creation, ensuring that no thread tries to check dfly_pcpu[]
  until the whole thing has been initialized.

* Fixes occassional panic in usched_dfly on boot on many-cores
  systems due to a lower-numbered usched thread triggering before
  dfly_pcpu is completely initialized.

sys/kern/usched_dfly.c

index 7fdb9da..26fdf48 100644 (file)
@@ -217,6 +217,7 @@ static cpumask_t dfly_rdyprocmask;  /* ready to accept a user process */
 static struct usched_dfly_pcpu dfly_pcpu[MAXCPU];
 static struct sysctl_ctx_list usched_dfly_sysctl_ctx;
 static struct sysctl_oid *usched_dfly_sysctl_tree;
+static struct lock usched_dfly_config_lk = LOCK_INITIALIZER("usdfs", 0, 0);
 
 /* Debug info exposed through debug.* sysctl */
 
@@ -2248,14 +2249,19 @@ dfly_helper_thread(void *dummy)
     mask = gd->gd_cpumask;     /* doesn't change */
     dd = &dfly_pcpu[cpuid];
 
+    /*
+     * Initial interlock, make sure all dfly_pcpu[] structures have
+     * been initialized before proceeding.
+     */
+    lockmgr(&usched_dfly_config_lk, LK_SHARED);
+    lockmgr(&usched_dfly_config_lk, LK_RELEASE);
+
     /*
      * Since we only want to be woken up only when no user processes
      * are scheduled on a cpu, run at an ultra low priority.
      */
     lwkt_setpri_self(TDPRI_USER_SCHEDULER);
 
-    tsleep(dd->helper_thread, 0, "schslp", 0);
-
     for (;;) {
        /*
         * We use the LWKT deschedule-interlock trick to avoid racing
@@ -2406,6 +2412,8 @@ usched_dfly_cpu_init(void)
 
        usched_dfly_node_mem = get_highest_node_memory();
 
+       lockmgr(&usched_dfly_config_lk, LK_EXCLUSIVE);
+
        for (i = 0; i < ncpus; ++i) {
                dfly_pcpu_t dd = &dfly_pcpu[i];
                cpumask_t mask;
@@ -2612,6 +2620,8 @@ usched_dfly_cpu_init(void)
                                "paremter hw.cpu_topology.level_description");
 #endif
        }
+       lockmgr(&usched_dfly_config_lk, LK_RELEASE);
 }
+
 SYSINIT(uschedtd, SI_BOOT2_USCHED, SI_ORDER_SECOND,
        usched_dfly_cpu_init, NULL);