rcu: Add quiescent states and boost states to show_rcu_gp_kthreads() output
authorPaul E. McKenney <paulmck@kernel.org>
Tue, 6 Apr 2021 23:31:42 +0000 (16:31 -0700)
committerPaul E. McKenney <paulmck@kernel.org>
Mon, 10 May 2021 23:22:54 +0000 (16:22 -0700)
This commit adds each rcu_node structure's ->qsmask and "bBEG" output
indicating whether: (1) There is a boost kthread, (2) A reader needs
to be (or is in the process of being) boosted, (3) A reader is blocking
an expedited grace period, and (4) A reader is blocking a normal grace
period.  This helps diagnose RCU priority boosting failures.

Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
kernel/rcu/tree.h
kernel/rcu/tree_plugin.h
kernel/rcu/tree_stall.h

index 71821d5..5fd0c44 100644 (file)
@@ -115,6 +115,7 @@ struct rcu_node {
                                /*  boosting for this rcu_node structure. */
        unsigned int boost_kthread_status;
                                /* State of boost_kthread_task for tracing. */
+       unsigned long n_boosts; /* Number of boosts for this rcu_node structure. */
 #ifdef CONFIG_RCU_NOCB_CPU
        struct swait_queue_head nocb_gp_wq[2];
                                /* Place for rcu_nocb_kthread() to wait GP. */
index 2cbe8f8..ef004cc 100644 (file)
@@ -1098,6 +1098,7 @@ static int rcu_boost(struct rcu_node *rnp)
        /* Lock only for side effect: boosts task t's priority. */
        rt_mutex_lock(&rnp->boost_mtx);
        rt_mutex_unlock(&rnp->boost_mtx);  /* Then keep lockdep happy. */
+       rnp->n_boosts++;
 
        return READ_ONCE(rnp->exp_tasks) != NULL ||
               READ_ONCE(rnp->boost_tasks) != NULL;
index a4e2bb3..c1f8386 100644 (file)
@@ -749,9 +749,15 @@ void show_rcu_gp_kthreads(void)
                if (ULONG_CMP_GE(READ_ONCE(rcu_state.gp_seq),
                                 READ_ONCE(rnp->gp_seq_needed)))
                        continue;
-               pr_info("\trcu_node %d:%d ->gp_seq %ld ->gp_seq_needed %ld\n",
-                       rnp->grplo, rnp->grphi, (long)data_race(rnp->gp_seq),
-                       (long)data_race(rnp->gp_seq_needed));
+               pr_info("\trcu_node %d:%d ->gp_seq %ld ->gp_seq_needed %ld ->qsmask %#lx %c%c%c%c ->n_boosts %ld\n",
+                       rnp->grplo, rnp->grphi,
+                       (long)data_race(rnp->gp_seq), (long)data_race(rnp->gp_seq_needed),
+                       data_race(rnp->qsmask),
+                       ".b"[!!data_race(rnp->boost_kthread_task)],
+                       ".B"[!!data_race(rnp->boost_tasks)],
+                       ".E"[!!data_race(rnp->exp_tasks)],
+                       ".G"[!!data_race(rnp->gp_tasks)],
+                       data_race(rnp->n_boosts));
                if (!rcu_is_leaf_node(rnp))
                        continue;
                for_each_leaf_node_possible_cpu(rnp, cpu) {