diff --git a/Documentation/RCU/stallwarn.txt b/Documentation/RCU/stallwarn.txt index 5abea29b41a0..50833568cb10 100644 --- a/Documentation/RCU/stallwarn.txt +++ b/Documentation/RCU/stallwarn.txt @@ -139,6 +139,15 @@ no non-lazy callbacks ("." is printed otherwise, as shown above) and "D" indicates that dyntick-idle processing is enabled ("." is printed otherwise, for example, if disabled via the "nohz=" kernel boot parameter). +If the relevant grace-period kthread has been unable to run prior to +the stall warning, the following additional line is printed: + + rcu_preempt kthread starved for 2023 jiffies! + +Starving the grace-period kthreads of CPU time can of course result in +RCU CPU stall warnings even when all CPUs and tasks have passed through +the required quiescent states. + Multiple Warnings From One Stall diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 68a28c78189c..fc3abf16cc22 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -826,6 +826,21 @@ static void record_gp_stall_check_time(struct rcu_state *rsp) rsp->n_force_qs_gpstart = ACCESS_ONCE(rsp->n_force_qs); } +/* + * Complain about starvation of grace-period kthread. + */ +static void rcu_check_gp_kthread_starvation(struct rcu_state *rsp) +{ + unsigned long gpa; + unsigned long j; + + j = jiffies; + gpa = ACCESS_ONCE(rsp->gp_activity); + if (j - gpa > 2 * HZ) + pr_err("%s kthread starved for %ld jiffies!\n", + rsp->name, j - gpa); +} + /* * Dump stacks of all tasks running on stalled CPUs. This is a fallback * for architectures that do not implement trigger_all_cpu_backtrace(). @@ -926,9 +941,10 @@ static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum) } /* Complain about tasks blocking the grace period. */ - rcu_print_detail_task_stall(rsp); + rcu_check_gp_kthread_starvation(rsp); + force_quiescent_state(rsp); /* Kick them all. */ } @@ -952,6 +968,9 @@ static void print_cpu_stall(struct rcu_state *rsp) totqlen += per_cpu_ptr(rsp->rda, cpu)->qlen; pr_cont(" (t=%lu jiffies g=%lu c=%lu q=%lu)\n", jiffies - rsp->gp_start, rsp->gpnum, rsp->completed, totqlen); + + rcu_check_gp_kthread_starvation(rsp); + if (!trigger_all_cpu_backtrace()) dump_stack();