All of lore.kernel.org
 help / color / mirror / Atom feed
From: Josh Triplett <josh@joshtriplett.org>
To: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: linux-kernel@vger.kernel.org, mingo@elte.hu,
	laijs@cn.fujitsu.com, dipankar@in.ibm.com,
	akpm@linux-foundation.org, mathieu.desnoyers@polymtl.ca,
	niv@us.ibm.com, tglx@linutronix.de, peterz@infradead.org,
	rostedt@goodmis.org, Valdis.Kletnieks@vt.edu,
	dhowells@redhat.com, eric.dumazet@gmail.com, darren@dvhart.com,
	fweisbec@gmail.com, sbw@mit.edu, patches@linaro.org
Subject: Re: [PATCH tip/core/rcu 06/23] rcu: Break up rcu_gp_kthread() into subfunctions
Date: Sat, 1 Sep 2012 19:11:22 -0700	[thread overview]
Message-ID: <20120902021121.GF5713@leaf> (raw)
In-Reply-To: <1346350718-30937-6-git-send-email-paulmck@linux.vnet.ibm.com>

On Thu, Aug 30, 2012 at 11:18:21AM -0700, Paul E. McKenney wrote:
> From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
> 
> 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: Paul E. McKenney <paulmck@linux.vnet.ibm.com>

Reviewed-by: Josh Triplett <josh@joshtriplett.org>

>  kernel/rcutree.c |  260 +++++++++++++++++++++++++++++-------------------------
>  1 files changed, 138 insertions(+), 122 deletions(-)
> 
> diff --git a/kernel/rcutree.c b/kernel/rcutree.c
> index 84a6f55..c2c036f 100644
> --- a/kernel/rcutree.c
> +++ b/kernel/rcutree.c
> @@ -1040,160 +1040,176 @@ 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 rcu_gp_kthread(void *arg)
> +static int rcu_gp_init(struct rcu_state *rsp)
>  {
>  	unsigned long flags;
> -	unsigned long gp_duration;
>  	struct rcu_data *rdp;
> -	struct rcu_node *rnp;
> -	struct rcu_state *rsp = arg;
> +	struct rcu_node *rnp = rcu_get_root(rsp);
>  
> -	for (;;) {
> +	raw_spin_lock_irqsave(&rnp->lock, flags);
> +	rsp->gp_flags = 0;
>  
> -		/* 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);
> -		}
> +	if (rcu_gp_in_progress(rsp)) {
> +		/* Grace period already in progress, don't start another. */
> +		raw_spin_unlock_irqrestore(&rnp->lock, flags);
> +		return 0;
> +	}
> +
> +	if (rsp->fqs_active) {
> +		/*
> +		 * We need a grace period, but force_quiescent_state()
> +		 * is running.  Tell it to start one on our behalf.
> +		 */
> +		rsp->fqs_need_gp = 1;
> +		raw_spin_unlock_irqrestore(&rnp->lock, flags);
> +		return 0;
> +	}
> +
> +	/* Advance to a new grace period and initialize state. */
> +	rsp->gpnum++;
> +	trace_rcu_grace_period(rsp->name, rsp->gpnum, "start");
> +	WARN_ON_ONCE(rsp->fqs_state == RCU_GP_INIT);
> +	rsp->fqs_state = RCU_GP_INIT; /* Stop force_quiescent_state. */
> +	rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS;
> +	record_gp_stall_check_time(rsp);
> +	raw_spin_unlock_irqrestore(&rnp->lock, flags);
> +
> +	/* Exclude any concurrent CPU-hotplug operations. */
> +	get_online_cpus();
> +
> +	/*
> +	 * 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, relying on the layout
> +	 * of the tree within the rsp->node[] array.  Note that other CPUs
> +	 * 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_irqsave(&rnp->lock, flags);
> -		rsp->gp_flags = 0;
>  		rdp = this_cpu_ptr(rsp->rda);
> +		rcu_preempt_check_blocked_tasks(rnp);
> +		rnp->qsmask = rnp->qsmaskinit;
> +		rnp->gpnum = rsp->gpnum;
> +		rnp->completed = rsp->completed;
> +		if (rnp == rdp->mynode)
> +			rcu_start_gp_per_cpu(rsp, rnp, rdp);
> +		rcu_preempt_boost_start_gp(rnp);
> +		trace_rcu_grace_period_init(rsp->name, rnp->gpnum,
> +					    rnp->level, rnp->grplo,
> +					    rnp->grphi, rnp->qsmask);
> +		raw_spin_unlock_irqrestore(&rnp->lock, flags);
> +		cond_resched();
> +	}
>  
> -		if (rcu_gp_in_progress(rsp)) {
> -			/*
> -			 * A grace period is already in progress, so
> -			 * don't start another one.
> -			 */
> -			raw_spin_unlock_irqrestore(&rnp->lock, flags);
> -			cond_resched();
> -			continue;
> -		}
> +	rnp = rcu_get_root(rsp);
> +	raw_spin_lock_irqsave(&rnp->lock, flags);
> +	/* force_quiescent_state() now OK. */
> +	rsp->fqs_state = RCU_SIGNAL_INIT;
> +	raw_spin_unlock_irqrestore(&rnp->lock, flags);
> +	put_online_cpus();
>  
> -		if (rsp->fqs_active) {
> -			/*
> -			 * We need a grace period, but force_quiescent_state()
> -			 * is running.  Tell it to start one on our behalf.
> -			 */
> -			rsp->fqs_need_gp = 1;
> -			raw_spin_unlock_irqrestore(&rnp->lock, flags);
> -			cond_resched();
> -			continue;
> -		}
> +	return 1;
> +}
>  
> -		/* Advance to a new grace period and initialize state. */
> -		rsp->gpnum++;
> -		trace_rcu_grace_period(rsp->name, rsp->gpnum, "start");
> -		WARN_ON_ONCE(rsp->fqs_state == RCU_GP_INIT);
> -		rsp->fqs_state = RCU_GP_INIT; /* Stop force_quiescent_state. */
> -		rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS;
> -		record_gp_stall_check_time(rsp);
> -		raw_spin_unlock_irqrestore(&rnp->lock, flags);
> +/*
> + * Clean up after the old grace period.
> + */
> +static int rcu_gp_cleanup(struct rcu_state *rsp)
> +{
> +	unsigned long flags;
> +	unsigned long gp_duration;
> +	struct rcu_data *rdp;
> +	struct rcu_node *rnp = rcu_get_root(rsp);
>  
> -		/* Exclude any concurrent CPU-hotplug operations. */
> -		get_online_cpus();
> +	raw_spin_lock_irqsave(&rnp->lock, flags);
> +	gp_duration = jiffies - rsp->gp_start;
> +	if (gp_duration > rsp->gp_max)
> +		rsp->gp_max = gp_duration;
> +
> +	/*
> +	 * We know the grace period is complete, but to everyone else
> +	 * it appears to still be ongoing.  But it is also the case
> +	 * that to everyone else it looks like there is nothing that
> +	 * they can do to advance the grace period.  It is therefore
> +	 * safe for us to drop the lock in order to mark the grace
> +	 * period as completed in all of the rcu_node structures.
> +	 *
> +	 * But if this CPU needs another grace period, it will take
> +	 * care of this while initializing the next grace period.
> +	 * We use RCU_WAIT_TAIL instead of the usual RCU_DONE_TAIL
> +	 * because the callbacks have not yet been advanced: Those
> +	 * 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_irqrestore(&rnp->lock, flags);
>  
>  		/*
> -		 * 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.
> -		 *
> -		 * Note that the grace period cannot complete until
> -		 * we finish the initialization process, as there will
> -		 * be at least one qsmask bit set in the root node until
> -		 * that time, namely the one corresponding to this CPU,
> -		 * due to the fact that we have irqs disabled.
> +		 * Propagate new ->completed value to rcu_node
> +		 * structures so that other CPUs don't have to
> +		 * wait until the start of the next grace period
> +		 * to process their callbacks.
>  		 */
>  		rcu_for_each_node_breadth_first(rsp, rnp) {
>  			raw_spin_lock_irqsave(&rnp->lock, flags);
> -			rcu_preempt_check_blocked_tasks(rnp);
> -			rnp->qsmask = rnp->qsmaskinit;
> -			rnp->gpnum = rsp->gpnum;
> -			rnp->completed = rsp->completed;
> -			if (rnp == rdp->mynode)
> -				rcu_start_gp_per_cpu(rsp, rnp, rdp);
> -			rcu_preempt_boost_start_gp(rnp);
> -			trace_rcu_grace_period_init(rsp->name, rnp->gpnum,
> -						    rnp->level, rnp->grplo,
> -						    rnp->grphi, rnp->qsmask);
> +			rnp->completed = rsp->gpnum;
>  			raw_spin_unlock_irqrestore(&rnp->lock, flags);
>  			cond_resched();
>  		}
> -
>  		rnp = rcu_get_root(rsp);
>  		raw_spin_lock_irqsave(&rnp->lock, flags);
> -		/* force_quiescent_state() now OK. */
> -		rsp->fqs_state = RCU_SIGNAL_INIT;
> -		raw_spin_unlock_irqrestore(&rnp->lock, flags);
> -		put_online_cpus();
> +	}
> +
> +	rsp->completed = rsp->gpnum; /* Declare grace period done. */
> +	trace_rcu_grace_period(rsp->name, rsp->completed, "end");
> +	rsp->fqs_state = RCU_GP_IDLE;
> +	rdp = this_cpu_ptr(rsp->rda);
> +	if (cpu_needs_another_gp(rsp, rdp))
> +		rsp->gp_flags = 1;
> +	raw_spin_unlock_irqrestore(&rnp->lock, flags);
> +	return 1;
> +}
> +
> +/*
> + * Body of kthread that handles grace periods.
> + */
> +static int 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_preempt_blocked_readers_cgp(rnp) &&
> +			    rcu_gp_cleanup(rsp))
>  				break;
> +			cond_resched();
>  			flush_signals(current);
>  		}
> -
> -		raw_spin_lock_irqsave(&rnp->lock, flags);
> -		gp_duration = jiffies - rsp->gp_start;
> -		if (gp_duration > rsp->gp_max)
> -			rsp->gp_max = gp_duration;
> -
> -		/*
> -		 * We know the grace period is complete, but to everyone else
> -		 * it appears to still be ongoing.  But it is also the case
> -		 * that to everyone else it looks like there is nothing that
> -		 * they can do to advance the grace period.  It is therefore
> -		 * safe for us to drop the lock in order to mark the grace
> -		 * period as completed in all of the rcu_node structures.
> -		 *
> -		 * But if this CPU needs another grace period, it will take
> -		 * care of this while initializing the next grace period.
> -		 * We use RCU_WAIT_TAIL instead of the usual RCU_DONE_TAIL
> -		 * because the callbacks have not yet been advanced: Those
> -		 * callbacks are waiting on the grace period that just now
> -		 * completed.
> -		 */
> -		if (*rdp->nxttail[RCU_WAIT_TAIL] == NULL) {
> -			raw_spin_unlock_irqrestore(&rnp->lock, flags);
> -
> -			/*
> -			 * Propagate new ->completed value to rcu_node
> -			 * structures so that other CPUs don't have to
> -			 * wait until the start of the next grace period
> -			 * to process their callbacks.
> -			 */
> -			rcu_for_each_node_breadth_first(rsp, rnp) {
> -				raw_spin_lock_irqsave(&rnp->lock, flags);
> -				rnp->completed = rsp->gpnum;
> -				raw_spin_unlock_irqrestore(&rnp->lock, flags);
> -				cond_resched();
> -			}
> -			rnp = rcu_get_root(rsp);
> -			raw_spin_lock_irqsave(&rnp->lock, flags);
> -		}
> -
> -		rsp->completed = rsp->gpnum; /* Declare grace period done. */
> -		trace_rcu_grace_period(rsp->name, rsp->completed, "end");
> -		rsp->fqs_state = RCU_GP_IDLE;
> -		if (cpu_needs_another_gp(rsp, rdp))
> -			rsp->gp_flags = 1;
> -		raw_spin_unlock_irqrestore(&rnp->lock, flags);
>  	}
>  	return 0;
>  }
> -- 
> 1.7.8
> 

  reply	other threads:[~2012-09-02  2:11 UTC|newest]

Thread overview: 86+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-30 18:18 [PATCH tip/core/rcu 0/23] Improvements to RT response on big systems and expedited functions Paul E. McKenney
2012-08-30 18:18 ` [PATCH tip/core/rcu 01/23] rcu: Move RCU grace-period initialization into a kthread Paul E. McKenney
2012-08-30 18:18   ` [PATCH tip/core/rcu 02/23] rcu: Allow RCU grace-period initialization to be preempted Paul E. McKenney
2012-09-02  1:09     ` Josh Triplett
2012-09-05  1:22       ` Paul E. McKenney
2012-08-30 18:18   ` [PATCH tip/core/rcu 03/23] rcu: Move RCU grace-period cleanup into kthread Paul E. McKenney
2012-09-02  1:22     ` Josh Triplett
2012-09-06 13:34     ` Peter Zijlstra
2012-09-06 17:29       ` Paul E. McKenney
2012-08-30 18:18   ` [PATCH tip/core/rcu 04/23] rcu: Allow RCU grace-period cleanup to be preempted Paul E. McKenney
2012-09-02  1:36     ` Josh Triplett
2012-08-30 18:18   ` [PATCH tip/core/rcu 05/23] rcu: Prevent offline CPUs from executing RCU core code Paul E. McKenney
2012-09-02  1:45     ` Josh Triplett
2012-08-30 18:18   ` [PATCH tip/core/rcu 06/23] rcu: Break up rcu_gp_kthread() into subfunctions Paul E. McKenney
2012-09-02  2:11     ` Josh Triplett [this message]
2012-09-06 13:39     ` Peter Zijlstra
2012-09-06 17:32       ` Paul E. McKenney
2012-09-06 18:49         ` Josh Triplett
2012-09-06 19:09           ` Peter Zijlstra
2012-09-06 20:30             ` Paul E. McKenney
2012-09-06 20:30           ` Paul E. McKenney
2012-08-30 18:18   ` [PATCH tip/core/rcu 07/23] rcu: Provide OOM handler to motivate lazy RCU callbacks Paul E. McKenney
2012-09-02  2:13     ` Josh Triplett
2012-09-03  9:08     ` Lai Jiangshan
2012-09-05 17:45       ` Paul E. McKenney
2012-09-06 13:46     ` Peter Zijlstra
2012-09-06 13:52       ` Steven Rostedt
2012-09-06 17:41         ` Paul E. McKenney
2012-09-06 17:46           ` Peter Zijlstra
2012-09-06 20:32             ` Paul E. McKenney
2012-08-30 18:18   ` [PATCH tip/core/rcu 08/23] rcu: Segregate rcu_state fields to improve cache locality Paul E. McKenney
2012-09-02  2:51     ` Josh Triplett
2012-08-30 18:18   ` [PATCH tip/core/rcu 09/23] rcu: Move quiescent-state forcing into kthread Paul E. McKenney
2012-08-30 18:18   ` [PATCH tip/core/rcu 10/23] rcu: Allow RCU quiescent-state forcing to be preempted Paul E. McKenney
2012-09-02  5:23     ` Josh Triplett
2012-08-30 18:18   ` [PATCH tip/core/rcu 11/23] rcu: Adjust debugfs tracing for kthread-based quiescent-state forcing Paul E. McKenney
2012-09-02  6:05     ` Josh Triplett
2012-08-30 18:18   ` [PATCH tip/core/rcu 12/23] rcu: Prevent force_quiescent_state() memory contention Paul E. McKenney
2012-09-02 10:47     ` Josh Triplett
2012-08-30 18:18   ` [PATCH tip/core/rcu 13/23] rcu: Control grace-period duration from sysfs Paul E. McKenney
2012-09-03  9:30     ` Josh Triplett
2012-09-03  9:31       ` Josh Triplett
2012-09-06 14:15     ` Peter Zijlstra
2012-09-06 17:53       ` Paul E. McKenney
2012-09-06 18:28         ` Peter Zijlstra
2012-09-06 20:37           ` Paul E. McKenney
2012-08-30 18:18   ` [PATCH tip/core/rcu 14/23] rcu: Remove now-unused rcu_state fields Paul E. McKenney
2012-09-03  9:31     ` Josh Triplett
2012-09-06 14:17     ` Peter Zijlstra
2012-09-06 18:02       ` Paul E. McKenney
2012-08-30 18:18   ` [PATCH tip/core/rcu 15/23] rcu: Make rcutree module parameters visible in sysfs Paul E. McKenney
2012-09-03  9:32     ` Josh Triplett
2012-08-30 18:18   ` [PATCH tip/core/rcu 16/23] rcu: Prevent initialization-time quiescent-state race Paul E. McKenney
2012-09-03  9:37     ` Josh Triplett
2012-09-05 18:19       ` Paul E. McKenney
2012-09-05 18:55         ` Josh Triplett
2012-09-05 19:49           ` Paul E. McKenney
2012-09-06 14:21         ` Peter Zijlstra
2012-09-06 16:18           ` Paul E. McKenney
2012-09-06 16:22             ` Peter Zijlstra
2012-08-30 18:18   ` [PATCH tip/core/rcu 17/23] rcu: Fix day-zero grace-period initialization/cleanup race Paul E. McKenney
2012-09-03  9:39     ` Josh Triplett
2012-09-06 14:24     ` Peter Zijlstra
2012-09-06 18:06       ` Paul E. McKenney
2012-08-30 18:18   ` [PATCH tip/core/rcu 18/23] rcu: Add random PROVE_RCU_DELAY to grace-period initialization Paul E. McKenney
2012-09-03  9:41     ` Josh Triplett
2012-09-06 14:27     ` Peter Zijlstra
2012-09-06 18:25       ` Paul E. McKenney
2012-08-30 18:18   ` [PATCH tip/core/rcu 19/23] rcu: Adjust for unconditional ->completed assignment Paul E. McKenney
2012-09-03  9:42     ` Josh Triplett
2012-08-30 18:18   ` [PATCH tip/core/rcu 20/23] rcu: Remove callback acceleration from grace-period initialization Paul E. McKenney
2012-09-03  9:42     ` Josh Triplett
2012-08-30 18:18   ` [PATCH tip/core/rcu 21/23] rcu: Eliminate signed overflow in synchronize_rcu_expedited() Paul E. McKenney
2012-09-03  9:43     ` Josh Triplett
2012-08-30 18:18   ` [PATCH tip/core/rcu 22/23] rcu: Reduce synchronize_rcu_expedited() latency Paul E. McKenney
2012-09-03  9:46     ` Josh Triplett
2012-08-30 18:18   ` [PATCH tip/core/rcu 23/23] rcu: Simplify quiescent-state detection Paul E. McKenney
2012-09-03  9:56     ` Josh Triplett
2012-09-06 14:36     ` Peter Zijlstra
2012-09-06 20:01       ` Paul E. McKenney
2012-09-06 21:18         ` Mathieu Desnoyers
2012-09-06 21:31           ` Paul E. McKenney
2012-09-02  1:04   ` [PATCH tip/core/rcu 01/23] rcu: Move RCU grace-period initialization into a kthread Josh Triplett
2012-09-06 13:32   ` Peter Zijlstra
2012-09-06 17:00     ` Paul E. McKenney
2012-09-20 18:47 [PATCH tip/core/rcu 0/23] v2 Improvements to RT response on big systems and expedited functions Paul E. McKenney
2012-09-20 18:47 ` [PATCH tip/core/rcu 01/23] rcu: Move RCU grace-period initialization into a kthread Paul E. McKenney
2012-09-20 18:48   ` [PATCH tip/core/rcu 06/23] rcu: Break up rcu_gp_kthread() into subfunctions Paul E. McKenney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120902021121.GF5713@leaf \
    --to=josh@joshtriplett.org \
    --cc=Valdis.Kletnieks@vt.edu \
    --cc=akpm@linux-foundation.org \
    --cc=darren@dvhart.com \
    --cc=dhowells@redhat.com \
    --cc=dipankar@in.ibm.com \
    --cc=eric.dumazet@gmail.com \
    --cc=fweisbec@gmail.com \
    --cc=laijs@cn.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mathieu.desnoyers@polymtl.ca \
    --cc=mingo@elte.hu \
    --cc=niv@us.ibm.com \
    --cc=patches@linaro.org \
    --cc=paulmck@linux.vnet.ibm.com \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=sbw@mit.edu \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.