Commit 7ba5c840e64d4a967379f1ae3eca73278180b11d

Authored by Paul E. McKenney
Committed by Ingo Molnar
1 parent 05cfbd66d0

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 };
... ... @@ -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