Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

rcu: Break up rcu_gp_kthread() into subfunctions



Then rcu_gp_kthread() function is too large and furthermore needs to
have the force_quiescent_state() code pulled in.  This commit therefore
breaks up rcu_gp_kthread() into rcu_gp_init() and rcu_gp_cleanup().

Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: default avatarJosh Triplett <josh@joshtriplett.org>
parent c856bafa
Loading
Loading
Loading
Loading
+135 −115
Original line number Diff line number Diff line
@@ -1028,37 +1028,20 @@ rcu_start_gp_per_cpu(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_dat
}

/*
 * Body of kthread that handles grace periods.
 * Initialize a new grace period.
 */
static int __noreturn rcu_gp_kthread(void *arg)
static int rcu_gp_init(struct rcu_state *rsp)
{
	unsigned long gp_duration;
	struct rcu_data *rdp;
	struct rcu_node *rnp;
	struct rcu_state *rsp = arg;

	for (;;) {
	struct rcu_node *rnp = rcu_get_root(rsp);

		/* Handle grace-period start. */
		rnp = rcu_get_root(rsp);
		for (;;) {
			wait_event_interruptible(rsp->gp_wq, rsp->gp_flags);
			if (rsp->gp_flags)
				break;
			flush_signals(current);
		}
	raw_spin_lock_irq(&rnp->lock);
	rsp->gp_flags = 0;
		rdp = this_cpu_ptr(rsp->rda);

	if (rcu_gp_in_progress(rsp)) {
			/*
			 * A grace period is already in progress, so
			 * don't start another one.
			 */
		/* Grace period already in progress, don't start another.  */
		raw_spin_unlock_irq(&rnp->lock);
			cond_resched();
			continue;
		return 0;
	}

	if (rsp->fqs_active) {
@@ -1068,8 +1051,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
		 */
		rsp->fqs_need_gp = 1;
		raw_spin_unlock_irq(&rnp->lock);
			cond_resched();
			continue;
		return 0;
	}

	/* Advance to a new grace period and initialize state. */
@@ -1086,17 +1068,20 @@ static int __noreturn rcu_gp_kthread(void *arg)

	/*
	 * Set the quiescent-state-needed bits in all the rcu_node
		 * structures for all currently online CPUs in breadth-first
		 * order, starting from the root rcu_node structure.
		 * This operation relies on the layout of the hierarchy
		 * within the rsp->node[] array.  Note that other CPUs will
		 * access only the leaves of the hierarchy, which still
		 * indicate that no grace period is in progress, at least
		 * until the corresponding leaf node has been initialized.
		 * In addition, we have excluded CPU-hotplug operations.
	 * structures for all currently online CPUs in breadth-first order,
	 * starting from the root rcu_node structure, relying on the layout
	 * of the tree within the rsp->node[] array.  Note that other CPUs
	 * will access only the leaves of the hierarchy, thus seeing that no
	 * grace period is in progress, at least until the corresponding
	 * leaf node has been initialized.  In addition, we have excluded
	 * CPU-hotplug operations.
	 *
	 * The grace period cannot complete until the initialization
	 * process finishes, because this kthread handles both.
	 */
	rcu_for_each_node_breadth_first(rsp, rnp) {
		raw_spin_lock_irq(&rnp->lock);
		rdp = this_cpu_ptr(rsp->rda);
		rcu_preempt_check_blocked_tasks(rnp);
		rnp->qsmask = rnp->qsmaskinit;
		rnp->gpnum = rsp->gpnum;
@@ -1117,19 +1102,18 @@ static int __noreturn rcu_gp_kthread(void *arg)
	rsp->fqs_state = RCU_SIGNAL_INIT;
	raw_spin_unlock_irq(&rnp->lock);
	put_online_cpus();

		/* Handle grace-period end. */
		rnp = rcu_get_root(rsp);
		for (;;) {
			wait_event_interruptible(rsp->gp_wq,
						 !ACCESS_ONCE(rnp->qsmask) &&
						 !rcu_preempt_blocked_readers_cgp(rnp));
			if (!ACCESS_ONCE(rnp->qsmask) &&
			    !rcu_preempt_blocked_readers_cgp(rnp))
				break;
			flush_signals(current);
	return 1;
}

/*
 * Clean up after the old grace period.
 */
static int rcu_gp_cleanup(struct rcu_state *rsp)
{
	unsigned long gp_duration;
	struct rcu_data *rdp;
	struct rcu_node *rnp = rcu_get_root(rsp);

	raw_spin_lock_irq(&rnp->lock);
	gp_duration = jiffies - rsp->gp_start;
	if (gp_duration > rsp->gp_max)
@@ -1150,6 +1134,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
	 * callbacks are waiting on the grace period that just now
	 * completed.
	 */
	rdp = this_cpu_ptr(rsp->rda);
	if (*rdp->nxttail[RCU_WAIT_TAIL] == NULL) {
		raw_spin_unlock_irq(&rnp->lock);

@@ -1175,6 +1160,41 @@ static int __noreturn rcu_gp_kthread(void *arg)
	if (cpu_needs_another_gp(rsp, rdp))
		rsp->gp_flags = 1;
	raw_spin_unlock_irq(&rnp->lock);
	return 1;
}

/*
 * Body of kthread that handles grace periods.
 */
static int __noreturn rcu_gp_kthread(void *arg)
{
	struct rcu_state *rsp = arg;
	struct rcu_node *rnp = rcu_get_root(rsp);

	for (;;) {

		/* Handle grace-period start. */
		for (;;) {
			wait_event_interruptible(rsp->gp_wq, rsp->gp_flags);
			if (rsp->gp_flags && rcu_gp_init(rsp))
				break;
			cond_resched();
			flush_signals(current);
		}

		/* Handle grace-period end. */
		rnp = rcu_get_root(rsp);
		for (;;) {
			wait_event_interruptible(rsp->gp_wq,
						 !ACCESS_ONCE(rnp->qsmask) &&
						 !rcu_preempt_blocked_readers_cgp(rnp));
			if (!ACCESS_ONCE(rnp->qsmask) &&
			    !rcu_preempt_blocked_readers_cgp(rnp) &&
			    rcu_gp_cleanup(rsp))
				break;
			cond_resched();
			flush_signals(current);
		}
	}
}