diff options
Diffstat (limited to 'kernel/rcutiny.c')
-rw-r--r-- | kernel/rcutiny.c | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c index 9f6d9ff2572c..196ec02f8be0 100644 --- a/kernel/rcutiny.c +++ b/kernel/rcutiny.c | |||
@@ -44,9 +44,9 @@ struct rcu_ctrlblk { | |||
44 | }; | 44 | }; |
45 | 45 | ||
46 | /* Definition for rcupdate control block. */ | 46 | /* Definition for rcupdate control block. */ |
47 | static struct rcu_ctrlblk rcu_ctrlblk = { | 47 | static struct rcu_ctrlblk rcu_sched_ctrlblk = { |
48 | .donetail = &rcu_ctrlblk.rcucblist, | 48 | .donetail = &rcu_sched_ctrlblk.rcucblist, |
49 | .curtail = &rcu_ctrlblk.rcucblist, | 49 | .curtail = &rcu_sched_ctrlblk.rcucblist, |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static struct rcu_ctrlblk rcu_bh_ctrlblk = { | 52 | static struct rcu_ctrlblk rcu_bh_ctrlblk = { |
@@ -54,6 +54,11 @@ static struct rcu_ctrlblk rcu_bh_ctrlblk = { | |||
54 | .curtail = &rcu_bh_ctrlblk.rcucblist, | 54 | .curtail = &rcu_bh_ctrlblk.rcucblist, |
55 | }; | 55 | }; |
56 | 56 | ||
57 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
58 | int rcu_scheduler_active __read_mostly; | ||
59 | EXPORT_SYMBOL_GPL(rcu_scheduler_active); | ||
60 | #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ | ||
61 | |||
57 | #ifdef CONFIG_NO_HZ | 62 | #ifdef CONFIG_NO_HZ |
58 | 63 | ||
59 | static long rcu_dynticks_nesting = 1; | 64 | static long rcu_dynticks_nesting = 1; |
@@ -108,7 +113,8 @@ static int rcu_qsctr_help(struct rcu_ctrlblk *rcp) | |||
108 | */ | 113 | */ |
109 | void rcu_sched_qs(int cpu) | 114 | void rcu_sched_qs(int cpu) |
110 | { | 115 | { |
111 | if (rcu_qsctr_help(&rcu_ctrlblk) + rcu_qsctr_help(&rcu_bh_ctrlblk)) | 116 | if (rcu_qsctr_help(&rcu_sched_ctrlblk) + |
117 | rcu_qsctr_help(&rcu_bh_ctrlblk)) | ||
112 | raise_softirq(RCU_SOFTIRQ); | 118 | raise_softirq(RCU_SOFTIRQ); |
113 | } | 119 | } |
114 | 120 | ||
@@ -163,6 +169,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) | |||
163 | while (list) { | 169 | while (list) { |
164 | next = list->next; | 170 | next = list->next; |
165 | prefetch(next); | 171 | prefetch(next); |
172 | debug_rcu_head_unqueue(list); | ||
166 | list->func(list); | 173 | list->func(list); |
167 | list = next; | 174 | list = next; |
168 | } | 175 | } |
@@ -173,7 +180,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) | |||
173 | */ | 180 | */ |
174 | static void rcu_process_callbacks(struct softirq_action *unused) | 181 | static void rcu_process_callbacks(struct softirq_action *unused) |
175 | { | 182 | { |
176 | __rcu_process_callbacks(&rcu_ctrlblk); | 183 | __rcu_process_callbacks(&rcu_sched_ctrlblk); |
177 | __rcu_process_callbacks(&rcu_bh_ctrlblk); | 184 | __rcu_process_callbacks(&rcu_bh_ctrlblk); |
178 | } | 185 | } |
179 | 186 | ||
@@ -187,7 +194,8 @@ static void rcu_process_callbacks(struct softirq_action *unused) | |||
187 | * | 194 | * |
188 | * Cool, huh? (Due to Josh Triplett.) | 195 | * Cool, huh? (Due to Josh Triplett.) |
189 | * | 196 | * |
190 | * But we want to make this a static inline later. | 197 | * But we want to make this a static inline later. The cond_resched() |
198 | * currently makes this problematic. | ||
191 | */ | 199 | */ |
192 | void synchronize_sched(void) | 200 | void synchronize_sched(void) |
193 | { | 201 | { |
@@ -195,12 +203,6 @@ void synchronize_sched(void) | |||
195 | } | 203 | } |
196 | EXPORT_SYMBOL_GPL(synchronize_sched); | 204 | EXPORT_SYMBOL_GPL(synchronize_sched); |
197 | 205 | ||
198 | void synchronize_rcu_bh(void) | ||
199 | { | ||
200 | synchronize_sched(); | ||
201 | } | ||
202 | EXPORT_SYMBOL_GPL(synchronize_rcu_bh); | ||
203 | |||
204 | /* | 206 | /* |
205 | * Helper function for call_rcu() and call_rcu_bh(). | 207 | * Helper function for call_rcu() and call_rcu_bh(). |
206 | */ | 208 | */ |
@@ -210,6 +212,7 @@ static void __call_rcu(struct rcu_head *head, | |||
210 | { | 212 | { |
211 | unsigned long flags; | 213 | unsigned long flags; |
212 | 214 | ||
215 | debug_rcu_head_queue(head); | ||
213 | head->func = func; | 216 | head->func = func; |
214 | head->next = NULL; | 217 | head->next = NULL; |
215 | 218 | ||
@@ -226,7 +229,7 @@ static void __call_rcu(struct rcu_head *head, | |||
226 | */ | 229 | */ |
227 | void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)) | 230 | void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)) |
228 | { | 231 | { |
229 | __call_rcu(head, func, &rcu_ctrlblk); | 232 | __call_rcu(head, func, &rcu_sched_ctrlblk); |
230 | } | 233 | } |
231 | EXPORT_SYMBOL_GPL(call_rcu); | 234 | EXPORT_SYMBOL_GPL(call_rcu); |
232 | 235 | ||
@@ -244,11 +247,13 @@ void rcu_barrier(void) | |||
244 | { | 247 | { |
245 | struct rcu_synchronize rcu; | 248 | struct rcu_synchronize rcu; |
246 | 249 | ||
250 | init_rcu_head_on_stack(&rcu.head); | ||
247 | init_completion(&rcu.completion); | 251 | init_completion(&rcu.completion); |
248 | /* Will wake me after RCU finished. */ | 252 | /* Will wake me after RCU finished. */ |
249 | call_rcu(&rcu.head, wakeme_after_rcu); | 253 | call_rcu(&rcu.head, wakeme_after_rcu); |
250 | /* Wait for it. */ | 254 | /* Wait for it. */ |
251 | wait_for_completion(&rcu.completion); | 255 | wait_for_completion(&rcu.completion); |
256 | destroy_rcu_head_on_stack(&rcu.head); | ||
252 | } | 257 | } |
253 | EXPORT_SYMBOL_GPL(rcu_barrier); | 258 | EXPORT_SYMBOL_GPL(rcu_barrier); |
254 | 259 | ||
@@ -256,11 +261,13 @@ void rcu_barrier_bh(void) | |||
256 | { | 261 | { |
257 | struct rcu_synchronize rcu; | 262 | struct rcu_synchronize rcu; |
258 | 263 | ||
264 | init_rcu_head_on_stack(&rcu.head); | ||
259 | init_completion(&rcu.completion); | 265 | init_completion(&rcu.completion); |
260 | /* Will wake me after RCU finished. */ | 266 | /* Will wake me after RCU finished. */ |
261 | call_rcu_bh(&rcu.head, wakeme_after_rcu); | 267 | call_rcu_bh(&rcu.head, wakeme_after_rcu); |
262 | /* Wait for it. */ | 268 | /* Wait for it. */ |
263 | wait_for_completion(&rcu.completion); | 269 | wait_for_completion(&rcu.completion); |
270 | destroy_rcu_head_on_stack(&rcu.head); | ||
264 | } | 271 | } |
265 | EXPORT_SYMBOL_GPL(rcu_barrier_bh); | 272 | EXPORT_SYMBOL_GPL(rcu_barrier_bh); |
266 | 273 | ||
@@ -268,11 +275,13 @@ void rcu_barrier_sched(void) | |||
268 | { | 275 | { |
269 | struct rcu_synchronize rcu; | 276 | struct rcu_synchronize rcu; |
270 | 277 | ||
278 | init_rcu_head_on_stack(&rcu.head); | ||
271 | init_completion(&rcu.completion); | 279 | init_completion(&rcu.completion); |
272 | /* Will wake me after RCU finished. */ | 280 | /* Will wake me after RCU finished. */ |
273 | call_rcu_sched(&rcu.head, wakeme_after_rcu); | 281 | call_rcu_sched(&rcu.head, wakeme_after_rcu); |
274 | /* Wait for it. */ | 282 | /* Wait for it. */ |
275 | wait_for_completion(&rcu.completion); | 283 | wait_for_completion(&rcu.completion); |
284 | destroy_rcu_head_on_stack(&rcu.head); | ||
276 | } | 285 | } |
277 | EXPORT_SYMBOL_GPL(rcu_barrier_sched); | 286 | EXPORT_SYMBOL_GPL(rcu_barrier_sched); |
278 | 287 | ||
@@ -280,3 +289,5 @@ void __init rcu_init(void) | |||
280 | { | 289 | { |
281 | open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); | 290 | open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); |
282 | } | 291 | } |
292 | |||
293 | #include "rcutiny_plugin.h" | ||