On Fri, Oct 05, 2007 at 08:21:49AM -0400, Steven Rostedt wrote:
Well, it would indeed appear that my mind was bent...
Fair enough!
OK, got it -- not needed in conjunction with my priority-boost mechanism.
(Though I do very much like the idea of high-priority synchronize_rcu()
invocations speeding up grace periods -- in fact, am considering
accelerating the detection mechanism in this case. But later.)
OK, seems to be at least limping, see patch below. (But you will want
to add the high priority to the writers for your RCU priority-boost
mechanism.)
:-/ We overlap exactly...
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
rcutorture.c | 67 ++++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 48 insertions(+), 19 deletions(-)
diff -urpNa -X dontdiff linux-2.6.22-i-cleanups/kernel/rcutorture.c linux-2.6.22-j-rostedtrt/kernel/rcutorture.c
--- linux-2.6.22-i-cleanups/kernel/rcutorture.c 2007-09-09 16:58:35.000000000 -0700
+++ linux-2.6.22-j-rostedtrt/kernel/rcutorture.c 2007-10-05 04:50:24.000000000 -0700
@@ -53,6 +53,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. */
@@ -65,6 +66,8 @@ module_param(nreaders, int, 0444);
MODULE_PARM_DESC(nreaders, "Number of RCU reader threads");
module_param(nfakewriters, int, 0444);
MODULE_PARM_DESC(nfakewriters, "Number of RCU fake writer threads");
+module_param(npreempthogs, int, 0444);
+MODULE_PARM_DESC(npreempthogs, "Number of preemption hog threads to run");
module_param(stat_interval, int, 0444);
MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s");
module_param(verbose, bool, 0444);
@@ -89,9 +92,11 @@ MODULE_PARM_DESC(torture_type, "Type of
static char printk_buf[4096];
static int nrealreaders;
+static int nrealpreempthogs;
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;
@@ -263,17 +268,15 @@ 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)
{
int completedstart;
int err;
- 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",
@@ -282,13 +285,12 @@ static int rcu_torture_preempt(void *arg
do {
completedstart = rcu_torture_completed();
- gcstart = xtime.tv_sec;
- while ((xtime.tv_sec - gcstart < 10) &&
- (rcu_torture_completed() == completedstart))
+ while (((xtime.tv_sec & 0xf) < 7) &&
+ ((rcu_torture_completed() - completedstart) < 2))
cond_resched();
if (rcu_torture_completed() == completedstart)
rcu_torture_preempt_errors++;
- schedule_timeout_interruptible(1);
+ schedule_timeout_interruptible(10 * HZ);
} while (!kthread_should_stop());
return 0;
}
@@ -296,24 +298,43 @@ static int rcu_torture_preempt(void *arg
static long rcu_preempt_start(void)
{
long retval = 0;
+ int i;
+
+ 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;
+ }
- 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;
+ 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)
@@ -847,9 +868,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);
}
@@ -923,7 +946,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[] =
@@ -951,6 +974,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;
+
/* Set up the freelist. */
INIT_LIST_HEAD(&rcu_torture_freelist);
@@ -998,7 +1027,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]);
-