Commit 7ba5c840e64d4a967379f1ae3eca73278180b11d
Committed by
Ingo Molnar
1 parent
05cfbd66d0
Exists in
master
and in
4 other branches
rcu: Add __rcu_pending tracing to hierarchical RCU
Add tracing to __rcu_pending() to provide information on why RCU processing was kicked off. This is helpful for debugging hierarchical RCU, and might also be helpful in learning how hierarchical RCU operates. Located-by: Anton Blanchard <anton@au1.ibm.com> Tested-by: Anton Blanchard <anton@au1.ibm.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: anton@samba.org Cc: akpm@linux-foundation.org Cc: dipankar@in.ibm.com Cc: manfred@colorfullife.com Cc: cl@linux-foundation.org Cc: josht@linux.vnet.ibm.com Cc: schamp@sgi.com Cc: niv@us.ibm.com Cc: dvhltc@us.ibm.com Cc: ego@in.ibm.com Cc: laijs@cn.fujitsu.com Cc: rostedt@goodmis.org Cc: peterz@infradead.org Cc: penberg@cs.helsinki.fi Cc: andi@firstfloor.org Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> LKML-Reference: <1239683479943-git-send-email-> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Showing 3 changed files with 90 additions and 8 deletions Side-by-side Diff
include/linux/rcutree.h
... | ... | @@ -161,8 +161,15 @@ |
161 | 161 | unsigned long offline_fqs; /* Kicked due to being offline. */ |
162 | 162 | unsigned long resched_ipi; /* Sent a resched IPI. */ |
163 | 163 | |
164 | - /* 5) For future __rcu_pending statistics. */ | |
164 | + /* 5) __rcu_pending() statistics. */ | |
165 | 165 | long n_rcu_pending; /* rcu_pending() calls since boot. */ |
166 | + long n_rp_qs_pending; | |
167 | + long n_rp_cb_ready; | |
168 | + long n_rp_cpu_needs_gp; | |
169 | + long n_rp_gp_completed; | |
170 | + long n_rp_gp_started; | |
171 | + long n_rp_need_fqs; | |
172 | + long n_rp_need_nothing; | |
166 | 173 | |
167 | 174 | int cpu; |
168 | 175 | }; |
kernel/rcutree.c
... | ... | @@ -1259,31 +1259,44 @@ |
1259 | 1259 | check_cpu_stall(rsp, rdp); |
1260 | 1260 | |
1261 | 1261 | /* Is the RCU core waiting for a quiescent state from this CPU? */ |
1262 | - if (rdp->qs_pending) | |
1262 | + if (rdp->qs_pending) { | |
1263 | + rdp->n_rp_qs_pending++; | |
1263 | 1264 | return 1; |
1265 | + } | |
1264 | 1266 | |
1265 | 1267 | /* Does this CPU have callbacks ready to invoke? */ |
1266 | - if (cpu_has_callbacks_ready_to_invoke(rdp)) | |
1268 | + if (cpu_has_callbacks_ready_to_invoke(rdp)) { | |
1269 | + rdp->n_rp_cb_ready++; | |
1267 | 1270 | return 1; |
1271 | + } | |
1268 | 1272 | |
1269 | 1273 | /* Has RCU gone idle with this CPU needing another grace period? */ |
1270 | - if (cpu_needs_another_gp(rsp, rdp)) | |
1274 | + if (cpu_needs_another_gp(rsp, rdp)) { | |
1275 | + rdp->n_rp_cpu_needs_gp++; | |
1271 | 1276 | return 1; |
1277 | + } | |
1272 | 1278 | |
1273 | 1279 | /* Has another RCU grace period completed? */ |
1274 | - if (ACCESS_ONCE(rsp->completed) != rdp->completed) /* outside of lock */ | |
1280 | + if (ACCESS_ONCE(rsp->completed) != rdp->completed) { /* outside lock */ | |
1281 | + rdp->n_rp_gp_completed++; | |
1275 | 1282 | return 1; |
1283 | + } | |
1276 | 1284 | |
1277 | 1285 | /* Has a new RCU grace period started? */ |
1278 | - if (ACCESS_ONCE(rsp->gpnum) != rdp->gpnum) /* outside of lock */ | |
1286 | + if (ACCESS_ONCE(rsp->gpnum) != rdp->gpnum) { /* outside lock */ | |
1287 | + rdp->n_rp_gp_started++; | |
1279 | 1288 | return 1; |
1289 | + } | |
1280 | 1290 | |
1281 | 1291 | /* Has an RCU GP gone long enough to send resched IPIs &c? */ |
1282 | 1292 | if (ACCESS_ONCE(rsp->completed) != ACCESS_ONCE(rsp->gpnum) && |
1283 | - ((long)(ACCESS_ONCE(rsp->jiffies_force_qs) - jiffies) < 0)) | |
1293 | + ((long)(ACCESS_ONCE(rsp->jiffies_force_qs) - jiffies) < 0)) { | |
1294 | + rdp->n_rp_need_fqs++; | |
1284 | 1295 | return 1; |
1296 | + } | |
1285 | 1297 | |
1286 | 1298 | /* nothing to do */ |
1299 | + rdp->n_rp_need_nothing++; | |
1287 | 1300 | return 0; |
1288 | 1301 | } |
1289 | 1302 |
kernel/rcutree_trace.c
... | ... | @@ -213,7 +213,63 @@ |
213 | 213 | .release = single_release, |
214 | 214 | }; |
215 | 215 | |
216 | -static struct dentry *rcudir, *datadir, *datadir_csv, *hierdir, *gpdir; | |
216 | +static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp) | |
217 | +{ | |
218 | + seq_printf(m, "%3d%cnp=%ld " | |
219 | + "qsp=%ld cbr=%ld cng=%ld gpc=%ld gps=%ld nf=%ld nn=%ld\n", | |
220 | + rdp->cpu, | |
221 | + cpu_is_offline(rdp->cpu) ? '!' : ' ', | |
222 | + rdp->n_rcu_pending, | |
223 | + rdp->n_rp_qs_pending, | |
224 | + rdp->n_rp_cb_ready, | |
225 | + rdp->n_rp_cpu_needs_gp, | |
226 | + rdp->n_rp_gp_completed, | |
227 | + rdp->n_rp_gp_started, | |
228 | + rdp->n_rp_need_fqs, | |
229 | + rdp->n_rp_need_nothing); | |
230 | +} | |
231 | + | |
232 | +static void print_rcu_pendings(struct seq_file *m, struct rcu_state *rsp) | |
233 | +{ | |
234 | + int cpu; | |
235 | + struct rcu_data *rdp; | |
236 | + | |
237 | + for_each_possible_cpu(cpu) { | |
238 | + rdp = rsp->rda[cpu]; | |
239 | + if (rdp->beenonline) | |
240 | + print_one_rcu_pending(m, rdp); | |
241 | + } | |
242 | +} | |
243 | + | |
244 | +static int show_rcu_pending(struct seq_file *m, void *unused) | |
245 | +{ | |
246 | + seq_puts(m, "rcu:\n"); | |
247 | + print_rcu_pendings(m, &rcu_state); | |
248 | + seq_puts(m, "rcu_bh:\n"); | |
249 | + print_rcu_pendings(m, &rcu_bh_state); | |
250 | + return 0; | |
251 | +} | |
252 | + | |
253 | +static int rcu_pending_open(struct inode *inode, struct file *file) | |
254 | +{ | |
255 | + return single_open(file, show_rcu_pending, NULL); | |
256 | +} | |
257 | + | |
258 | +static struct file_operations rcu_pending_fops = { | |
259 | + .owner = THIS_MODULE, | |
260 | + .open = rcu_pending_open, | |
261 | + .read = seq_read, | |
262 | + .llseek = seq_lseek, | |
263 | + .release = single_release, | |
264 | +}; | |
265 | + | |
266 | +static struct dentry *rcudir; | |
267 | +static struct dentry *datadir; | |
268 | +static struct dentry *datadir_csv; | |
269 | +static struct dentry *gpdir; | |
270 | +static struct dentry *hierdir; | |
271 | +static struct dentry *rcu_pendingdir; | |
272 | + | |
217 | 273 | static int __init rcuclassic_trace_init(void) |
218 | 274 | { |
219 | 275 | rcudir = debugfs_create_dir("rcu", NULL); |
... | ... | @@ -238,6 +294,11 @@ |
238 | 294 | NULL, &rcuhier_fops); |
239 | 295 | if (!hierdir) |
240 | 296 | goto free_out; |
297 | + | |
298 | + rcu_pendingdir = debugfs_create_file("rcu_pending", 0444, rcudir, | |
299 | + NULL, &rcu_pending_fops); | |
300 | + if (!rcu_pendingdir) | |
301 | + goto free_out; | |
241 | 302 | return 0; |
242 | 303 | free_out: |
243 | 304 | if (datadir) |
... | ... | @@ -257,6 +318,7 @@ |
257 | 318 | debugfs_remove(datadir_csv); |
258 | 319 | debugfs_remove(gpdir); |
259 | 320 | debugfs_remove(hierdir); |
321 | + debugfs_remove(rcu_pendingdir); | |
260 | 322 | debugfs_remove(rcudir); |
261 | 323 | } |
262 | 324 |