diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2011-05-20 20:06:24 +0200 | 
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2011-05-20 20:08:05 +0200 | 
| commit | 250f972d85effad5b6e10da4bbd877e6a4b503b6 (patch) | |
| tree | 007393a6fc6439af7e0121dd99a6f9f9fb8405bc /kernel/rcutree_trace.c | |
| parent | 7372b0b122af0f6675f3ab65bfd91c8a438e0480 (diff) | |
| parent | bbe7b8bef48c567f5ff3f6041c1fb011292e8f12 (diff) | |
| download | olio-linux-3.10-250f972d85effad5b6e10da4bbd877e6a4b503b6.tar.xz olio-linux-3.10-250f972d85effad5b6e10da4bbd877e6a4b503b6.zip  | |
Merge branch 'timers/urgent' into timers/core
Reason: Get upstream fixes and kfree_rcu which is necessary for a
follow up patch.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/rcutree_trace.c')
| -rw-r--r-- | kernel/rcutree_trace.c | 180 | 
1 files changed, 165 insertions, 15 deletions
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c index c8e97853b97..aa0fd72b4bc 100644 --- a/kernel/rcutree_trace.c +++ b/kernel/rcutree_trace.c @@ -46,6 +46,18 @@  #define RCU_TREE_NONCORE  #include "rcutree.h" +DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status); +DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_cpu); +DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_loops); +DECLARE_PER_CPU(char, rcu_cpu_has_work); + +static char convert_kthread_status(unsigned int kthread_status) +{ +	if (kthread_status > RCU_KTHREAD_MAX) +		return '?'; +	return "SRWOY"[kthread_status]; +} +  static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)  {  	if (!rdp->beenonline) @@ -64,7 +76,21 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)  		   rdp->dynticks_fqs);  #endif /* #ifdef CONFIG_NO_HZ */  	seq_printf(m, " of=%lu ri=%lu", rdp->offline_fqs, rdp->resched_ipi); -	seq_printf(m, " ql=%ld b=%ld", rdp->qlen, rdp->blimit); +	seq_printf(m, " ql=%ld qs=%c%c%c%c kt=%d/%c/%d ktl=%x b=%ld", +		   rdp->qlen, +		   ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != +			rdp->nxttail[RCU_NEXT_TAIL]], +		   ".R"[rdp->nxttail[RCU_WAIT_TAIL] != +			rdp->nxttail[RCU_NEXT_READY_TAIL]], +		   ".W"[rdp->nxttail[RCU_DONE_TAIL] != +			rdp->nxttail[RCU_WAIT_TAIL]], +		   ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]], +		   per_cpu(rcu_cpu_has_work, rdp->cpu), +		   convert_kthread_status(per_cpu(rcu_cpu_kthread_status, +					  rdp->cpu)), +		   per_cpu(rcu_cpu_kthread_cpu, rdp->cpu), +		   per_cpu(rcu_cpu_kthread_loops, rdp->cpu) & 0xffff, +		   rdp->blimit);  	seq_printf(m, " ci=%lu co=%lu ca=%lu\n",  		   rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);  } @@ -121,7 +147,18 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp)  		   rdp->dynticks_fqs);  #endif /* #ifdef CONFIG_NO_HZ */  	seq_printf(m, ",%lu,%lu", rdp->offline_fqs, rdp->resched_ipi); -	seq_printf(m, ",%ld,%ld", rdp->qlen, rdp->blimit); +	seq_printf(m, ",%ld,\"%c%c%c%c\",%d,\"%c\",%ld", rdp->qlen, +		   ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != +			rdp->nxttail[RCU_NEXT_TAIL]], +		   ".R"[rdp->nxttail[RCU_WAIT_TAIL] != +			rdp->nxttail[RCU_NEXT_READY_TAIL]], +		   ".W"[rdp->nxttail[RCU_DONE_TAIL] != +			rdp->nxttail[RCU_WAIT_TAIL]], +		   ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]], +		   per_cpu(rcu_cpu_has_work, rdp->cpu), +		   convert_kthread_status(per_cpu(rcu_cpu_kthread_status, +					  rdp->cpu)), +		   rdp->blimit);  	seq_printf(m, ",%lu,%lu,%lu\n",  		   rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);  } @@ -157,11 +194,76 @@ static const struct file_operations rcudata_csv_fops = {  	.release = single_release,  }; +#ifdef CONFIG_RCU_BOOST + +static void print_one_rcu_node_boost(struct seq_file *m, struct rcu_node *rnp) +{ +	seq_printf(m,  "%d:%d tasks=%c%c%c%c kt=%c ntb=%lu neb=%lu nnb=%lu " +		   "j=%04x bt=%04x\n", +		   rnp->grplo, rnp->grphi, +		   "T."[list_empty(&rnp->blkd_tasks)], +		   "N."[!rnp->gp_tasks], +		   "E."[!rnp->exp_tasks], +		   "B."[!rnp->boost_tasks], +		   convert_kthread_status(rnp->boost_kthread_status), +		   rnp->n_tasks_boosted, rnp->n_exp_boosts, +		   rnp->n_normal_boosts, +		   (int)(jiffies & 0xffff), +		   (int)(rnp->boost_time & 0xffff)); +	seq_printf(m, "%s: nt=%lu egt=%lu bt=%lu nb=%lu ny=%lu nos=%lu\n", +		   "     balk", +		   rnp->n_balk_blkd_tasks, +		   rnp->n_balk_exp_gp_tasks, +		   rnp->n_balk_boost_tasks, +		   rnp->n_balk_notblocked, +		   rnp->n_balk_notyet, +		   rnp->n_balk_nos); +} + +static int show_rcu_node_boost(struct seq_file *m, void *unused) +{ +	struct rcu_node *rnp; + +	rcu_for_each_leaf_node(&rcu_preempt_state, rnp) +		print_one_rcu_node_boost(m, rnp); +	return 0; +} + +static int rcu_node_boost_open(struct inode *inode, struct file *file) +{ +	return single_open(file, show_rcu_node_boost, NULL); +} + +static const struct file_operations rcu_node_boost_fops = { +	.owner = THIS_MODULE, +	.open = rcu_node_boost_open, +	.read = seq_read, +	.llseek = seq_lseek, +	.release = single_release, +}; + +/* + * Create the rcuboost debugfs entry.  Standard error return. + */ +static int rcu_boost_trace_create_file(struct dentry *rcudir) +{ +	return !debugfs_create_file("rcuboost", 0444, rcudir, NULL, +				    &rcu_node_boost_fops); +} + +#else /* #ifdef CONFIG_RCU_BOOST */ + +static int rcu_boost_trace_create_file(struct dentry *rcudir) +{ +	return 0;  /* There cannot be an error if we didn't create it! */ +} + +#endif /* #else #ifdef CONFIG_RCU_BOOST */ +  static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)  {  	unsigned long gpnum;  	int level = 0; -	int phase;  	struct rcu_node *rnp;  	gpnum = rsp->gpnum; @@ -178,13 +280,11 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)  			seq_puts(m, "\n");  			level = rnp->level;  		} -		phase = gpnum & 0x1; -		seq_printf(m, "%lx/%lx %c%c>%c%c %d:%d ^%d    ", +		seq_printf(m, "%lx/%lx %c%c>%c %d:%d ^%d    ",  			   rnp->qsmask, rnp->qsmaskinit, -			   "T."[list_empty(&rnp->blocked_tasks[phase])], -			   "E."[list_empty(&rnp->blocked_tasks[phase + 2])], -			   "T."[list_empty(&rnp->blocked_tasks[!phase])], -			   "E."[list_empty(&rnp->blocked_tasks[!phase + 2])], +			   ".G"[rnp->gp_tasks != NULL], +			   ".E"[rnp->exp_tasks != NULL], +			   ".T"[!list_empty(&rnp->blkd_tasks)],  			   rnp->grplo, rnp->grphi, rnp->grpnum);  	}  	seq_puts(m, "\n"); @@ -216,16 +316,35 @@ static const struct file_operations rcuhier_fops = {  	.release = single_release,  }; +static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp) +{ +	unsigned long flags; +	unsigned long completed; +	unsigned long gpnum; +	unsigned long gpage; +	unsigned long gpmax; +	struct rcu_node *rnp = &rsp->node[0]; + +	raw_spin_lock_irqsave(&rnp->lock, flags); +	completed = rsp->completed; +	gpnum = rsp->gpnum; +	if (rsp->completed == rsp->gpnum) +		gpage = 0; +	else +		gpage = jiffies - rsp->gp_start; +	gpmax = rsp->gp_max; +	raw_spin_unlock_irqrestore(&rnp->lock, flags); +	seq_printf(m, "%s: completed=%ld  gpnum=%lu  age=%ld  max=%ld\n", +		   rsp->name, completed, gpnum, gpage, gpmax); +} +  static int show_rcugp(struct seq_file *m, void *unused)  {  #ifdef CONFIG_TREE_PREEMPT_RCU -	seq_printf(m, "rcu_preempt: completed=%ld  gpnum=%lu\n", -		   rcu_preempt_state.completed, rcu_preempt_state.gpnum); +	show_one_rcugp(m, &rcu_preempt_state);  #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ -	seq_printf(m, "rcu_sched: completed=%ld  gpnum=%lu\n", -		   rcu_sched_state.completed, rcu_sched_state.gpnum); -	seq_printf(m, "rcu_bh: completed=%ld  gpnum=%lu\n", -		   rcu_bh_state.completed, rcu_bh_state.gpnum); +	show_one_rcugp(m, &rcu_sched_state); +	show_one_rcugp(m, &rcu_bh_state);  	return 0;  } @@ -298,6 +417,29 @@ static const struct file_operations rcu_pending_fops = {  	.release = single_release,  }; +static int show_rcutorture(struct seq_file *m, void *unused) +{ +	seq_printf(m, "rcutorture test sequence: %lu %s\n", +		   rcutorture_testseq >> 1, +		   (rcutorture_testseq & 0x1) ? "(test in progress)" : ""); +	seq_printf(m, "rcutorture update version number: %lu\n", +		   rcutorture_vernum); +	return 0; +} + +static int rcutorture_open(struct inode *inode, struct file *file) +{ +	return single_open(file, show_rcutorture, NULL); +} + +static const struct file_operations rcutorture_fops = { +	.owner = THIS_MODULE, +	.open = rcutorture_open, +	.read = seq_read, +	.llseek = seq_lseek, +	.release = single_release, +}; +  static struct dentry *rcudir;  static int __init rcutree_trace_init(void) @@ -318,6 +460,9 @@ static int __init rcutree_trace_init(void)  	if (!retval)  		goto free_out; +	if (rcu_boost_trace_create_file(rcudir)) +		goto free_out; +  	retval = debugfs_create_file("rcugp", 0444, rcudir, NULL, &rcugp_fops);  	if (!retval)  		goto free_out; @@ -331,6 +476,11 @@ static int __init rcutree_trace_init(void)  						NULL, &rcu_pending_fops);  	if (!retval)  		goto free_out; + +	retval = debugfs_create_file("rcutorture", 0444, rcudir, +						NULL, &rcutorture_fops); +	if (!retval) +		goto free_out;  	return 0;  free_out:  	debugfs_remove_recursive(rcudir);  |