aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);