aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutorture.c
diff options
context:
space:
mode:
authorSrivatsa Vaddagiri <vatsa@in.ibm.com>2006-01-08 04:03:42 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-08 23:13:59 -0500
commitd84f520348d77e61f936227a048403dbc349fff1 (patch)
tree765dd3cc733b4149222d4ac9cf746f54cf557fdd /kernel/rcutorture.c
parent9841d61d75da5e46ed7a978bed4f50c78b1d87fd (diff)
[PATCH] Extend RCU torture module to test tickless idle CPU
This patch forces RCU torture threads off various CPUs in the system allowing them to become idle and go tickless. Meant to test support for such tickless idle CPU in RCU. Signed-off-by: Srivatsa Vaddagiri <vatsa@in.ibm.com> Cc: Dipankar Sarma <dipankar@in.ibm.com> Cc: "Paul E. McKenney" <paulmck@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/rcutorture.c')
-rw-r--r--kernel/rcutorture.c96
1 files changed, 91 insertions, 5 deletions
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 75174c81529a..773219907dd8 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -48,9 +48,11 @@
48MODULE_LICENSE("GPL"); 48MODULE_LICENSE("GPL");
49 49
50static int nreaders = -1; /* # reader threads, defaults to 4*ncpus */ 50static int nreaders = -1; /* # reader threads, defaults to 4*ncpus */
51static int stat_interval = 0; /* Interval between stats, in seconds. */ 51static int stat_interval; /* Interval between stats, in seconds. */
52 /* Defaults to "only at end of test". */ 52 /* Defaults to "only at end of test". */
53static int verbose = 0; /* Print more debug info. */ 53static int verbose; /* Print more debug info. */
54static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */
55static int shuffle_interval = 5; /* Interval between shuffles (in sec)*/
54 56
55MODULE_PARM(nreaders, "i"); 57MODULE_PARM(nreaders, "i");
56MODULE_PARM_DESC(nreaders, "Number of RCU reader threads"); 58MODULE_PARM_DESC(nreaders, "Number of RCU reader threads");
@@ -58,6 +60,10 @@ MODULE_PARM(stat_interval, "i");
58MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s"); 60MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s");
59MODULE_PARM(verbose, "i"); 61MODULE_PARM(verbose, "i");
60MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s"); 62MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
63MODULE_PARM(test_no_idle_hz, "i");
64MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs");
65MODULE_PARM(shuffle_interval, "i");
66MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles");
61#define TORTURE_FLAG "rcutorture: " 67#define TORTURE_FLAG "rcutorture: "
62#define PRINTK_STRING(s) \ 68#define PRINTK_STRING(s) \
63 do { printk(KERN_ALERT TORTURE_FLAG s "\n"); } while (0) 69 do { printk(KERN_ALERT TORTURE_FLAG s "\n"); } while (0)
@@ -72,6 +78,7 @@ static int nrealreaders;
72static struct task_struct *writer_task; 78static struct task_struct *writer_task;
73static struct task_struct **reader_tasks; 79static struct task_struct **reader_tasks;
74static struct task_struct *stats_task; 80static struct task_struct *stats_task;
81static struct task_struct *shuffler_task;
75 82
76#define RCU_TORTURE_PIPE_LEN 10 83#define RCU_TORTURE_PIPE_LEN 10
77 84
@@ -375,12 +382,77 @@ rcu_torture_stats(void *arg)
375 return 0; 382 return 0;
376} 383}
377 384
385static int rcu_idle_cpu; /* Force all torture tasks off this CPU */
386
387/* Shuffle tasks such that we allow @rcu_idle_cpu to become idle. A special case
388 * is when @rcu_idle_cpu = -1, when we allow the tasks to run on all CPUs.
389 */
390void rcu_torture_shuffle_tasks(void)
391{
392 cpumask_t tmp_mask = CPU_MASK_ALL;
393 int i;
394
395 lock_cpu_hotplug();
396
397 /* No point in shuffling if there is only one online CPU (ex: UP) */
398 if (num_online_cpus() == 1) {
399 unlock_cpu_hotplug();
400 return;
401 }
402
403 if (rcu_idle_cpu != -1)
404 cpu_clear(rcu_idle_cpu, tmp_mask);
405
406 set_cpus_allowed(current, tmp_mask);
407
408 if (reader_tasks != NULL) {
409 for (i = 0; i < nrealreaders; i++)
410 if (reader_tasks[i])
411 set_cpus_allowed(reader_tasks[i], tmp_mask);
412 }
413
414 if (writer_task)
415 set_cpus_allowed(writer_task, tmp_mask);
416
417 if (stats_task)
418 set_cpus_allowed(stats_task, tmp_mask);
419
420 if (rcu_idle_cpu == -1)
421 rcu_idle_cpu = num_online_cpus() - 1;
422 else
423 rcu_idle_cpu--;
424
425 unlock_cpu_hotplug();
426}
427
428/* Shuffle tasks across CPUs, with the intent of allowing each CPU in the
429 * system to become idle at a time and cut off its timer ticks. This is meant
430 * to test the support for such tickless idle CPU in RCU.
431 */
432static int
433rcu_torture_shuffle(void *arg)
434{
435 VERBOSE_PRINTK_STRING("rcu_torture_shuffle task started");
436 do {
437 schedule_timeout_interruptible(shuffle_interval * HZ);
438 rcu_torture_shuffle_tasks();
439 } while (!kthread_should_stop());
440 VERBOSE_PRINTK_STRING("rcu_torture_shuffle task stopping");
441 return 0;
442}
443
378static void 444static void
379rcu_torture_cleanup(void) 445rcu_torture_cleanup(void)
380{ 446{
381 int i; 447 int i;
382 448
383 fullstop = 1; 449 fullstop = 1;
450 if (shuffler_task != NULL) {
451 VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task");
452 kthread_stop(shuffler_task);
453 }
454 shuffler_task = NULL;
455
384 if (writer_task != NULL) { 456 if (writer_task != NULL) {
385 VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task"); 457 VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task");
386 kthread_stop(writer_task); 458 kthread_stop(writer_task);
@@ -429,9 +501,11 @@ rcu_torture_init(void)
429 nrealreaders = nreaders; 501 nrealreaders = nreaders;
430 else 502 else
431 nrealreaders = 2 * num_online_cpus(); 503 nrealreaders = 2 * num_online_cpus();
432 printk(KERN_ALERT TORTURE_FLAG 504 printk(KERN_ALERT TORTURE_FLAG "--- Start of test: nreaders=%d "
433 "--- Start of test: nreaders=%d stat_interval=%d verbose=%d\n", 505 "stat_interval=%d verbose=%d test_no_idle_hz=%d "
434 nrealreaders, stat_interval, verbose); 506 "shuffle_interval = %d\n",
507 nrealreaders, stat_interval, verbose, test_no_idle_hz,
508 shuffle_interval);
435 fullstop = 0; 509 fullstop = 0;
436 510
437 /* Set up the freelist. */ 511 /* Set up the freelist. */
@@ -501,6 +575,18 @@ rcu_torture_init(void)
501 goto unwind; 575 goto unwind;
502 } 576 }
503 } 577 }
578 if (test_no_idle_hz) {
579 rcu_idle_cpu = num_online_cpus() - 1;
580 /* Create the shuffler thread */
581 shuffler_task = kthread_run(rcu_torture_shuffle, NULL,
582 "rcu_torture_shuffle");
583 if (IS_ERR(shuffler_task)) {
584 firsterr = PTR_ERR(shuffler_task);
585 VERBOSE_PRINTK_ERRSTRING("Failed to create shuffler");
586 shuffler_task = NULL;
587 goto unwind;
588 }
589 }
504 return 0; 590 return 0;
505 591
506unwind: 592unwind: