aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2011-02-22 16:42:43 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2011-05-06 02:16:55 -0400
commit0ea1f2ebeb217d38770aebf91c4ecaa8e01b3305 (patch)
treeef558d2eb804ca033a5166d24f5b4be7cf87727f
parent67b98dba474f293c389fc2b7254dcf7c0492e3bd (diff)
rcu: Add boosting to TREE_PREEMPT_RCU tracing
Includes total number of tasks boosted, number boosted on behalf of each of normal and expedited grace periods, and statistics on attempts to initiate boosting that failed for various reasons. Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
-rw-r--r--kernel/rcutree.h19
-rw-r--r--kernel/rcutree_plugin.h42
-rw-r--r--kernel/rcutree_trace.c68
3 files changed, 125 insertions, 4 deletions
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index 8db0cdc7f450..d49046c79c59 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -152,6 +152,25 @@ struct rcu_node {
152 wait_queue_head_t boost_wq; 152 wait_queue_head_t boost_wq;
153 /* Wait queue on which to park the boost */ 153 /* Wait queue on which to park the boost */
154 /* kthread. */ 154 /* kthread. */
155 unsigned long n_tasks_boosted;
156 /* Total number of tasks boosted. */
157 unsigned long n_exp_boosts;
158 /* Number of tasks boosted for expedited GP. */
159 unsigned long n_normal_boosts;
160 /* Number of tasks boosted for normal GP. */
161 unsigned long n_balk_blkd_tasks;
162 /* Refused to boost: no blocked tasks. */
163 unsigned long n_balk_exp_gp_tasks;
164 /* Refused to boost: nothing blocking GP. */
165 unsigned long n_balk_boost_tasks;
166 /* Refused to boost: already boosting. */
167 unsigned long n_balk_notblocked;
168 /* Refused to boost: RCU RS CS still running. */
169 unsigned long n_balk_notyet;
170 /* Refused to boost: not yet time. */
171 unsigned long n_balk_nos;
172 /* Refused to boost: not sure why, though. */
173 /* This can happen due to race conditions. */
155#endif /* #ifdef CONFIG_RCU_BOOST */ 174#endif /* #ifdef CONFIG_RCU_BOOST */
156 struct task_struct *node_kthread_task; 175 struct task_struct *node_kthread_task;
157 /* kthread that takes care of this rcu_node */ 176 /* kthread that takes care of this rcu_node */
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 4e486255df63..07d346445d12 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -1073,6 +1073,33 @@ static void __init __rcu_init_preempt(void)
1073 1073
1074#include "rtmutex_common.h" 1074#include "rtmutex_common.h"
1075 1075
1076#ifdef CONFIG_RCU_TRACE
1077
1078static void rcu_initiate_boost_trace(struct rcu_node *rnp)
1079{
1080 if (list_empty(&rnp->blkd_tasks))
1081 rnp->n_balk_blkd_tasks++;
1082 else if (rnp->exp_tasks == NULL && rnp->gp_tasks == NULL)
1083 rnp->n_balk_exp_gp_tasks++;
1084 else if (rnp->gp_tasks != NULL && rnp->boost_tasks != NULL)
1085 rnp->n_balk_boost_tasks++;
1086 else if (rnp->gp_tasks != NULL && rnp->qsmask != 0)
1087 rnp->n_balk_notblocked++;
1088 else if (rnp->gp_tasks != NULL &&
1089 ULONG_CMP_GE(jiffies, rnp->boost_time))
1090 rnp->n_balk_notyet++;
1091 else
1092 rnp->n_balk_nos++;
1093}
1094
1095#else /* #ifdef CONFIG_RCU_TRACE */
1096
1097static void rcu_initiate_boost_trace(struct rcu_node *rnp)
1098{
1099}
1100
1101#endif /* #else #ifdef CONFIG_RCU_TRACE */
1102
1076/* 1103/*
1077 * Carry out RCU priority boosting on the task indicated by ->exp_tasks 1104 * Carry out RCU priority boosting on the task indicated by ->exp_tasks
1078 * or ->boost_tasks, advancing the pointer to the next task in the 1105 * or ->boost_tasks, advancing the pointer to the next task in the
@@ -1108,10 +1135,14 @@ static int rcu_boost(struct rcu_node *rnp)
1108 * expedited grace period must boost all blocked tasks, including 1135 * expedited grace period must boost all blocked tasks, including
1109 * those blocking the pre-existing normal grace period. 1136 * those blocking the pre-existing normal grace period.
1110 */ 1137 */
1111 if (rnp->exp_tasks != NULL) 1138 if (rnp->exp_tasks != NULL) {
1112 tb = rnp->exp_tasks; 1139 tb = rnp->exp_tasks;
1113 else 1140 rnp->n_exp_boosts++;
1141 } else {
1114 tb = rnp->boost_tasks; 1142 tb = rnp->boost_tasks;
1143 rnp->n_normal_boosts++;
1144 }
1145 rnp->n_tasks_boosted++;
1115 1146
1116 /* 1147 /*
1117 * We boost task t by manufacturing an rt_mutex that appears to 1148 * We boost task t by manufacturing an rt_mutex that appears to
@@ -1197,8 +1228,10 @@ static void rcu_initiate_boost(struct rcu_node *rnp)
1197{ 1228{
1198 struct task_struct *t; 1229 struct task_struct *t;
1199 1230
1200 if (!rcu_preempt_blocked_readers_cgp(rnp) && rnp->exp_tasks == NULL) 1231 if (!rcu_preempt_blocked_readers_cgp(rnp) && rnp->exp_tasks == NULL) {
1232 rnp->n_balk_exp_gp_tasks++;
1201 return; 1233 return;
1234 }
1202 if (rnp->exp_tasks != NULL || 1235 if (rnp->exp_tasks != NULL ||
1203 (rnp->gp_tasks != NULL && 1236 (rnp->gp_tasks != NULL &&
1204 rnp->boost_tasks == NULL && 1237 rnp->boost_tasks == NULL &&
@@ -1209,7 +1242,8 @@ static void rcu_initiate_boost(struct rcu_node *rnp)
1209 t = rnp->boost_kthread_task; 1242 t = rnp->boost_kthread_task;
1210 if (t != NULL) 1243 if (t != NULL)
1211 wake_up_process(t); 1244 wake_up_process(t);
1212 } 1245 } else
1246 rcu_initiate_boost_trace(rnp);
1213} 1247}
1214 1248
1215/* 1249/*
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c
index 1cedf94e2c4f..ead5736f99b5 100644
--- a/kernel/rcutree_trace.c
+++ b/kernel/rcutree_trace.c
@@ -157,6 +157,71 @@ static const struct file_operations rcudata_csv_fops = {
157 .release = single_release, 157 .release = single_release,
158}; 158};
159 159
160#ifdef CONFIG_RCU_BOOST
161
162static void print_one_rcu_node_boost(struct seq_file *m, struct rcu_node *rnp)
163{
164 seq_printf(m, "%d:%d tasks=%c%c%c%c ntb=%lu neb=%lu nnb=%lu "
165 "j=%04x bt=%04x\n",
166 rnp->grplo, rnp->grphi,
167 "T."[list_empty(&rnp->blkd_tasks)],
168 "N."[!rnp->gp_tasks],
169 "E."[!rnp->exp_tasks],
170 "B."[!rnp->boost_tasks],
171 rnp->n_tasks_boosted, rnp->n_exp_boosts,
172 rnp->n_normal_boosts,
173 (int)(jiffies & 0xffff),
174 (int)(rnp->boost_time & 0xffff));
175 seq_printf(m, "%s: nt=%lu egt=%lu bt=%lu nb=%lu ny=%lu nos=%lu\n",
176 " balk",
177 rnp->n_balk_blkd_tasks,
178 rnp->n_balk_exp_gp_tasks,
179 rnp->n_balk_boost_tasks,
180 rnp->n_balk_notblocked,
181 rnp->n_balk_notyet,
182 rnp->n_balk_nos);
183}
184
185static int show_rcu_node_boost(struct seq_file *m, void *unused)
186{
187 struct rcu_node *rnp;
188
189 rcu_for_each_leaf_node(&rcu_preempt_state, rnp)
190 print_one_rcu_node_boost(m, rnp);
191 return 0;
192}
193
194static int rcu_node_boost_open(struct inode *inode, struct file *file)
195{
196 return single_open(file, show_rcu_node_boost, NULL);
197}
198
199static const struct file_operations rcu_node_boost_fops = {
200 .owner = THIS_MODULE,
201 .open = rcu_node_boost_open,
202 .read = seq_read,
203 .llseek = seq_lseek,
204 .release = single_release,
205};
206
207/*
208 * Create the rcuboost debugfs entry. Standard error return.
209 */
210static int rcu_boost_trace_create_file(struct dentry *rcudir)
211{
212 return !debugfs_create_file("rcuboost", 0444, rcudir, NULL,
213 &rcu_node_boost_fops);
214}
215
216#else /* #ifdef CONFIG_RCU_BOOST */
217
218static int rcu_boost_trace_create_file(struct dentry *rcudir)
219{
220 return 0; /* There cannot be an error if we didn't create it! */
221}
222
223#endif /* #else #ifdef CONFIG_RCU_BOOST */
224
160static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp) 225static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
161{ 226{
162 unsigned long gpnum; 227 unsigned long gpnum;
@@ -315,6 +380,9 @@ static int __init rcutree_trace_init(void)
315 if (!retval) 380 if (!retval)
316 goto free_out; 381 goto free_out;
317 382
383 if (rcu_boost_trace_create_file(rcudir))
384 goto free_out;
385
318 retval = debugfs_create_file("rcugp", 0444, rcudir, NULL, &rcugp_fops); 386 retval = debugfs_create_file("rcugp", 0444, rcudir, NULL, &rcugp_fops);
319 if (!retval) 387 if (!retval)
320 goto free_out; 388 goto free_out;