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 | 
