diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-01-31 14:57:43 -0500 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-02-23 12:02:54 -0500 |
commit | 628edaa5062282b6e3d76c886fd2cbccae5cb87b (patch) | |
tree | a21fe0f1b950f18859e8808b93fa4de57d05ffdd /kernel/torture.c | |
parent | fac480efcba6a9f0aea91947f151fd569538b0af (diff) |
rcutorture: Abstract stutter_wait()
Because stuttering the test load (stopping and restarting it) is useful
for non-RCU testing, this commit moves the load-stuttering functionality
to kernel/torture.c.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Diffstat (limited to 'kernel/torture.c')
-rw-r--r-- | kernel/torture.c | 87 |
1 files changed, 86 insertions, 1 deletions
diff --git a/kernel/torture.c b/kernel/torture.c index d51de3029a5c..b30c2ee78580 100644 --- a/kernel/torture.c +++ b/kernel/torture.c | |||
@@ -58,6 +58,7 @@ static bool verbose; | |||
58 | #define FULLSTOP_RMMOD 2 /* Normal rmmod of torture. */ | 58 | #define FULLSTOP_RMMOD 2 /* Normal rmmod of torture. */ |
59 | static int fullstop = FULLSTOP_RMMOD; | 59 | static int fullstop = FULLSTOP_RMMOD; |
60 | static DEFINE_MUTEX(fullstop_mutex); | 60 | static DEFINE_MUTEX(fullstop_mutex); |
61 | static int *torture_runnable; | ||
61 | 62 | ||
62 | #ifdef CONFIG_HOTPLUG_CPU | 63 | #ifdef CONFIG_HOTPLUG_CPU |
63 | 64 | ||
@@ -453,16 +454,100 @@ static struct notifier_block torture_shutdown_nb = { | |||
453 | }; | 454 | }; |
454 | 455 | ||
455 | /* | 456 | /* |
457 | * Variables for stuttering, which means to periodically pause and | ||
458 | * restart testing in order to catch bugs that appear when load is | ||
459 | * suddenly applied to or removed from the system. | ||
460 | */ | ||
461 | static struct task_struct *stutter_task; | ||
462 | static int stutter_pause_test; | ||
463 | static int stutter; | ||
464 | |||
465 | /* | ||
466 | * Block until the stutter interval ends. This must be called periodically | ||
467 | * by all running kthreads that need to be subject to stuttering. | ||
468 | */ | ||
469 | void stutter_wait(const char *title) | ||
470 | { | ||
471 | while (ACCESS_ONCE(stutter_pause_test) || | ||
472 | (torture_runnable && !ACCESS_ONCE(*torture_runnable))) { | ||
473 | if (stutter_pause_test) | ||
474 | schedule_timeout_interruptible(1); | ||
475 | else | ||
476 | schedule_timeout_interruptible(round_jiffies_relative(HZ)); | ||
477 | torture_shutdown_absorb(title); | ||
478 | } | ||
479 | } | ||
480 | EXPORT_SYMBOL_GPL(stutter_wait); | ||
481 | |||
482 | /* | ||
483 | * Cause the torture test to "stutter", starting and stopping all | ||
484 | * threads periodically. | ||
485 | */ | ||
486 | static int torture_stutter(void *arg) | ||
487 | { | ||
488 | VERBOSE_TOROUT_STRING("torture_stutter task started"); | ||
489 | do { | ||
490 | if (!torture_must_stop()) { | ||
491 | schedule_timeout_interruptible(stutter); | ||
492 | ACCESS_ONCE(stutter_pause_test) = 1; | ||
493 | } | ||
494 | if (!torture_must_stop()) | ||
495 | schedule_timeout_interruptible(stutter); | ||
496 | ACCESS_ONCE(stutter_pause_test) = 0; | ||
497 | torture_shutdown_absorb("torture_stutter"); | ||
498 | } while (!torture_must_stop()); | ||
499 | VERBOSE_TOROUT_STRING("torture_stutter task stopping"); | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | /* | ||
504 | * Initialize and kick off the torture_stutter kthread. | ||
505 | */ | ||
506 | int torture_stutter_init(int s) | ||
507 | { | ||
508 | int ret; | ||
509 | |||
510 | stutter = s; | ||
511 | stutter_task = kthread_run(torture_stutter, NULL, "torture_stutter"); | ||
512 | if (IS_ERR(stutter_task)) { | ||
513 | ret = PTR_ERR(stutter_task); | ||
514 | VERBOSE_TOROUT_ERRSTRING("Failed to create stutter"); | ||
515 | stutter_task = NULL; | ||
516 | return ret; | ||
517 | } | ||
518 | torture_shuffle_task_register(stutter_task); | ||
519 | return 0; | ||
520 | } | ||
521 | EXPORT_SYMBOL_GPL(torture_stutter_init); | ||
522 | |||
523 | /* | ||
524 | * Cleanup after the torture_stutter kthread. | ||
525 | */ | ||
526 | void torture_stutter_cleanup(void) | ||
527 | { | ||
528 | if (!stutter_task) | ||
529 | return; | ||
530 | VERBOSE_TOROUT_STRING("Stopping torture_stutter task"); | ||
531 | kthread_stop(stutter_task); | ||
532 | stutter_task = NULL; | ||
533 | } | ||
534 | EXPORT_SYMBOL_GPL(torture_stutter_cleanup); | ||
535 | |||
536 | /* | ||
456 | * Initialize torture module. Please note that this is -not- invoked via | 537 | * Initialize torture module. Please note that this is -not- invoked via |
457 | * the usual module_init() mechanism, but rather by an explicit call from | 538 | * the usual module_init() mechanism, but rather by an explicit call from |
458 | * the client torture module. This call must be paired with a later | 539 | * the client torture module. This call must be paired with a later |
459 | * torture_init_end(). | 540 | * torture_init_end(). |
541 | * | ||
542 | * The runnable parameter points to a flag that controls whether or not | ||
543 | * the test is currently runnable. If there is no such flag, pass in NULL. | ||
460 | */ | 544 | */ |
461 | void __init torture_init_begin(char *ttype, bool v) | 545 | void __init torture_init_begin(char *ttype, bool v, int *runnable) |
462 | { | 546 | { |
463 | mutex_lock(&fullstop_mutex); | 547 | mutex_lock(&fullstop_mutex); |
464 | torture_type = ttype; | 548 | torture_type = ttype; |
465 | verbose = v; | 549 | verbose = v; |
550 | torture_runnable = runnable; | ||
466 | fullstop = FULLSTOP_DONTSTOP; | 551 | fullstop = FULLSTOP_DONTSTOP; |
467 | 552 | ||
468 | } | 553 | } |