diff options
Diffstat (limited to 'kernel/rcutiny_plugin.h')
-rw-r--r-- | kernel/rcutiny_plugin.h | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h index f85016a2309b..8a233002faeb 100644 --- a/kernel/rcutiny_plugin.h +++ b/kernel/rcutiny_plugin.h | |||
@@ -33,6 +33,9 @@ struct rcu_ctrlblk { | |||
33 | struct rcu_head **donetail; /* ->next pointer of last "done" CB. */ | 33 | struct rcu_head **donetail; /* ->next pointer of last "done" CB. */ |
34 | struct rcu_head **curtail; /* ->next pointer of last CB. */ | 34 | struct rcu_head **curtail; /* ->next pointer of last CB. */ |
35 | RCU_TRACE(long qlen); /* Number of pending CBs. */ | 35 | RCU_TRACE(long qlen); /* Number of pending CBs. */ |
36 | RCU_TRACE(unsigned long gp_start); /* Start time for stalls. */ | ||
37 | RCU_TRACE(unsigned long ticks_this_gp); /* Statistic for stalls. */ | ||
38 | RCU_TRACE(unsigned long jiffies_stall); /* Jiffies at next stall. */ | ||
36 | RCU_TRACE(char *name); /* Name of RCU type. */ | 39 | RCU_TRACE(char *name); /* Name of RCU type. */ |
37 | }; | 40 | }; |
38 | 41 | ||
@@ -54,6 +57,51 @@ int rcu_scheduler_active __read_mostly; | |||
54 | EXPORT_SYMBOL_GPL(rcu_scheduler_active); | 57 | EXPORT_SYMBOL_GPL(rcu_scheduler_active); |
55 | #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ | 58 | #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ |
56 | 59 | ||
60 | #ifdef CONFIG_RCU_TRACE | ||
61 | |||
62 | static void check_cpu_stall(struct rcu_ctrlblk *rcp) | ||
63 | { | ||
64 | unsigned long j; | ||
65 | unsigned long js; | ||
66 | |||
67 | if (rcu_cpu_stall_suppress) | ||
68 | return; | ||
69 | rcp->ticks_this_gp++; | ||
70 | j = jiffies; | ||
71 | js = rcp->jiffies_stall; | ||
72 | if (*rcp->curtail && ULONG_CMP_GE(j, js)) { | ||
73 | pr_err("INFO: %s stall on CPU (%lu ticks this GP) idle=%llx (t=%lu jiffies q=%ld)\n", | ||
74 | rcp->name, rcp->ticks_this_gp, rcu_dynticks_nesting, | ||
75 | jiffies - rcp->gp_start, rcp->qlen); | ||
76 | dump_stack(); | ||
77 | } | ||
78 | if (*rcp->curtail && ULONG_CMP_GE(j, js)) | ||
79 | rcp->jiffies_stall = jiffies + | ||
80 | 3 * rcu_jiffies_till_stall_check() + 3; | ||
81 | else if (ULONG_CMP_GE(j, js)) | ||
82 | rcp->jiffies_stall = jiffies + rcu_jiffies_till_stall_check(); | ||
83 | } | ||
84 | |||
85 | static void check_cpu_stall_preempt(void); | ||
86 | |||
87 | #endif /* #ifdef CONFIG_RCU_TRACE */ | ||
88 | |||
89 | static void reset_cpu_stall_ticks(struct rcu_ctrlblk *rcp) | ||
90 | { | ||
91 | #ifdef CONFIG_RCU_TRACE | ||
92 | rcp->ticks_this_gp = 0; | ||
93 | rcp->gp_start = jiffies; | ||
94 | rcp->jiffies_stall = jiffies + rcu_jiffies_till_stall_check(); | ||
95 | #endif /* #ifdef CONFIG_RCU_TRACE */ | ||
96 | } | ||
97 | |||
98 | static void check_cpu_stalls(void) | ||
99 | { | ||
100 | RCU_TRACE(check_cpu_stall(&rcu_bh_ctrlblk)); | ||
101 | RCU_TRACE(check_cpu_stall(&rcu_sched_ctrlblk)); | ||
102 | RCU_TRACE(check_cpu_stall_preempt()); | ||
103 | } | ||
104 | |||
57 | #ifdef CONFIG_TINY_PREEMPT_RCU | 105 | #ifdef CONFIG_TINY_PREEMPT_RCU |
58 | 106 | ||
59 | #include <linux/delay.h> | 107 | #include <linux/delay.h> |
@@ -448,6 +496,7 @@ static void rcu_preempt_start_gp(void) | |||
448 | /* Official start of GP. */ | 496 | /* Official start of GP. */ |
449 | rcu_preempt_ctrlblk.gpnum++; | 497 | rcu_preempt_ctrlblk.gpnum++; |
450 | RCU_TRACE(rcu_preempt_ctrlblk.n_grace_periods++); | 498 | RCU_TRACE(rcu_preempt_ctrlblk.n_grace_periods++); |
499 | reset_cpu_stall_ticks(&rcu_preempt_ctrlblk.rcb); | ||
451 | 500 | ||
452 | /* Any blocked RCU readers block new GP. */ | 501 | /* Any blocked RCU readers block new GP. */ |
453 | if (rcu_preempt_blocked_readers_any()) | 502 | if (rcu_preempt_blocked_readers_any()) |
@@ -1054,4 +1103,11 @@ MODULE_AUTHOR("Paul E. McKenney"); | |||
1054 | MODULE_DESCRIPTION("Read-Copy Update tracing for tiny implementation"); | 1103 | MODULE_DESCRIPTION("Read-Copy Update tracing for tiny implementation"); |
1055 | MODULE_LICENSE("GPL"); | 1104 | MODULE_LICENSE("GPL"); |
1056 | 1105 | ||
1106 | static void check_cpu_stall_preempt(void) | ||
1107 | { | ||
1108 | #ifdef CONFIG_TINY_PREEMPT_RCU | ||
1109 | check_cpu_stall(&rcu_preempt_ctrlblk.rcb); | ||
1110 | #endif /* #ifdef CONFIG_TINY_PREEMPT_RCU */ | ||
1111 | } | ||
1112 | |||
1057 | #endif /* #ifdef CONFIG_RCU_TRACE */ | 1113 | #endif /* #ifdef CONFIG_RCU_TRACE */ |