mirror of
https://github.com/torvalds/linux.git
synced 2024-12-31 23:31:29 +00:00
rcutorture: Make stutter_wait() caller restore priority
Currently, stutter_wait() will happily spin waiting for the stutter interval to end even if the caller is running at a real-time priority level. This could starve normal-priority tasks for no good reason. This commit therefore drops the calling task's priority to SCHED_OTHER MAX_NICE if stutter_wait() needs to wait. But when it waits, stutter_wait() returns true, which allows the caller to restore the priority if needed. Callers that were already running at SCHED_OTHER MAX_NICE obviously do not need any changes, but this commit also restores priority for higher-priority callers. Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
This commit is contained in:
parent
c1e0628758
commit
ab1b7880de
@ -912,7 +912,8 @@ static int rcu_torture_boost(void *arg)
|
|||||||
oldstarttime = boost_starttime;
|
oldstarttime = boost_starttime;
|
||||||
while (time_before(jiffies, oldstarttime)) {
|
while (time_before(jiffies, oldstarttime)) {
|
||||||
schedule_timeout_interruptible(oldstarttime - jiffies);
|
schedule_timeout_interruptible(oldstarttime - jiffies);
|
||||||
stutter_wait("rcu_torture_boost");
|
if (stutter_wait("rcu_torture_boost"))
|
||||||
|
sched_set_fifo_low(current);
|
||||||
if (torture_must_stop())
|
if (torture_must_stop())
|
||||||
goto checkwait;
|
goto checkwait;
|
||||||
}
|
}
|
||||||
@ -932,7 +933,8 @@ static int rcu_torture_boost(void *arg)
|
|||||||
jiffies);
|
jiffies);
|
||||||
call_rcu_time = jiffies;
|
call_rcu_time = jiffies;
|
||||||
}
|
}
|
||||||
stutter_wait("rcu_torture_boost");
|
if (stutter_wait("rcu_torture_boost"))
|
||||||
|
sched_set_fifo_low(current);
|
||||||
if (torture_must_stop())
|
if (torture_must_stop())
|
||||||
goto checkwait;
|
goto checkwait;
|
||||||
}
|
}
|
||||||
@ -964,7 +966,8 @@ static int rcu_torture_boost(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Go do the stutter. */
|
/* Go do the stutter. */
|
||||||
checkwait: stutter_wait("rcu_torture_boost");
|
checkwait: if (stutter_wait("rcu_torture_boost"))
|
||||||
|
sched_set_fifo_low(current);
|
||||||
} while (!torture_must_stop());
|
} while (!torture_must_stop());
|
||||||
|
|
||||||
/* Clean up and exit. */
|
/* Clean up and exit. */
|
||||||
@ -987,6 +990,7 @@ rcu_torture_fqs(void *arg)
|
|||||||
{
|
{
|
||||||
unsigned long fqs_resume_time;
|
unsigned long fqs_resume_time;
|
||||||
int fqs_burst_remaining;
|
int fqs_burst_remaining;
|
||||||
|
int oldnice = task_nice(current);
|
||||||
|
|
||||||
VERBOSE_TOROUT_STRING("rcu_torture_fqs task started");
|
VERBOSE_TOROUT_STRING("rcu_torture_fqs task started");
|
||||||
do {
|
do {
|
||||||
@ -1002,7 +1006,8 @@ rcu_torture_fqs(void *arg)
|
|||||||
udelay(fqs_holdoff);
|
udelay(fqs_holdoff);
|
||||||
fqs_burst_remaining -= fqs_holdoff;
|
fqs_burst_remaining -= fqs_holdoff;
|
||||||
}
|
}
|
||||||
stutter_wait("rcu_torture_fqs");
|
if (stutter_wait("rcu_torture_fqs"))
|
||||||
|
sched_set_normal(current, oldnice);
|
||||||
} while (!torture_must_stop());
|
} while (!torture_must_stop());
|
||||||
torture_kthread_stopping("rcu_torture_fqs");
|
torture_kthread_stopping("rcu_torture_fqs");
|
||||||
return 0;
|
return 0;
|
||||||
@ -1022,9 +1027,11 @@ rcu_torture_writer(void *arg)
|
|||||||
bool gp_cond1 = gp_cond, gp_exp1 = gp_exp, gp_normal1 = gp_normal;
|
bool gp_cond1 = gp_cond, gp_exp1 = gp_exp, gp_normal1 = gp_normal;
|
||||||
bool gp_sync1 = gp_sync;
|
bool gp_sync1 = gp_sync;
|
||||||
int i;
|
int i;
|
||||||
|
int oldnice = task_nice(current);
|
||||||
struct rcu_torture *rp;
|
struct rcu_torture *rp;
|
||||||
struct rcu_torture *old_rp;
|
struct rcu_torture *old_rp;
|
||||||
static DEFINE_TORTURE_RANDOM(rand);
|
static DEFINE_TORTURE_RANDOM(rand);
|
||||||
|
bool stutter_waited;
|
||||||
int synctype[] = { RTWS_DEF_FREE, RTWS_EXP_SYNC,
|
int synctype[] = { RTWS_DEF_FREE, RTWS_EXP_SYNC,
|
||||||
RTWS_COND_GET, RTWS_SYNC };
|
RTWS_COND_GET, RTWS_SYNC };
|
||||||
int nsynctypes = 0;
|
int nsynctypes = 0;
|
||||||
@ -1143,7 +1150,8 @@ rcu_torture_writer(void *arg)
|
|||||||
!rcu_gp_is_normal();
|
!rcu_gp_is_normal();
|
||||||
}
|
}
|
||||||
rcu_torture_writer_state = RTWS_STUTTER;
|
rcu_torture_writer_state = RTWS_STUTTER;
|
||||||
if (stutter_wait("rcu_torture_writer") &&
|
stutter_waited = stutter_wait("rcu_torture_writer");
|
||||||
|
if (stutter_waited &&
|
||||||
!READ_ONCE(rcu_fwd_cb_nodelay) &&
|
!READ_ONCE(rcu_fwd_cb_nodelay) &&
|
||||||
!cur_ops->slow_gps &&
|
!cur_ops->slow_gps &&
|
||||||
!torture_must_stop() &&
|
!torture_must_stop() &&
|
||||||
@ -1155,6 +1163,8 @@ rcu_torture_writer(void *arg)
|
|||||||
rcu_ftrace_dump(DUMP_ALL);
|
rcu_ftrace_dump(DUMP_ALL);
|
||||||
WARN(1, "%s: rtort_pipe_count: %d\n", __func__, rcu_tortures[i].rtort_pipe_count);
|
WARN(1, "%s: rtort_pipe_count: %d\n", __func__, rcu_tortures[i].rtort_pipe_count);
|
||||||
}
|
}
|
||||||
|
if (stutter_waited)
|
||||||
|
sched_set_normal(current, oldnice);
|
||||||
} while (!torture_must_stop());
|
} while (!torture_must_stop());
|
||||||
rcu_torture_current = NULL; // Let stats task know that we are done.
|
rcu_torture_current = NULL; // Let stats task know that we are done.
|
||||||
/* Reset expediting back to unexpedited. */
|
/* Reset expediting back to unexpedited. */
|
||||||
@ -2103,6 +2113,7 @@ static struct notifier_block rcutorture_oom_nb = {
|
|||||||
/* Carry out grace-period forward-progress testing. */
|
/* Carry out grace-period forward-progress testing. */
|
||||||
static int rcu_torture_fwd_prog(void *args)
|
static int rcu_torture_fwd_prog(void *args)
|
||||||
{
|
{
|
||||||
|
int oldnice = task_nice(current);
|
||||||
struct rcu_fwd *rfp = args;
|
struct rcu_fwd *rfp = args;
|
||||||
int tested = 0;
|
int tested = 0;
|
||||||
int tested_tries = 0;
|
int tested_tries = 0;
|
||||||
@ -2121,7 +2132,8 @@ static int rcu_torture_fwd_prog(void *args)
|
|||||||
rcu_torture_fwd_prog_cr(rfp);
|
rcu_torture_fwd_prog_cr(rfp);
|
||||||
|
|
||||||
/* Avoid slow periods, better to test when busy. */
|
/* Avoid slow periods, better to test when busy. */
|
||||||
stutter_wait("rcu_torture_fwd_prog");
|
if (stutter_wait("rcu_torture_fwd_prog"))
|
||||||
|
sched_set_normal(current, oldnice);
|
||||||
} while (!torture_must_stop());
|
} while (!torture_must_stop());
|
||||||
/* Short runs might not contain a valid forward-progress attempt. */
|
/* Short runs might not contain a valid forward-progress attempt. */
|
||||||
WARN_ON(!tested && tested_tries >= 5);
|
WARN_ON(!tested && tested_tries >= 5);
|
||||||
|
@ -604,19 +604,19 @@ bool stutter_wait(const char *title)
|
|||||||
{
|
{
|
||||||
ktime_t delay;
|
ktime_t delay;
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
int oldnice;
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
int spt;
|
int spt;
|
||||||
|
|
||||||
cond_resched_tasks_rcu_qs();
|
cond_resched_tasks_rcu_qs();
|
||||||
spt = READ_ONCE(stutter_pause_test);
|
spt = READ_ONCE(stutter_pause_test);
|
||||||
for (; spt; spt = READ_ONCE(stutter_pause_test)) {
|
for (; spt; spt = READ_ONCE(stutter_pause_test)) {
|
||||||
ret = true;
|
if (!ret) {
|
||||||
|
sched_set_normal(current, MAX_NICE);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
if (spt == 1) {
|
if (spt == 1) {
|
||||||
schedule_timeout_interruptible(1);
|
schedule_timeout_interruptible(1);
|
||||||
} else if (spt == 2) {
|
} else if (spt == 2) {
|
||||||
oldnice = task_nice(current);
|
|
||||||
set_user_nice(current, MAX_NICE);
|
|
||||||
while (READ_ONCE(stutter_pause_test)) {
|
while (READ_ONCE(stutter_pause_test)) {
|
||||||
if (!(i++ & 0xffff)) {
|
if (!(i++ & 0xffff)) {
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
@ -625,7 +625,6 @@ bool stutter_wait(const char *title)
|
|||||||
}
|
}
|
||||||
cond_resched();
|
cond_resched();
|
||||||
}
|
}
|
||||||
set_user_nice(current, oldnice);
|
|
||||||
} else {
|
} else {
|
||||||
schedule_timeout_interruptible(round_jiffies_relative(HZ));
|
schedule_timeout_interruptible(round_jiffies_relative(HZ));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user