On Wed, Oct 03, 2007 at 04:59:51PM -0400, Steven Rostedt wrote:
> Paul,
>
> I ran your original preemption test of RCU torture, and after several
> minutes, my preempt boost patch had one Preemption stall. I then
> disabled preemption boosting, and ran the preempt torture again, and it
> seemed to never stall. Something seemed strange, so I took a look.
>
> Looks like you have a single thread that will run at max prio that runs
> for 10 secs and then sleeps again. This thread seems to only push rcu
> readers around. But it doesn't seem to do much else. That is a good test
> to see if RCU readers can handle being pushed around, but it doesn't
> test preemption boosting.
Looks like I shot myself in the foot by complaining about a bug... :-/
http://lkml.org/lkml/2007/6/10/234
With the bug, the readers weren't migrating, without it, they do.
Good catch!!! Thank you!!!
> To do that, I modified the test to create CPUS-1 preempt boost hogs (or
> 1 if it is UP). But instead of putting it at max prio, I set it to the
> lowest RT prio of 1. This way it's still at a higher priority than the
> readers. I also switched the writers to run at 1+n where n increases for
> every fake writer there is.
>
> Without preempt boosting, after a couple of minutes I had 83 preemption
> stalls. When I turned my boosting back on, after several minutes (still
> running as I type this) it has no preemption stalls.
>
> This seems to be a good test for RCU preemption boosting.
I am testing it out against my earlier patchset, with some encouraging
results -- I will incorporate into the next round of my mainline patchset.
Some questions and comments below.
> -- Steve
>
> PS. I got rid of your rcu_preeempt_task for rcu_preempt_tasks ;-)
>
> (No the above is _not_ a typo)
:-/
> Signed-off-by: Steven Rostedt <[email protected]>
>
> Index: linux-2.6.23-rc9-rt1/kernel/rcutorture.c
> ===================================================================
> --- linux-2.6.23-rc9-rt1.orig/kernel/rcutorture.c
> +++ linux-2.6.23-rc9-rt1/kernel/rcutorture.c
> @@ -54,6 +54,7 @@ MODULE_AUTHOR("Paul E. McKenney <paulmck
>
> static int nreaders = -1; /* # reader threads, defaults to 2*ncpus */
> static int nfakewriters = 4; /* # fake writer threads */
> +static int npreempthogs = -1; /* # preempt hogs to run (defaults to ncpus-1) or 1 */
> static int stat_interval; /* Interval between stats, in seconds. */
> /* Defaults to "only at end of test". */
> static int verbose; /* Print more debug info. */
> @@ -90,9 +91,11 @@ MODULE_PARM_DESC(torture_type, "Type of
> static char printk_buf[4096];
>
> static int nrealreaders;
> +static int nrealpreempthogs;
I made the above be a module parameter. This OK?
> static struct task_struct *writer_task;
> static struct task_struct **fakewriter_tasks;
> static struct task_struct **reader_tasks;
> +static struct task_struct **rcu_preempt_tasks;
> static struct task_struct *stats_task;
> static struct task_struct *shuffler_task;
>
> @@ -264,7 +267,6 @@ static void rcu_torture_deferred_free(st
> call_rcu(&p->rtort_rcu, rcu_torture_cb);
> }
>
> -static struct task_struct *rcu_preeempt_task;
> static unsigned long rcu_torture_preempt_errors;
>
> static int rcu_torture_preempt(void *arg)
> @@ -274,7 +276,7 @@ static int rcu_torture_preempt(void *arg
> time_t gcstart;
> struct sched_param sp;
>
> - sp.sched_priority = MAX_RT_PRIO - 1;
> + sp.sched_priority = 1;
> err = sched_setscheduler(current, SCHED_RR, &sp);
> if (err != 0)
> printk(KERN_ALERT "rcu_torture_preempt() priority err: %d\n",
> @@ -297,24 +299,43 @@ static int rcu_torture_preempt(void *arg
> static long rcu_preempt_start(void)
> {
> long retval = 0;
> + int i;
>
> - rcu_preeempt_task = kthread_run(rcu_torture_preempt, NULL,
> - "rcu_torture_preempt");
> - if (IS_ERR(rcu_preeempt_task)) {
> - VERBOSE_PRINTK_ERRSTRING("Failed to create preempter");
> - retval = PTR_ERR(rcu_preeempt_task);
> - rcu_preeempt_task = NULL;
> + rcu_preempt_tasks = kzalloc(nrealpreempthogs * sizeof(rcu_preempt_tasks[0]),
> + GFP_KERNEL);
> + if (rcu_preempt_tasks == NULL) {
> + VERBOSE_PRINTK_ERRSTRING("out of memory");
> + retval = -ENOMEM;
> + goto out;
> }
> +
> + for (i=0; i < nrealpreempthogs; i++) {
> + rcu_preempt_tasks[i] = kthread_run(rcu_torture_preempt, NULL,
> + "rcu_torture_preempt");
> + if (IS_ERR(rcu_preempt_tasks[i])) {
> + VERBOSE_PRINTK_ERRSTRING("Failed to create preempter");
> + retval = PTR_ERR(rcu_preempt_tasks[i]);
> + rcu_preempt_tasks[i] = NULL;
> + break;
> + }
> + }
> + out:
> return retval;
> }
>
> static void rcu_preempt_end(void)
> {
> - if (rcu_preeempt_task != NULL) {
> - VERBOSE_PRINTK_STRING("Stopping rcu_preempt task");
> - kthread_stop(rcu_preeempt_task);
> + int i;
> + if (rcu_preempt_tasks) {
> + for (i=0; i < nrealpreempthogs; i++) {
> + if (rcu_preempt_tasks[i] != NULL) {
> + VERBOSE_PRINTK_STRING("Stopping rcu_preempt task");
> + kthread_stop(rcu_preempt_tasks[i]);
> + }
> + rcu_preempt_tasks[i] = NULL;
> + }
> + kfree(rcu_preempt_tasks);
> }
> - rcu_preeempt_task = NULL;
> }
>
> static int rcu_preempt_stats(char *page)
> @@ -613,10 +634,20 @@ rcu_torture_writer(void *arg)
> static int
> rcu_torture_fakewriter(void *arg)
> {
> + struct sched_param sp;
> + long id = (long) arg;
> + int err;
> DEFINE_RCU_RANDOM(rand);
>
> VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task started");
> - set_user_nice(current, 19);
> + /*
> + * Set up at a higher prio than the readers.
> + */
> + sp.sched_priority = 1 + id;
> + err = sched_setscheduler(current, SCHED_RR, &sp);
> + if (err != 0)
> + printk(KERN_ALERT "rcu_torture_writer() priority err: %d\n",
> + err);
The idea here is to force inheritance, to force the writer to continue
pushing grace periods even when the hogs are running, or both?
> do {
> schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
> @@ -849,9 +880,11 @@ rcu_torture_print_module_parms(char *tag
> {
> printk(KERN_ALERT "%s" TORTURE_FLAG
> "--- %s: nreaders=%d nfakewriters=%d "
> + "npreempthogs=%d "
> "stat_interval=%d verbose=%d test_no_idle_hz=%d "
> "shuffle_interval=%d preempt_torture=%d\n",
> torture_type, tag, nrealreaders, nfakewriters,
> + nrealpreempthogs,
> stat_interval, verbose, test_no_idle_hz, shuffle_interval,
> preempt_torture);
> }
> @@ -925,7 +958,7 @@ rcu_torture_cleanup(void)
> static int __init
> rcu_torture_init(void)
> {
> - int i;
> + long i;
> int cpu;
> int firsterr = 0;
> static struct rcu_torture_ops *torture_ops[] =
> @@ -953,6 +986,12 @@ rcu_torture_init(void)
> rcu_torture_print_module_parms("Start of test");
> fullstop = 0;
>
> + if (npreempthogs >= 0)
> + nrealpreempthogs = npreempthogs;
> + else
> + nrealpreempthogs = num_online_cpus() == 1 ? 1 :
> + num_online_cpus() - 1;
OK -- the idea here is to leave at least one CPU to respond to keyboard
and mouse? I end up with all the readers getting shoved to the left-over
CPU. I am experimenting with ways of synchronizing the hogs and also
allowing synchronized idle time...
> +
> /* Set up the freelist. */
>
> INIT_LIST_HEAD(&rcu_torture_freelist);
> @@ -1000,7 +1039,7 @@ rcu_torture_init(void)
> }
> for (i = 0; i < nfakewriters; i++) {
> VERBOSE_PRINTK_STRING("Creating rcu_torture_fakewriter task");
> - fakewriter_tasks[i] = kthread_run(rcu_torture_fakewriter, NULL,
> + fakewriter_tasks[i] = kthread_run(rcu_torture_fakewriter, (void*)i,
> "rcu_torture_fakewriter");
> if (IS_ERR(fakewriter_tasks[i])) {
> firsterr = PTR_ERR(fakewriter_tasks[i]);
>
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]