Commit ab1b7880 authored by Paul E. McKenney's avatar Paul E. McKenney
Browse files

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: default avatarPaul E. McKenney <paulmck@kernel.org>
parent c1e06287
Loading
Loading
Loading
Loading
+18 −6
Original line number Diff line number Diff line
@@ -912,7 +912,8 @@ static int rcu_torture_boost(void *arg)
		oldstarttime = boost_starttime;
		while (time_before(jiffies, oldstarttime)) {
			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())
				goto checkwait;
		}
@@ -932,7 +933,8 @@ static int rcu_torture_boost(void *arg)
								 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())
				goto checkwait;
		}
@@ -964,7 +966,8 @@ static int rcu_torture_boost(void *arg)
		}

		/* 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());

	/* Clean up and exit. */
@@ -987,6 +990,7 @@ rcu_torture_fqs(void *arg)
{
	unsigned long fqs_resume_time;
	int fqs_burst_remaining;
	int oldnice = task_nice(current);

	VERBOSE_TOROUT_STRING("rcu_torture_fqs task started");
	do {
@@ -1002,7 +1006,8 @@ rcu_torture_fqs(void *arg)
			udelay(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());
	torture_kthread_stopping("rcu_torture_fqs");
	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_sync1 = gp_sync;
	int i;
	int oldnice = task_nice(current);
	struct rcu_torture *rp;
	struct rcu_torture *old_rp;
	static DEFINE_TORTURE_RANDOM(rand);
	bool stutter_waited;
	int synctype[] = { RTWS_DEF_FREE, RTWS_EXP_SYNC,
			   RTWS_COND_GET, RTWS_SYNC };
	int nsynctypes = 0;
@@ -1143,7 +1150,8 @@ rcu_torture_writer(void *arg)
				       !rcu_gp_is_normal();
		}
		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) &&
		    !cur_ops->slow_gps &&
		    !torture_must_stop() &&
@@ -1155,6 +1163,8 @@ rcu_torture_writer(void *arg)
					rcu_ftrace_dump(DUMP_ALL);
					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());
	rcu_torture_current = NULL;  // Let stats task know that we are done.
	/* Reset expediting back to unexpedited. */
@@ -2103,6 +2113,7 @@ static struct notifier_block rcutorture_oom_nb = {
/* Carry out grace-period forward-progress testing. */
static int rcu_torture_fwd_prog(void *args)
{
	int oldnice = task_nice(current);
	struct rcu_fwd *rfp = args;
	int tested = 0;
	int tested_tries = 0;
@@ -2121,7 +2132,8 @@ static int rcu_torture_fwd_prog(void *args)
			rcu_torture_fwd_prog_cr(rfp);

		/* 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());
	/* Short runs might not contain a valid forward-progress attempt. */
	WARN_ON(!tested && tested_tries >= 5);
+4 −5
Original line number Diff line number Diff line
@@ -604,19 +604,19 @@ bool stutter_wait(const char *title)
{
	ktime_t delay;
	unsigned int i = 0;
	int oldnice;
	bool ret = false;
	int spt;

	cond_resched_tasks_rcu_qs();
	spt = READ_ONCE(stutter_pause_test);
	for (; spt; spt = READ_ONCE(stutter_pause_test)) {
		if (!ret) {
			sched_set_normal(current, MAX_NICE);
			ret = true;
		}
		if (spt == 1) {
			schedule_timeout_interruptible(1);
		} else if (spt == 2) {
			oldnice = task_nice(current);
			set_user_nice(current, MAX_NICE);
			while (READ_ONCE(stutter_pause_test)) {
				if (!(i++ & 0xffff)) {
					set_current_state(TASK_INTERRUPTIBLE);
@@ -625,7 +625,6 @@ bool stutter_wait(const char *title)
				}
				cond_resched();
			}
			set_user_nice(current, oldnice);
		} else {
			schedule_timeout_interruptible(round_jiffies_relative(HZ));
		}