aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutorture.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/rcutorture.c')
-rw-r--r--kernel/rcutorture.c34
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
491static void rcu_sched_torture_deferred_free(struct rcu_torture *p)
492{
493 call_rcu_sched(&p->rtort_rcu, rcu_torture_cb);
494}
495
485static void sched_torture_synchronize(void) 496static 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
515static 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++) {