kernel - Avoid a race between dfly_schedulerclock and usched_dfly_cpu_init.
authorImre Vadász <imre@vdsz.com>
Tue, 4 Sep 2018 20:47:17 +0000 (22:47 +0200)
committerImre Vadász <imre@vdsz.com>
Wed, 5 Sep 2018 19:55:18 +0000 (21:55 +0200)
* This race was repeatedly occuring during startup, running with multiple
  virtual cpu cores in qemu (using TCG emulation on a DragonFly host).

sys/kern/kern_clock.c

index 13f668b..d1e5e0c 100644 (file)
@@ -428,9 +428,6 @@ initclocks_other(void *dummy)
                                          SYSTF_MSSYNC | SYSTF_FIRST);
                systimer_init_periodic_flags(&gd->gd_hardclock, hardclock,
                                          NULL, hz, SYSTF_MSSYNC);
-               /* XXX correct the frequency for scheduler / estcpu tests */
-               systimer_init_periodic_flags(&gd->gd_schedclock, schedclock,
-                                         NULL, ESTCPUFREQ, SYSTF_MSSYNC);
        }
        lwkt_setcpu_self(ogd);
 
@@ -446,6 +443,31 @@ initclocks_other(void *dummy)
 }
 SYSINIT(clocks2, SI_BOOT2_POST_SMP, SI_ORDER_ANY, initclocks_other, NULL);
 
+/*
+ * This method is called on just the BSP, after all the usched implementations
+ * are initialized. This avoids races between usched initialization functions
+ * and usched_schedulerclock().
+ */
+static
+void
+initclocks_usched(void *dummy)
+{
+       struct globaldata *ogd = mycpu;
+       struct globaldata *gd;
+       int n;
+
+       for (n = 0; n < ncpus; ++n) {
+               lwkt_setcpu_self(globaldata_find(n));
+               gd = mycpu;
+
+               /* XXX correct the frequency for scheduler / estcpu tests */
+               systimer_init_periodic_flags(&gd->gd_schedclock, schedclock,
+                                         NULL, ESTCPUFREQ, SYSTF_MSSYNC);
+       }
+       lwkt_setcpu_self(ogd);
+}
+SYSINIT(clocks3, SI_BOOT2_USCHED, SI_ORDER_ANY, initclocks_usched, NULL);
+
 /*
  * This sets the current real time of day.  Timespecs are in seconds and
  * nanoseconds.  We do not mess with gd_time_seconds and gd_cpuclock_base,