diff options
-rw-r--r-- | include/linux/rcupdate.h | 1 | ||||
-rw-r--r-- | kernel/rcupdate.c | 10 | ||||
-rw-r--r-- | kernel/rcutorture.c | 40 |
3 files changed, 49 insertions, 2 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 6312758393b6..48dfe00070c7 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
@@ -258,6 +258,7 @@ extern void rcu_init(void); | |||
258 | extern void rcu_check_callbacks(int cpu, int user); | 258 | extern void rcu_check_callbacks(int cpu, int user); |
259 | extern void rcu_restart_cpu(int cpu); | 259 | extern void rcu_restart_cpu(int cpu); |
260 | extern long rcu_batches_completed(void); | 260 | extern long rcu_batches_completed(void); |
261 | extern long rcu_batches_completed_bh(void); | ||
261 | 262 | ||
262 | /* Exported interfaces */ | 263 | /* Exported interfaces */ |
263 | extern void FASTCALL(call_rcu(struct rcu_head *head, | 264 | extern void FASTCALL(call_rcu(struct rcu_head *head, |
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 20e9710fc21c..c0e1cb95dd4f 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
@@ -182,6 +182,15 @@ long rcu_batches_completed(void) | |||
182 | return rcu_ctrlblk.completed; | 182 | return rcu_ctrlblk.completed; |
183 | } | 183 | } |
184 | 184 | ||
185 | /* | ||
186 | * Return the number of RCU batches processed thus far. Useful | ||
187 | * for debug and statistics. | ||
188 | */ | ||
189 | long rcu_batches_completed_bh(void) | ||
190 | { | ||
191 | return rcu_bh_ctrlblk.completed; | ||
192 | } | ||
193 | |||
185 | static void rcu_barrier_callback(struct rcu_head *notused) | 194 | static void rcu_barrier_callback(struct rcu_head *notused) |
186 | { | 195 | { |
187 | if (atomic_dec_and_test(&rcu_barrier_cpu_count)) | 196 | if (atomic_dec_and_test(&rcu_barrier_cpu_count)) |
@@ -619,6 +628,7 @@ module_param(qlowmark, int, 0); | |||
619 | module_param(rsinterval, int, 0); | 628 | module_param(rsinterval, int, 0); |
620 | #endif | 629 | #endif |
621 | EXPORT_SYMBOL_GPL(rcu_batches_completed); | 630 | EXPORT_SYMBOL_GPL(rcu_batches_completed); |
631 | EXPORT_SYMBOL_GPL(rcu_batches_completed_bh); | ||
622 | EXPORT_SYMBOL_GPL(call_rcu); | 632 | EXPORT_SYMBOL_GPL(call_rcu); |
623 | EXPORT_SYMBOL_GPL(call_rcu_bh); | 633 | EXPORT_SYMBOL_GPL(call_rcu_bh); |
624 | EXPORT_SYMBOL_GPL(synchronize_rcu); | 634 | EXPORT_SYMBOL_GPL(synchronize_rcu); |
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index c96b5edd6ed1..4d1c3d247127 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c | |||
@@ -66,7 +66,7 @@ MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs"); | |||
66 | module_param(shuffle_interval, int, 0); | 66 | module_param(shuffle_interval, int, 0); |
67 | MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles"); | 67 | MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles"); |
68 | module_param(torture_type, charp, 0); | 68 | module_param(torture_type, charp, 0); |
69 | MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu)"); | 69 | MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh)"); |
70 | 70 | ||
71 | #define TORTURE_FLAG "-torture:" | 71 | #define TORTURE_FLAG "-torture:" |
72 | #define PRINTK_STRING(s) \ | 72 | #define PRINTK_STRING(s) \ |
@@ -246,8 +246,44 @@ static struct rcu_torture_ops rcu_ops = { | |||
246 | .name = "rcu" | 246 | .name = "rcu" |
247 | }; | 247 | }; |
248 | 248 | ||
249 | /* | ||
250 | * Definitions for rcu_bh torture testing. | ||
251 | */ | ||
252 | |||
253 | static int rcu_bh_torture_read_lock(void) | ||
254 | { | ||
255 | rcu_read_lock_bh(); | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static void rcu_bh_torture_read_unlock(int idx) | ||
260 | { | ||
261 | rcu_read_unlock_bh(); | ||
262 | } | ||
263 | |||
264 | static int rcu_bh_torture_completed(void) | ||
265 | { | ||
266 | return rcu_batches_completed_bh(); | ||
267 | } | ||
268 | |||
269 | static void rcu_bh_torture_deferred_free(struct rcu_torture *p) | ||
270 | { | ||
271 | call_rcu_bh(&p->rtort_rcu, rcu_torture_cb); | ||
272 | } | ||
273 | |||
274 | static struct rcu_torture_ops rcu_bh_ops = { | ||
275 | .init = NULL, | ||
276 | .cleanup = NULL, | ||
277 | .readlock = rcu_bh_torture_read_lock, | ||
278 | .readunlock = rcu_bh_torture_read_unlock, | ||
279 | .completed = rcu_bh_torture_completed, | ||
280 | .deferredfree = rcu_bh_torture_deferred_free, | ||
281 | .stats = NULL, | ||
282 | .name = "rcu_bh" | ||
283 | }; | ||
284 | |||
249 | static struct rcu_torture_ops *torture_ops[] = | 285 | static struct rcu_torture_ops *torture_ops[] = |
250 | { &rcu_ops, NULL }; | 286 | { &rcu_ops, &rcu_bh_ops, NULL }; |
251 | 287 | ||
252 | /* | 288 | /* |
253 | * RCU torture writer kthread. Repeatedly substitutes a new structure | 289 | * RCU torture writer kthread. Repeatedly substitutes a new structure |