diff options
| -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++) { |
