Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.31-rc1 331 lines 8.8 kB view raw
1/* 2 * Read-Copy Update tracing for classic implementation 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 * 18 * Copyright IBM Corporation, 2008 19 * 20 * Papers: http://www.rdrop.com/users/paulmck/RCU 21 * 22 * For detailed explanation of Read-Copy Update mechanism see - 23 * Documentation/RCU 24 * 25 */ 26#include <linux/types.h> 27#include <linux/kernel.h> 28#include <linux/init.h> 29#include <linux/spinlock.h> 30#include <linux/smp.h> 31#include <linux/rcupdate.h> 32#include <linux/interrupt.h> 33#include <linux/sched.h> 34#include <asm/atomic.h> 35#include <linux/bitops.h> 36#include <linux/module.h> 37#include <linux/completion.h> 38#include <linux/moduleparam.h> 39#include <linux/percpu.h> 40#include <linux/notifier.h> 41#include <linux/cpu.h> 42#include <linux/mutex.h> 43#include <linux/debugfs.h> 44#include <linux/seq_file.h> 45 46#include "rcutree.h" 47 48static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) 49{ 50 if (!rdp->beenonline) 51 return; 52 seq_printf(m, "%3d%cc=%ld g=%ld pq=%d pqc=%ld qp=%d", 53 rdp->cpu, 54 cpu_is_offline(rdp->cpu) ? '!' : ' ', 55 rdp->completed, rdp->gpnum, 56 rdp->passed_quiesc, rdp->passed_quiesc_completed, 57 rdp->qs_pending); 58#ifdef CONFIG_NO_HZ 59 seq_printf(m, " dt=%d/%d dn=%d df=%lu", 60 rdp->dynticks->dynticks, 61 rdp->dynticks->dynticks_nesting, 62 rdp->dynticks->dynticks_nmi, 63 rdp->dynticks_fqs); 64#endif /* #ifdef CONFIG_NO_HZ */ 65 seq_printf(m, " of=%lu ri=%lu", rdp->offline_fqs, rdp->resched_ipi); 66 seq_printf(m, " ql=%ld b=%ld\n", rdp->qlen, rdp->blimit); 67} 68 69#define PRINT_RCU_DATA(name, func, m) \ 70 do { \ 71 int _p_r_d_i; \ 72 \ 73 for_each_possible_cpu(_p_r_d_i) \ 74 func(m, &per_cpu(name, _p_r_d_i)); \ 75 } while (0) 76 77static int show_rcudata(struct seq_file *m, void *unused) 78{ 79 seq_puts(m, "rcu:\n"); 80 PRINT_RCU_DATA(rcu_data, print_one_rcu_data, m); 81 seq_puts(m, "rcu_bh:\n"); 82 PRINT_RCU_DATA(rcu_bh_data, print_one_rcu_data, m); 83 return 0; 84} 85 86static int rcudata_open(struct inode *inode, struct file *file) 87{ 88 return single_open(file, show_rcudata, NULL); 89} 90 91static struct file_operations rcudata_fops = { 92 .owner = THIS_MODULE, 93 .open = rcudata_open, 94 .read = seq_read, 95 .llseek = seq_lseek, 96 .release = single_release, 97}; 98 99static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp) 100{ 101 if (!rdp->beenonline) 102 return; 103 seq_printf(m, "%d,%s,%ld,%ld,%d,%ld,%d", 104 rdp->cpu, 105 cpu_is_offline(rdp->cpu) ? "\"Y\"" : "\"N\"", 106 rdp->completed, rdp->gpnum, 107 rdp->passed_quiesc, rdp->passed_quiesc_completed, 108 rdp->qs_pending); 109#ifdef CONFIG_NO_HZ 110 seq_printf(m, ",%d,%d,%d,%lu", 111 rdp->dynticks->dynticks, 112 rdp->dynticks->dynticks_nesting, 113 rdp->dynticks->dynticks_nmi, 114 rdp->dynticks_fqs); 115#endif /* #ifdef CONFIG_NO_HZ */ 116 seq_printf(m, ",%lu,%lu", rdp->offline_fqs, rdp->resched_ipi); 117 seq_printf(m, ",%ld,%ld\n", rdp->qlen, rdp->blimit); 118} 119 120static int show_rcudata_csv(struct seq_file *m, void *unused) 121{ 122 seq_puts(m, "\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pqc\",\"pq\","); 123#ifdef CONFIG_NO_HZ 124 seq_puts(m, "\"dt\",\"dt nesting\",\"dn\",\"df\","); 125#endif /* #ifdef CONFIG_NO_HZ */ 126 seq_puts(m, "\"of\",\"ri\",\"ql\",\"b\"\n"); 127 seq_puts(m, "\"rcu:\"\n"); 128 PRINT_RCU_DATA(rcu_data, print_one_rcu_data_csv, m); 129 seq_puts(m, "\"rcu_bh:\"\n"); 130 PRINT_RCU_DATA(rcu_bh_data, print_one_rcu_data_csv, m); 131 return 0; 132} 133 134static int rcudata_csv_open(struct inode *inode, struct file *file) 135{ 136 return single_open(file, show_rcudata_csv, NULL); 137} 138 139static struct file_operations rcudata_csv_fops = { 140 .owner = THIS_MODULE, 141 .open = rcudata_csv_open, 142 .read = seq_read, 143 .llseek = seq_lseek, 144 .release = single_release, 145}; 146 147static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp) 148{ 149 int level = 0; 150 struct rcu_node *rnp; 151 152 seq_printf(m, "c=%ld g=%ld s=%d jfq=%ld j=%x " 153 "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu\n", 154 rsp->completed, rsp->gpnum, rsp->signaled, 155 (long)(rsp->jiffies_force_qs - jiffies), 156 (int)(jiffies & 0xffff), 157 rsp->n_force_qs, rsp->n_force_qs_ngp, 158 rsp->n_force_qs - rsp->n_force_qs_ngp, 159 rsp->n_force_qs_lh); 160 for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < NUM_RCU_NODES; rnp++) { 161 if (rnp->level != level) { 162 seq_puts(m, "\n"); 163 level = rnp->level; 164 } 165 seq_printf(m, "%lx/%lx %d:%d ^%d ", 166 rnp->qsmask, rnp->qsmaskinit, 167 rnp->grplo, rnp->grphi, rnp->grpnum); 168 } 169 seq_puts(m, "\n"); 170} 171 172static int show_rcuhier(struct seq_file *m, void *unused) 173{ 174 seq_puts(m, "rcu:\n"); 175 print_one_rcu_state(m, &rcu_state); 176 seq_puts(m, "rcu_bh:\n"); 177 print_one_rcu_state(m, &rcu_bh_state); 178 return 0; 179} 180 181static int rcuhier_open(struct inode *inode, struct file *file) 182{ 183 return single_open(file, show_rcuhier, NULL); 184} 185 186static struct file_operations rcuhier_fops = { 187 .owner = THIS_MODULE, 188 .open = rcuhier_open, 189 .read = seq_read, 190 .llseek = seq_lseek, 191 .release = single_release, 192}; 193 194static int show_rcugp(struct seq_file *m, void *unused) 195{ 196 seq_printf(m, "rcu: completed=%ld gpnum=%ld\n", 197 rcu_state.completed, rcu_state.gpnum); 198 seq_printf(m, "rcu_bh: completed=%ld gpnum=%ld\n", 199 rcu_bh_state.completed, rcu_bh_state.gpnum); 200 return 0; 201} 202 203static int rcugp_open(struct inode *inode, struct file *file) 204{ 205 return single_open(file, show_rcugp, NULL); 206} 207 208static struct file_operations rcugp_fops = { 209 .owner = THIS_MODULE, 210 .open = rcugp_open, 211 .read = seq_read, 212 .llseek = seq_lseek, 213 .release = single_release, 214}; 215 216static 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 232static 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 244static 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 253static int rcu_pending_open(struct inode *inode, struct file *file) 254{ 255 return single_open(file, show_rcu_pending, NULL); 256} 257 258static 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 266static struct dentry *rcudir; 267static struct dentry *datadir; 268static struct dentry *datadir_csv; 269static struct dentry *gpdir; 270static struct dentry *hierdir; 271static struct dentry *rcu_pendingdir; 272 273static int __init rcuclassic_trace_init(void) 274{ 275 rcudir = debugfs_create_dir("rcu", NULL); 276 if (!rcudir) 277 goto out; 278 279 datadir = debugfs_create_file("rcudata", 0444, rcudir, 280 NULL, &rcudata_fops); 281 if (!datadir) 282 goto free_out; 283 284 datadir_csv = debugfs_create_file("rcudata.csv", 0444, rcudir, 285 NULL, &rcudata_csv_fops); 286 if (!datadir_csv) 287 goto free_out; 288 289 gpdir = debugfs_create_file("rcugp", 0444, rcudir, NULL, &rcugp_fops); 290 if (!gpdir) 291 goto free_out; 292 293 hierdir = debugfs_create_file("rcuhier", 0444, rcudir, 294 NULL, &rcuhier_fops); 295 if (!hierdir) 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; 302 return 0; 303free_out: 304 if (datadir) 305 debugfs_remove(datadir); 306 if (datadir_csv) 307 debugfs_remove(datadir_csv); 308 if (gpdir) 309 debugfs_remove(gpdir); 310 debugfs_remove(rcudir); 311out: 312 return 1; 313} 314 315static void __exit rcuclassic_trace_cleanup(void) 316{ 317 debugfs_remove(datadir); 318 debugfs_remove(datadir_csv); 319 debugfs_remove(gpdir); 320 debugfs_remove(hierdir); 321 debugfs_remove(rcu_pendingdir); 322 debugfs_remove(rcudir); 323} 324 325 326module_init(rcuclassic_trace_init); 327module_exit(rcuclassic_trace_cleanup); 328 329MODULE_AUTHOR("Paul E. McKenney"); 330MODULE_DESCRIPTION("Read-Copy Update tracing for hierarchical implementation"); 331MODULE_LICENSE("GPL");