rcu: Fix quiescent state reporting deadlock
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 15 Jun 2018 20:33:54 +0000 (16:33 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 15 Jun 2018 20:33:54 +0000 (16:33 -0400)
When a core is the last to report in, it will kick the gp_ktask's rendez
variable.  That will wake the gp_ktask, and waking a ktask is done with a
kernel message.  Currently, those messages are sent to the calling core.

When we reported *after* checking the RKMs, we'd halt.  Then the GP ktask
wouldn't run.  We wouldn't see it sleeping (e.g. with "db sem"), since it
was in the process of being awake.  We wouldn't see it running either,
since it was stuck as a KMSG.  With trace_printks, we could see it went
into the rendez (rcu.c L435), but never came out.

By kicking all the cores with "trace coretf -1", we woke the system up.
I thought to try that since it would trigger a QS, but in the trace also
spat out a message for the RKM that hadn't run yet.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/src/smp.c

index 886c7e4..d11083c 100644 (file)
@@ -69,10 +69,13 @@ static void __attribute__((noreturn)) __smp_idle(void *arg)
        enable_irq();   /* one-shot change to get any IRQs before we halt later */
        disable_irq();
        while (1) {
+               /* This might wake a kthread (the gp ktask), so be sure to run PRKM
+                * after reporting the quiescent state.  Note that after each RKM
+                * finishes, we'll also rerun rcu_report_qs(). */
+               rcu_report_qs();
                process_routine_kmsg();
                try_run_proc();
                cpu_bored();            /* call out to the ksched */
-               rcu_report_qs();
                /* cpu_halt() atomically turns on interrupts and halts the core.
                 * Important to do this, since we could have a RKM come in via an
                 * interrupt right while PRKM is returning, and we wouldn't catch