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

rcu-tasks: Code movement to allow more Tasks RCU variants



This commit does nothing but move rcu_tasks_wait_gp() up to a new section
for common code.

Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
parent e4fe5dd6
Loading
Loading
Loading
Loading
+63 −59
Original line number Diff line number Diff line
@@ -211,6 +211,69 @@ static void __init rcu_tasks_bootup_oddness(void)

#ifdef CONFIG_TASKS_RCU

////////////////////////////////////////////////////////////////////////
//
// Shared code between task-list-scanning variants of Tasks RCU.

/* Wait for one RCU-tasks grace period. */
static void rcu_tasks_wait_gp(struct rcu_tasks *rtp)
{
	struct task_struct *g, *t;
	unsigned long lastreport;
	LIST_HEAD(holdouts);
	int fract;

	rtp->pregp_func();

	/*
	 * There were callbacks, so we need to wait for an RCU-tasks
	 * grace period.  Start off by scanning the task list for tasks
	 * that are not already voluntarily blocked.  Mark these tasks
	 * and make a list of them in holdouts.
	 */
	rcu_read_lock();
	for_each_process_thread(g, t)
		rtp->pertask_func(t, &holdouts);
	rcu_read_unlock();

	rtp->postscan_func();

	/*
	 * Each pass through the following loop scans the list of holdout
	 * tasks, removing any that are no longer holdouts.  When the list
	 * is empty, we are done.
	 */
	lastreport = jiffies;

	/* Start off with HZ/10 wait and slowly back off to 1 HZ wait. */
	fract = 10;

	for (;;) {
		bool firstreport;
		bool needreport;
		int rtst;

		if (list_empty(&holdouts))
			break;

		/* Slowly back off waiting for holdouts */
		schedule_timeout_interruptible(HZ/fract);

		if (fract > 1)
			fract--;

		rtst = READ_ONCE(rcu_task_stall_timeout);
		needreport = rtst > 0 && time_after(jiffies, lastreport + rtst);
		if (needreport)
			lastreport = jiffies;
		firstreport = true;
		WARN_ON(signal_pending(current));
		rtp->holdouts_func(&holdouts, needreport, &firstreport);
	}

	rtp->postgp_func();
}

////////////////////////////////////////////////////////////////////////
//
// Simple variant of RCU whose quiescent states are voluntary context
@@ -333,65 +396,6 @@ static void rcu_tasks_postgp(void)
	synchronize_rcu();
}

/* Wait for one RCU-tasks grace period. */
static void rcu_tasks_wait_gp(struct rcu_tasks *rtp)
{
	struct task_struct *g, *t;
	unsigned long lastreport;
	LIST_HEAD(holdouts);
	int fract;

	rtp->pregp_func();

	/*
	 * There were callbacks, so we need to wait for an RCU-tasks
	 * grace period.  Start off by scanning the task list for tasks
	 * that are not already voluntarily blocked.  Mark these tasks
	 * and make a list of them in holdouts.
	 */
	rcu_read_lock();
	for_each_process_thread(g, t)
		rtp->pertask_func(t, &holdouts);
	rcu_read_unlock();

	rtp->postscan_func();

	/*
	 * Each pass through the following loop scans the list of holdout
	 * tasks, removing any that are no longer holdouts.  When the list
	 * is empty, we are done.
	 */
	lastreport = jiffies;

	/* Start off with HZ/10 wait and slowly back off to 1 HZ wait. */
	fract = 10;

	for (;;) {
		bool firstreport;
		bool needreport;
		int rtst;

		if (list_empty(&holdouts))
			break;

		/* Slowly back off waiting for holdouts */
		schedule_timeout_interruptible(HZ/fract);

		if (fract > 1)
			fract--;

		rtst = READ_ONCE(rcu_task_stall_timeout);
		needreport = rtst > 0 && time_after(jiffies, lastreport + rtst);
		if (needreport)
			lastreport = jiffies;
		firstreport = true;
		WARN_ON(signal_pending(current));
		rtp->holdouts_func(&holdouts, needreport, &firstreport);
	}

	rtp->postgp_func();
}

void call_rcu_tasks(struct rcu_head *rhp, rcu_callback_t func);
DEFINE_RCU_TASKS(rcu_tasks, rcu_tasks_wait_gp, call_rcu_tasks, "RCU Tasks");