diff options
Diffstat (limited to 'kernel/rcutorture.c')
-rw-r--r-- | kernel/rcutorture.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 33acc424667e..0334b6a8baca 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c | |||
@@ -192,6 +192,7 @@ struct rcu_torture_ops { | |||
192 | int (*completed)(void); | 192 | int (*completed)(void); |
193 | void (*deferredfree)(struct rcu_torture *p); | 193 | void (*deferredfree)(struct rcu_torture *p); |
194 | void (*sync)(void); | 194 | void (*sync)(void); |
195 | void (*cb_barrier)(void); | ||
195 | int (*stats)(char *page); | 196 | int (*stats)(char *page); |
196 | char *name; | 197 | char *name; |
197 | }; | 198 | }; |
@@ -265,6 +266,7 @@ static struct rcu_torture_ops rcu_ops = { | |||
265 | .completed = rcu_torture_completed, | 266 | .completed = rcu_torture_completed, |
266 | .deferredfree = rcu_torture_deferred_free, | 267 | .deferredfree = rcu_torture_deferred_free, |
267 | .sync = synchronize_rcu, | 268 | .sync = synchronize_rcu, |
269 | .cb_barrier = rcu_barrier, | ||
268 | .stats = NULL, | 270 | .stats = NULL, |
269 | .name = "rcu" | 271 | .name = "rcu" |
270 | }; | 272 | }; |
@@ -304,6 +306,7 @@ static struct rcu_torture_ops rcu_sync_ops = { | |||
304 | .completed = rcu_torture_completed, | 306 | .completed = rcu_torture_completed, |
305 | .deferredfree = rcu_sync_torture_deferred_free, | 307 | .deferredfree = rcu_sync_torture_deferred_free, |
306 | .sync = synchronize_rcu, | 308 | .sync = synchronize_rcu, |
309 | .cb_barrier = NULL, | ||
307 | .stats = NULL, | 310 | .stats = NULL, |
308 | .name = "rcu_sync" | 311 | .name = "rcu_sync" |
309 | }; | 312 | }; |
@@ -364,6 +367,7 @@ static struct rcu_torture_ops rcu_bh_ops = { | |||
364 | .completed = rcu_bh_torture_completed, | 367 | .completed = rcu_bh_torture_completed, |
365 | .deferredfree = rcu_bh_torture_deferred_free, | 368 | .deferredfree = rcu_bh_torture_deferred_free, |
366 | .sync = rcu_bh_torture_synchronize, | 369 | .sync = rcu_bh_torture_synchronize, |
370 | .cb_barrier = rcu_barrier_bh, | ||
367 | .stats = NULL, | 371 | .stats = NULL, |
368 | .name = "rcu_bh" | 372 | .name = "rcu_bh" |
369 | }; | 373 | }; |
@@ -377,6 +381,7 @@ static struct rcu_torture_ops rcu_bh_sync_ops = { | |||
377 | .completed = rcu_bh_torture_completed, | 381 | .completed = rcu_bh_torture_completed, |
378 | .deferredfree = rcu_sync_torture_deferred_free, | 382 | .deferredfree = rcu_sync_torture_deferred_free, |
379 | .sync = rcu_bh_torture_synchronize, | 383 | .sync = rcu_bh_torture_synchronize, |
384 | .cb_barrier = NULL, | ||
380 | .stats = NULL, | 385 | .stats = NULL, |
381 | .name = "rcu_bh_sync" | 386 | .name = "rcu_bh_sync" |
382 | }; | 387 | }; |
@@ -458,6 +463,7 @@ static struct rcu_torture_ops srcu_ops = { | |||
458 | .completed = srcu_torture_completed, | 463 | .completed = srcu_torture_completed, |
459 | .deferredfree = rcu_sync_torture_deferred_free, | 464 | .deferredfree = rcu_sync_torture_deferred_free, |
460 | .sync = srcu_torture_synchronize, | 465 | .sync = srcu_torture_synchronize, |
466 | .cb_barrier = NULL, | ||
461 | .stats = srcu_torture_stats, | 467 | .stats = srcu_torture_stats, |
462 | .name = "srcu" | 468 | .name = "srcu" |
463 | }; | 469 | }; |
@@ -482,6 +488,11 @@ static int sched_torture_completed(void) | |||
482 | return 0; | 488 | return 0; |
483 | } | 489 | } |
484 | 490 | ||
491 | static void rcu_sched_torture_deferred_free(struct rcu_torture *p) | ||
492 | { | ||
493 | call_rcu_sched(&p->rtort_rcu, rcu_torture_cb); | ||
494 | } | ||
495 | |||
485 | static void sched_torture_synchronize(void) | 496 | static void sched_torture_synchronize(void) |
486 | { | 497 | { |
487 | synchronize_sched(); | 498 | synchronize_sched(); |
@@ -494,12 +505,27 @@ static struct rcu_torture_ops sched_ops = { | |||
494 | .readdelay = rcu_read_delay, /* just reuse rcu's version. */ | 505 | .readdelay = rcu_read_delay, /* just reuse rcu's version. */ |
495 | .readunlock = sched_torture_read_unlock, | 506 | .readunlock = sched_torture_read_unlock, |
496 | .completed = sched_torture_completed, | 507 | .completed = sched_torture_completed, |
497 | .deferredfree = rcu_sync_torture_deferred_free, | 508 | .deferredfree = rcu_sched_torture_deferred_free, |
498 | .sync = sched_torture_synchronize, | 509 | .sync = sched_torture_synchronize, |
510 | .cb_barrier = rcu_barrier_sched, | ||
499 | .stats = NULL, | 511 | .stats = NULL, |
500 | .name = "sched" | 512 | .name = "sched" |
501 | }; | 513 | }; |
502 | 514 | ||
515 | static struct rcu_torture_ops sched_ops_sync = { | ||
516 | .init = rcu_sync_torture_init, | ||
517 | .cleanup = NULL, | ||
518 | .readlock = sched_torture_read_lock, | ||
519 | .readdelay = rcu_read_delay, /* just reuse rcu's version. */ | ||
520 | .readunlock = sched_torture_read_unlock, | ||
521 | .completed = sched_torture_completed, | ||
522 | .deferredfree = rcu_sync_torture_deferred_free, | ||
523 | .sync = sched_torture_synchronize, | ||
524 | .cb_barrier = NULL, | ||
525 | .stats = NULL, | ||
526 | .name = "sched_sync" | ||
527 | }; | ||
528 | |||
503 | /* | 529 | /* |
504 | * RCU torture writer kthread. Repeatedly substitutes a new structure | 530 | * RCU torture writer kthread. Repeatedly substitutes a new structure |
505 | * for that pointed to by rcu_torture_current, freeing the old structure | 531 | * for that pointed to by rcu_torture_current, freeing the old structure |
@@ -848,7 +874,9 @@ rcu_torture_cleanup(void) | |||
848 | stats_task = NULL; | 874 | stats_task = NULL; |
849 | 875 | ||
850 | /* Wait for all RCU callbacks to fire. */ | 876 | /* Wait for all RCU callbacks to fire. */ |
851 | rcu_barrier(); | 877 | |
878 | if (cur_ops->cb_barrier != NULL) | ||
879 | cur_ops->cb_barrier(); | ||
852 | 880 | ||
853 | rcu_torture_stats_print(); /* -After- the stats thread is stopped! */ | 881 | rcu_torture_stats_print(); /* -After- the stats thread is stopped! */ |
854 | 882 | ||
@@ -868,7 +896,7 @@ rcu_torture_init(void) | |||
868 | int firsterr = 0; | 896 | int firsterr = 0; |
869 | static struct rcu_torture_ops *torture_ops[] = | 897 | static struct rcu_torture_ops *torture_ops[] = |
870 | { &rcu_ops, &rcu_sync_ops, &rcu_bh_ops, &rcu_bh_sync_ops, | 898 | { &rcu_ops, &rcu_sync_ops, &rcu_bh_ops, &rcu_bh_sync_ops, |
871 | &srcu_ops, &sched_ops, }; | 899 | &srcu_ops, &sched_ops, &sched_ops_sync, }; |
872 | 900 | ||
873 | /* Process args and tell the world that the torturer is on the job. */ | 901 | /* Process args and tell the world that the torturer is on the job. */ |
874 | for (i = 0; i < ARRAY_SIZE(torture_ops); i++) { | 902 | for (i = 0; i < ARRAY_SIZE(torture_ops); i++) { |