aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutree_plugin.h
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2012-01-16 16:29:10 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2012-02-21 12:03:49 -0500
commita858af2875fb291d0f4b0a4419fefbf03c2379c0 (patch)
tree5183796cbf50ec0cd3bd5c741db15705376dacbd /kernel/rcutree_plugin.h
parent13cfcca0e4e2d4cee1d0183c049eb34e54ac976e (diff)
rcu: Print scheduling-clock information on RCU CPU stall-warning messages
There have been situations where RCU CPU stall warnings were caused by issues in scheduling-clock timer initialization. To make it easier to track these down, this commit causes the RCU CPU stall-warning messages to print out the number of scheduling-clock interrupts taken in the current grace period for each stalled CPU. Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/rcutree_plugin.h')
-rw-r--r--kernel/rcutree_plugin.h150
1 files changed, 147 insertions, 3 deletions
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 0e74e1c6333f..aa93b074bb2f 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -63,7 +63,10 @@ static void __init rcu_bootup_announce_oddness(void)
63 printk(KERN_INFO "\tRCU torture testing starts during boot.\n"); 63 printk(KERN_INFO "\tRCU torture testing starts during boot.\n");
64#endif 64#endif
65#if defined(CONFIG_TREE_PREEMPT_RCU) && !defined(CONFIG_RCU_CPU_STALL_VERBOSE) 65#if defined(CONFIG_TREE_PREEMPT_RCU) && !defined(CONFIG_RCU_CPU_STALL_VERBOSE)
66 printk(KERN_INFO "\tVerbose stalled-CPUs detection is disabled.\n"); 66 printk(KERN_INFO "\tDump stacks of tasks blocking RCU-preempt GP.\n");
67#endif
68#if defined(CONFIG_RCU_CPU_STALL_INFO)
69 printk(KERN_INFO "\tAdditional per-CPU info printed with stalls.\n");
67#endif 70#endif
68#if NUM_RCU_LVL_4 != 0 71#if NUM_RCU_LVL_4 != 0
69 printk(KERN_INFO "\tExperimental four-level hierarchy is enabled.\n"); 72 printk(KERN_INFO "\tExperimental four-level hierarchy is enabled.\n");
@@ -490,6 +493,31 @@ static void rcu_print_detail_task_stall(struct rcu_state *rsp)
490 493
491#endif /* #else #ifdef CONFIG_RCU_CPU_STALL_VERBOSE */ 494#endif /* #else #ifdef CONFIG_RCU_CPU_STALL_VERBOSE */
492 495
496#ifdef CONFIG_RCU_CPU_STALL_INFO
497
498static void rcu_print_task_stall_begin(struct rcu_node *rnp)
499{
500 printk(KERN_ERR "\tTasks blocked on level-%d rcu_node (CPUs %d-%d):",
501 rnp->level, rnp->grplo, rnp->grphi);
502}
503
504static void rcu_print_task_stall_end(void)
505{
506 printk(KERN_CONT "\n");
507}
508
509#else /* #ifdef CONFIG_RCU_CPU_STALL_INFO */
510
511static void rcu_print_task_stall_begin(struct rcu_node *rnp)
512{
513}
514
515static void rcu_print_task_stall_end(void)
516{
517}
518
519#endif /* #else #ifdef CONFIG_RCU_CPU_STALL_INFO */
520
493/* 521/*
494 * Scan the current list of tasks blocked within RCU read-side critical 522 * Scan the current list of tasks blocked within RCU read-side critical
495 * sections, printing out the tid of each. 523 * sections, printing out the tid of each.
@@ -501,12 +529,14 @@ static int rcu_print_task_stall(struct rcu_node *rnp)
501 529
502 if (!rcu_preempt_blocked_readers_cgp(rnp)) 530 if (!rcu_preempt_blocked_readers_cgp(rnp))
503 return 0; 531 return 0;
532 rcu_print_task_stall_begin(rnp);
504 t = list_entry(rnp->gp_tasks, 533 t = list_entry(rnp->gp_tasks,
505 struct task_struct, rcu_node_entry); 534 struct task_struct, rcu_node_entry);
506 list_for_each_entry_continue(t, &rnp->blkd_tasks, rcu_node_entry) { 535 list_for_each_entry_continue(t, &rnp->blkd_tasks, rcu_node_entry) {
507 printk(" P%d", t->pid); 536 printk(KERN_CONT " P%d", t->pid);
508 ndetected++; 537 ndetected++;
509 } 538 }
539 rcu_print_task_stall_end();
510 return ndetected; 540 return ndetected;
511} 541}
512 542
@@ -2004,7 +2034,7 @@ static void rcu_cleanup_after_idle(int cpu)
2004} 2034}
2005 2035
2006/* 2036/*
2007 * Do the idle-entry grace-period work, which, because CONFIG_RCU_FAST_NO_HZ=y, 2037 * Do the idle-entry grace-period work, which, because CONFIG_RCU_FAST_NO_HZ=n,
2008 * is nothing. 2038 * is nothing.
2009 */ 2039 */
2010static void rcu_prepare_for_idle(int cpu) 2040static void rcu_prepare_for_idle(int cpu)
@@ -2273,3 +2303,117 @@ static void rcu_prepare_for_idle(int cpu)
2273} 2303}
2274 2304
2275#endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */ 2305#endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */
2306
2307#ifdef CONFIG_RCU_CPU_STALL_INFO
2308
2309#ifdef CONFIG_RCU_FAST_NO_HZ
2310
2311static void print_cpu_stall_fast_no_hz(char *cp, int cpu)
2312{
2313 struct hrtimer *hrtp = &per_cpu(rcu_idle_gp_timer, cpu);
2314
2315 sprintf(cp, "drain=%d %c timer=%lld",
2316 per_cpu(rcu_dyntick_drain, cpu),
2317 per_cpu(rcu_dyntick_holdoff, cpu) == jiffies ? 'H' : '.',
2318 hrtimer_active(hrtp)
2319 ? ktime_to_us(hrtimer_get_remaining(hrtp))
2320 : -1);
2321}
2322
2323#else /* #ifdef CONFIG_RCU_FAST_NO_HZ */
2324
2325static void print_cpu_stall_fast_no_hz(char *cp, int cpu)
2326{
2327}
2328
2329#endif /* #else #ifdef CONFIG_RCU_FAST_NO_HZ */
2330
2331/* Initiate the stall-info list. */
2332static void print_cpu_stall_info_begin(void)
2333{
2334 printk(KERN_CONT "\n");
2335}
2336
2337/*
2338 * Print out diagnostic information for the specified stalled CPU.
2339 *
2340 * If the specified CPU is aware of the current RCU grace period
2341 * (flavor specified by rsp), then print the number of scheduling
2342 * clock interrupts the CPU has taken during the time that it has
2343 * been aware. Otherwise, print the number of RCU grace periods
2344 * that this CPU is ignorant of, for example, "1" if the CPU was
2345 * aware of the previous grace period.
2346 *
2347 * Also print out idle and (if CONFIG_RCU_FAST_NO_HZ) idle-entry info.
2348 */
2349static void print_cpu_stall_info(struct rcu_state *rsp, int cpu)
2350{
2351 char fast_no_hz[72];
2352 struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
2353 struct rcu_dynticks *rdtp = rdp->dynticks;
2354 char *ticks_title;
2355 unsigned long ticks_value;
2356
2357 if (rsp->gpnum == rdp->gpnum) {
2358 ticks_title = "ticks this GP";
2359 ticks_value = rdp->ticks_this_gp;
2360 } else {
2361 ticks_title = "GPs behind";
2362 ticks_value = rsp->gpnum - rdp->gpnum;
2363 }
2364 print_cpu_stall_fast_no_hz(fast_no_hz, cpu);
2365 printk(KERN_ERR "\t%d: (%lu %s) idle=%03x/%llx/%d %s\n",
2366 cpu, ticks_value, ticks_title,
2367 atomic_read(&rdtp->dynticks) & 0xfff,
2368 rdtp->dynticks_nesting, rdtp->dynticks_nmi_nesting,
2369 fast_no_hz);
2370}
2371
2372/* Terminate the stall-info list. */
2373static void print_cpu_stall_info_end(void)
2374{
2375 printk(KERN_ERR "\t");
2376}
2377
2378/* Zero ->ticks_this_gp for all flavors of RCU. */
2379static void zero_cpu_stall_ticks(struct rcu_data *rdp)
2380{
2381 rdp->ticks_this_gp = 0;
2382}
2383
2384/* Increment ->ticks_this_gp for all flavors of RCU. */
2385static void increment_cpu_stall_ticks(void)
2386{
2387 __get_cpu_var(rcu_sched_data).ticks_this_gp++;
2388 __get_cpu_var(rcu_bh_data).ticks_this_gp++;
2389#ifdef CONFIG_TREE_PREEMPT_RCU
2390 __get_cpu_var(rcu_preempt_data).ticks_this_gp++;
2391#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
2392}
2393
2394#else /* #ifdef CONFIG_RCU_CPU_STALL_INFO */
2395
2396static void print_cpu_stall_info_begin(void)
2397{
2398 printk(KERN_CONT " {");
2399}
2400
2401static void print_cpu_stall_info(struct rcu_state *rsp, int cpu)
2402{
2403 printk(KERN_CONT " %d", cpu);
2404}
2405
2406static void print_cpu_stall_info_end(void)
2407{
2408 printk(KERN_CONT "} ");
2409}
2410
2411static void zero_cpu_stall_ticks(struct rcu_data *rdp)
2412{
2413}
2414
2415static void increment_cpu_stall_ticks(void)
2416{
2417}
2418
2419#endif /* #else #ifdef CONFIG_RCU_CPU_STALL_INFO */