mirror of https://gitee.com/openkylin/linux.git
rcu/nocb: Add grace period and task state to show_rcu_nocb_state() output
This commit improves debuggability by indicating which grace period each batch of nocb callbacks is waiting on and by showing the task state and last CPU for reach nocb kthread. [ paulmck: Handle !SMP CB offloading per kernel test robot feedback. ] Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
This commit is contained in:
parent
70e8088b97
commit
341690611f
|
@ -117,6 +117,17 @@ static inline bool rcu_segcblist_restempty(struct rcu_segcblist *rsclp, int seg)
|
|||
return !READ_ONCE(*READ_ONCE(rsclp->tails[seg]));
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the specified segment of the specified rcu_segcblist structure
|
||||
* empty of callbacks?
|
||||
*/
|
||||
static inline bool rcu_segcblist_segempty(struct rcu_segcblist *rsclp, int seg)
|
||||
{
|
||||
if (seg == RCU_DONE_TAIL)
|
||||
return &rsclp->head == rsclp->tails[RCU_DONE_TAIL];
|
||||
return rsclp->tails[seg - 1] == rsclp->tails[seg];
|
||||
}
|
||||
|
||||
void rcu_segcblist_inc_len(struct rcu_segcblist *rsclp);
|
||||
void rcu_segcblist_add_len(struct rcu_segcblist *rsclp, long v);
|
||||
void rcu_segcblist_init(struct rcu_segcblist *rsclp);
|
||||
|
|
|
@ -2672,6 +2672,19 @@ void rcu_bind_current_to_nocb(void)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(rcu_bind_current_to_nocb);
|
||||
|
||||
// The ->on_cpu field is available only in CONFIG_SMP=y, so...
|
||||
#ifdef CONFIG_SMP
|
||||
static char *show_rcu_should_be_on_cpu(struct task_struct *tsp)
|
||||
{
|
||||
return tsp && tsp->state == TASK_RUNNING && !tsp->on_cpu ? "!" : "";
|
||||
}
|
||||
#else // #ifdef CONFIG_SMP
|
||||
static char *show_rcu_should_be_on_cpu(struct task_struct *tsp)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
#endif // #else #ifdef CONFIG_SMP
|
||||
|
||||
/*
|
||||
* Dump out nocb grace-period kthread state for the specified rcu_data
|
||||
* structure.
|
||||
|
@ -2680,7 +2693,7 @@ static void show_rcu_nocb_gp_state(struct rcu_data *rdp)
|
|||
{
|
||||
struct rcu_node *rnp = rdp->mynode;
|
||||
|
||||
pr_info("nocb GP %d %c%c%c%c%c%c %c[%c%c] %c%c:%ld rnp %d:%d %lu\n",
|
||||
pr_info("nocb GP %d %c%c%c%c%c%c %c[%c%c] %c%c:%ld rnp %d:%d %lu %c CPU %d%s\n",
|
||||
rdp->cpu,
|
||||
"kK"[!!rdp->nocb_gp_kthread],
|
||||
"lL"[raw_spin_is_locked(&rdp->nocb_gp_lock)],
|
||||
|
@ -2694,12 +2707,17 @@ static void show_rcu_nocb_gp_state(struct rcu_data *rdp)
|
|||
".B"[!!rdp->nocb_gp_bypass],
|
||||
".G"[!!rdp->nocb_gp_gp],
|
||||
(long)rdp->nocb_gp_seq,
|
||||
rnp->grplo, rnp->grphi, READ_ONCE(rdp->nocb_gp_loops));
|
||||
rnp->grplo, rnp->grphi, READ_ONCE(rdp->nocb_gp_loops),
|
||||
rdp->nocb_gp_kthread ? task_state_to_char(rdp->nocb_gp_kthread) : '.',
|
||||
rdp->nocb_cb_kthread ? (int)task_cpu(rdp->nocb_gp_kthread) : -1,
|
||||
show_rcu_should_be_on_cpu(rdp->nocb_cb_kthread));
|
||||
}
|
||||
|
||||
/* Dump out nocb kthread state for the specified rcu_data structure. */
|
||||
static void show_rcu_nocb_state(struct rcu_data *rdp)
|
||||
{
|
||||
char bufw[20];
|
||||
char bufr[20];
|
||||
struct rcu_segcblist *rsclp = &rdp->cblist;
|
||||
bool waslocked;
|
||||
bool wastimer;
|
||||
|
@ -2708,7 +2726,9 @@ static void show_rcu_nocb_state(struct rcu_data *rdp)
|
|||
if (rdp->nocb_gp_rdp == rdp)
|
||||
show_rcu_nocb_gp_state(rdp);
|
||||
|
||||
pr_info(" CB %d->%d %c%c%c%c%c%c F%ld L%ld C%d %c%c%c%c%c q%ld\n",
|
||||
sprintf(bufw, "%ld", rsclp->gp_seq[RCU_WAIT_TAIL]);
|
||||
sprintf(bufr, "%ld", rsclp->gp_seq[RCU_NEXT_READY_TAIL]);
|
||||
pr_info(" CB %d^%d->%d %c%c%c%c%c%c F%ld L%ld C%d %c%c%s%c%s%c%c q%ld %c CPU %d%s\n",
|
||||
rdp->cpu, rdp->nocb_gp_rdp->cpu,
|
||||
"kK"[!!rdp->nocb_cb_kthread],
|
||||
"bB"[raw_spin_is_locked(&rdp->nocb_bypass_lock)],
|
||||
|
@ -2720,11 +2740,16 @@ static void show_rcu_nocb_state(struct rcu_data *rdp)
|
|||
jiffies - rdp->nocb_nobypass_last,
|
||||
rdp->nocb_nobypass_count,
|
||||
".D"[rcu_segcblist_ready_cbs(rsclp)],
|
||||
".W"[!rcu_segcblist_restempty(rsclp, RCU_DONE_TAIL)],
|
||||
".R"[!rcu_segcblist_restempty(rsclp, RCU_WAIT_TAIL)],
|
||||
".N"[!rcu_segcblist_restempty(rsclp, RCU_NEXT_READY_TAIL)],
|
||||
".W"[!rcu_segcblist_segempty(rsclp, RCU_WAIT_TAIL)],
|
||||
rcu_segcblist_segempty(rsclp, RCU_WAIT_TAIL) ? "" : bufw,
|
||||
".R"[!rcu_segcblist_segempty(rsclp, RCU_NEXT_READY_TAIL)],
|
||||
rcu_segcblist_segempty(rsclp, RCU_NEXT_READY_TAIL) ? "" : bufr,
|
||||
".N"[!rcu_segcblist_segempty(rsclp, RCU_NEXT_TAIL)],
|
||||
".B"[!!rcu_cblist_n_cbs(&rdp->nocb_bypass)],
|
||||
rcu_segcblist_n_cbs(&rdp->cblist));
|
||||
rcu_segcblist_n_cbs(&rdp->cblist),
|
||||
rdp->nocb_cb_kthread ? task_state_to_char(rdp->nocb_cb_kthread) : '.',
|
||||
rdp->nocb_cb_kthread ? (int)task_cpu(rdp->nocb_gp_kthread) : -1,
|
||||
show_rcu_should_be_on_cpu(rdp->nocb_cb_kthread));
|
||||
|
||||
/* It is OK for GP kthreads to have GP state. */
|
||||
if (rdp->nocb_gp_rdp == rdp)
|
||||
|
|
Loading…
Reference in New Issue