netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
To: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
	netfilter-devel@vger.kernel.org, mingo@elte.hu,
	akpm@linux-foundation.org, torvalds@linux-foundation.org,
	davem@davemloft.net, dada1@cosmosbay.com, zbr@ioremap.net,
	jeff.chua.linux@gmail.com, paulus@samba.org,
	laijs@cn.fujitsu.com, jengelh@medozas.de, r000n@r000n.net,
	benh@kernel.crashing.org
Subject: Re: [PATCH RFC] v2 not-so-expedited "big hammer" RCU grace periods
Date: Wed, 29 Apr 2009 09:34:49 -0400	[thread overview]
Message-ID: <20090429133449.GB1966@Krystal> (raw)
In-Reply-To: <20090429132323.GG6808@linux.vnet.ibm.com>

* Paul E. McKenney (paulmck@linux.vnet.ibm.com) wrote:
> On Wed, Apr 29, 2009 at 01:58:40AM -0400, Mathieu Desnoyers wrote:
> > * Paul E. McKenney (paulmck@linux.vnet.ibm.com) wrote:
> 
> [ . . . ]
> 
> > > +
> > > +		/*
> > > +		 * Wait a bit.  If we have already waited a fair
> > > +		 * amount of time, sleep.
> > > +		 */
> > > +		if (++times < 10)
> > > +			udelay(10 * times);
> > > +		else
> > > +			schedule_timeout_uninterruptible(1);
> > 
> > Waiting a whole jiffy (e.g. 1ms, 4ms, 10ms) here seems like a big hammer
> > to nail a delicate pin. I would not be surprised if your long delay
> > would come from here. Is it possible that your ipi+scheduling delay is
> > actually longer than the 11 udelays you are doing and that you end up
> > calling schedule_timeout_uninterruptible(1) each time ?
> 
> It might be -- easy to try increasing the number of udelay passes
> through the loop.
> 

Or just counting the number of times schedule_timeout_uninterruptible()
is invoked from here.

> On the other hand, the 550 microseconds waited by the sum of the udelay
> passes is ridiculously long in and of itself.
> 
> Still, would be interesting to know.  I will change the loop to udelay
> up to HZ.  Hmmm...  I wonder if udelay() itself is turning into a 1-HZ
> wait beyond a certain point.
>

It does not seem to be the case in arch/x86/lib/delay.c at least.

Mathieu
 
> 							Thanx, Paul
> 
> > Mathieu
> > 
> > > +		/* FIXME: need to complain about holdout CPUs if too long. */
> > > +	}
> > > +
> > > +	synchronize_rcu_bh_completed++;
> > > +	mutex_unlock(&synchronize_rcu_bh_mutex);
> > > +}
> > > +EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
> > > +
> > > +void synchronize_rcu_bh_expedited(void)
> > > +{
> > > +	synchronize_rcu_expedited();
> > > +}
> > > +EXPORT_SYMBOL_GPL(synchronize_rcu_bh_expedited);
> > > +
> > > +#endif /* #else #ifndef CONFIG_SMP */
> > > +
> > >  void __init rcu_init(void)
> > >  {
> > >  	__rcu_init();
> > >  	hotcpu_notifier(rcu_barrier_cpu_hotplug, 0);
> > > +	synchronize_rcu_expedited_init();
> > >  }
> > >  
> > >  void rcu_scheduler_starting(void)
> > > diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
> > > index 9b4a975..8845936 100644
> > > --- a/kernel/rcutorture.c
> > > +++ b/kernel/rcutorture.c
> > > @@ -257,14 +257,14 @@ struct rcu_torture_ops {
> > >  	void (*init)(void);
> > >  	void (*cleanup)(void);
> > >  	int (*readlock)(void);
> > > -	void (*readdelay)(struct rcu_random_state *rrsp);
> > > +	void (*read_delay)(struct rcu_random_state *rrsp);
> > >  	void (*readunlock)(int idx);
> > >  	int (*completed)(void);
> > > -	void (*deferredfree)(struct rcu_torture *p);
> > > +	void (*deferred_free)(struct rcu_torture *p);
> > >  	void (*sync)(void);
> > >  	void (*cb_barrier)(void);
> > >  	int (*stats)(char *page);
> > > -	int irqcapable;
> > > +	int irq_capable;
> > >  	char *name;
> > >  };
> > >  static struct rcu_torture_ops *cur_ops = NULL;
> > > @@ -320,7 +320,7 @@ rcu_torture_cb(struct rcu_head *p)
> > >  		rp->rtort_mbtest = 0;
> > >  		rcu_torture_free(rp);
> > >  	} else
> > > -		cur_ops->deferredfree(rp);
> > > +		cur_ops->deferred_free(rp);
> > >  }
> > >  
> > >  static void rcu_torture_deferred_free(struct rcu_torture *p)
> > > @@ -329,18 +329,18 @@ static void rcu_torture_deferred_free(struct rcu_torture *p)
> > >  }
> > >  
> > >  static struct rcu_torture_ops rcu_ops = {
> > > -	.init = NULL,
> > > -	.cleanup = NULL,
> > > -	.readlock = rcu_torture_read_lock,
> > > -	.readdelay = rcu_read_delay,
> > > -	.readunlock = rcu_torture_read_unlock,
> > > -	.completed = rcu_torture_completed,
> > > -	.deferredfree = rcu_torture_deferred_free,
> > > -	.sync = synchronize_rcu,
> > > -	.cb_barrier = rcu_barrier,
> > > -	.stats = NULL,
> > > -	.irqcapable = 1,
> > > -	.name = "rcu"
> > > +	.init		= NULL,
> > > +	.cleanup	= NULL,
> > > +	.readlock	= rcu_torture_read_lock,
> > > +	.read_delay	= rcu_read_delay,
> > > +	.readunlock	= rcu_torture_read_unlock,
> > > +	.completed	= rcu_torture_completed,
> > > +	.deferred_free	= rcu_torture_deferred_free,
> > > +	.sync		= synchronize_rcu,
> > > +	.cb_barrier	= rcu_barrier,
> > > +	.stats		= NULL,
> > > +	.irq_capable 	= 1,
> > > +	.name 		= "rcu"
> > >  };
> > >  
> > >  static void rcu_sync_torture_deferred_free(struct rcu_torture *p)
> > > @@ -370,18 +370,18 @@ static void rcu_sync_torture_init(void)
> > >  }
> > >  
> > >  static struct rcu_torture_ops rcu_sync_ops = {
> > > -	.init = rcu_sync_torture_init,
> > > -	.cleanup = NULL,
> > > -	.readlock = rcu_torture_read_lock,
> > > -	.readdelay = rcu_read_delay,
> > > -	.readunlock = rcu_torture_read_unlock,
> > > -	.completed = rcu_torture_completed,
> > > -	.deferredfree = rcu_sync_torture_deferred_free,
> > > -	.sync = synchronize_rcu,
> > > -	.cb_barrier = NULL,
> > > -	.stats = NULL,
> > > -	.irqcapable = 1,
> > > -	.name = "rcu_sync"
> > > +	.init		= rcu_sync_torture_init,
> > > +	.cleanup	= NULL,
> > > +	.readlock	= rcu_torture_read_lock,
> > > +	.read_delay	= rcu_read_delay,
> > > +	.readunlock	= rcu_torture_read_unlock,
> > > +	.completed	= rcu_torture_completed,
> > > +	.deferred_free	= rcu_sync_torture_deferred_free,
> > > +	.sync		= synchronize_rcu,
> > > +	.cb_barrier	= NULL,
> > > +	.stats		= NULL,
> > > +	.irq_capable	= 1,
> > > +	.name		= "rcu_sync"
> > >  };
> > >  
> > >  /*
> > > @@ -432,33 +432,53 @@ static void rcu_bh_torture_synchronize(void)
> > >  }
> > >  
> > >  static struct rcu_torture_ops rcu_bh_ops = {
> > > -	.init = NULL,
> > > -	.cleanup = NULL,
> > > -	.readlock = rcu_bh_torture_read_lock,
> > > -	.readdelay = rcu_read_delay,  /* just reuse rcu's version. */
> > > -	.readunlock = rcu_bh_torture_read_unlock,
> > > -	.completed = rcu_bh_torture_completed,
> > > -	.deferredfree = rcu_bh_torture_deferred_free,
> > > -	.sync = rcu_bh_torture_synchronize,
> > > -	.cb_barrier = rcu_barrier_bh,
> > > -	.stats = NULL,
> > > -	.irqcapable = 1,
> > > -	.name = "rcu_bh"
> > > +	.init		= NULL,
> > > +	.cleanup	= NULL,
> > > +	.readlock	= rcu_bh_torture_read_lock,
> > > +	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
> > > +	.readunlock	= rcu_bh_torture_read_unlock,
> > > +	.completed	= rcu_bh_torture_completed,
> > > +	.deferred_free	= rcu_bh_torture_deferred_free,
> > > +	.sync		= rcu_bh_torture_synchronize,
> > > +	.cb_barrier	= rcu_barrier_bh,
> > > +	.stats		= NULL,
> > > +	.irq_capable	= 1,
> > > +	.name		= "rcu_bh"
> > >  };
> > >  
> > >  static struct rcu_torture_ops rcu_bh_sync_ops = {
> > > -	.init = rcu_sync_torture_init,
> > > -	.cleanup = NULL,
> > > -	.readlock = rcu_bh_torture_read_lock,
> > > -	.readdelay = rcu_read_delay,  /* just reuse rcu's version. */
> > > -	.readunlock = rcu_bh_torture_read_unlock,
> > > -	.completed = rcu_bh_torture_completed,
> > > -	.deferredfree = rcu_sync_torture_deferred_free,
> > > -	.sync = rcu_bh_torture_synchronize,
> > > -	.cb_barrier = NULL,
> > > -	.stats = NULL,
> > > -	.irqcapable = 1,
> > > -	.name = "rcu_bh_sync"
> > > +	.init		= rcu_sync_torture_init,
> > > +	.cleanup	= NULL,
> > > +	.readlock	= rcu_bh_torture_read_lock,
> > > +	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
> > > +	.readunlock	= rcu_bh_torture_read_unlock,
> > > +	.completed	= rcu_bh_torture_completed,
> > > +	.deferred_free	= rcu_sync_torture_deferred_free,
> > > +	.sync		= rcu_bh_torture_synchronize,
> > > +	.cb_barrier	= NULL,
> > > +	.stats		= NULL,
> > > +	.irq_capable	= 1,
> > > +	.name		= "rcu_bh_sync"
> > > +};
> > > +
> > > +static int rcu_bh_expedited_torture_completed(void)
> > > +{
> > > +	return rcu_batches_completed_bh_expedited();
> > > +}
> > > +
> > > +static struct rcu_torture_ops rcu_bh_expedited_ops = {
> > > +	.init		= rcu_sync_torture_init,
> > > +	.cleanup	= NULL,
> > > +	.readlock	= rcu_bh_torture_read_lock,
> > > +	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
> > > +	.readunlock	= rcu_bh_torture_read_unlock,
> > > +	.completed	= rcu_bh_expedited_torture_completed,
> > > +	.deferred_free	= rcu_sync_torture_deferred_free,
> > > +	.sync		= synchronize_rcu_bh_expedited,
> > > +	.cb_barrier	= NULL,
> > > +	.stats		= NULL,
> > > +	.irq_capable	= 1,
> > > +	.name		= "rcu_bh_expedited"
> > >  };
> > >  
> > >  /*
> > > @@ -530,17 +550,17 @@ static int srcu_torture_stats(char *page)
> > >  }
> > >  
> > >  static struct rcu_torture_ops srcu_ops = {
> > > -	.init = srcu_torture_init,
> > > -	.cleanup = srcu_torture_cleanup,
> > > -	.readlock = srcu_torture_read_lock,
> > > -	.readdelay = srcu_read_delay,
> > > -	.readunlock = srcu_torture_read_unlock,
> > > -	.completed = srcu_torture_completed,
> > > -	.deferredfree = rcu_sync_torture_deferred_free,
> > > -	.sync = srcu_torture_synchronize,
> > > -	.cb_barrier = NULL,
> > > -	.stats = srcu_torture_stats,
> > > -	.name = "srcu"
> > > +	.init		= srcu_torture_init,
> > > +	.cleanup	= srcu_torture_cleanup,
> > > +	.readlock	= srcu_torture_read_lock,
> > > +	.read_delay	= srcu_read_delay,
> > > +	.readunlock	= srcu_torture_read_unlock,
> > > +	.completed	= srcu_torture_completed,
> > > +	.deferred_free	= rcu_sync_torture_deferred_free,
> > > +	.sync		= srcu_torture_synchronize,
> > > +	.cb_barrier	= NULL,
> > > +	.stats		= srcu_torture_stats,
> > > +	.name		= "srcu"
> > >  };
> > >  
> > >  /*
> > > @@ -574,32 +594,32 @@ static void sched_torture_synchronize(void)
> > >  }
> > >  
> > >  static struct rcu_torture_ops sched_ops = {
> > > -	.init = rcu_sync_torture_init,
> > > -	.cleanup = NULL,
> > > -	.readlock = sched_torture_read_lock,
> > > -	.readdelay = rcu_read_delay,  /* just reuse rcu's version. */
> > > -	.readunlock = sched_torture_read_unlock,
> > > -	.completed = sched_torture_completed,
> > > -	.deferredfree = rcu_sched_torture_deferred_free,
> > > -	.sync = sched_torture_synchronize,
> > > -	.cb_barrier = rcu_barrier_sched,
> > > -	.stats = NULL,
> > > -	.irqcapable = 1,
> > > -	.name = "sched"
> > > +	.init		= rcu_sync_torture_init,
> > > +	.cleanup	= NULL,
> > > +	.readlock	= sched_torture_read_lock,
> > > +	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
> > > +	.readunlock	= sched_torture_read_unlock,
> > > +	.completed	= sched_torture_completed,
> > > +	.deferred_free	= rcu_sched_torture_deferred_free,
> > > +	.sync		= sched_torture_synchronize,
> > > +	.cb_barrier	= rcu_barrier_sched,
> > > +	.stats		= NULL,
> > > +	.irq_capable	= 1,
> > > +	.name		= "sched"
> > >  };
> > >  
> > >  static struct rcu_torture_ops sched_ops_sync = {
> > > -	.init = rcu_sync_torture_init,
> > > -	.cleanup = NULL,
> > > -	.readlock = sched_torture_read_lock,
> > > -	.readdelay = rcu_read_delay,  /* just reuse rcu's version. */
> > > -	.readunlock = sched_torture_read_unlock,
> > > -	.completed = sched_torture_completed,
> > > -	.deferredfree = rcu_sync_torture_deferred_free,
> > > -	.sync = sched_torture_synchronize,
> > > -	.cb_barrier = NULL,
> > > -	.stats = NULL,
> > > -	.name = "sched_sync"
> > > +	.init		= rcu_sync_torture_init,
> > > +	.cleanup	= NULL,
> > > +	.readlock	= sched_torture_read_lock,
> > > +	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */
> > > +	.readunlock	= sched_torture_read_unlock,
> > > +	.completed	= sched_torture_completed,
> > > +	.deferred_free	= rcu_sync_torture_deferred_free,
> > > +	.sync		= sched_torture_synchronize,
> > > +	.cb_barrier	= NULL,
> > > +	.stats		= NULL,
> > > +	.name		= "sched_sync"
> > >  };
> > >  
> > >  /*
> > > @@ -635,7 +655,7 @@ rcu_torture_writer(void *arg)
> > >  				i = RCU_TORTURE_PIPE_LEN;
> > >  			atomic_inc(&rcu_torture_wcount[i]);
> > >  			old_rp->rtort_pipe_count++;
> > > -			cur_ops->deferredfree(old_rp);
> > > +			cur_ops->deferred_free(old_rp);
> > >  		}
> > >  		rcu_torture_current_version++;
> > >  		oldbatch = cur_ops->completed();
> > > @@ -700,7 +720,7 @@ static void rcu_torture_timer(unsigned long unused)
> > >  	if (p->rtort_mbtest == 0)
> > >  		atomic_inc(&n_rcu_torture_mberror);
> > >  	spin_lock(&rand_lock);
> > > -	cur_ops->readdelay(&rand);
> > > +	cur_ops->read_delay(&rand);
> > >  	n_rcu_torture_timers++;
> > >  	spin_unlock(&rand_lock);
> > >  	preempt_disable();
> > > @@ -738,11 +758,11 @@ rcu_torture_reader(void *arg)
> > >  
> > >  	VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
> > >  	set_user_nice(current, 19);
> > > -	if (irqreader && cur_ops->irqcapable)
> > > +	if (irqreader && cur_ops->irq_capable)
> > >  		setup_timer_on_stack(&t, rcu_torture_timer, 0);
> > >  
> > >  	do {
> > > -		if (irqreader && cur_ops->irqcapable) {
> > > +		if (irqreader && cur_ops->irq_capable) {
> > >  			if (!timer_pending(&t))
> > >  				mod_timer(&t, 1);
> > >  		}
> > > @@ -757,7 +777,7 @@ rcu_torture_reader(void *arg)
> > >  		}
> > >  		if (p->rtort_mbtest == 0)
> > >  			atomic_inc(&n_rcu_torture_mberror);
> > > -		cur_ops->readdelay(&rand);
> > > +		cur_ops->read_delay(&rand);
> > >  		preempt_disable();
> > >  		pipe_count = p->rtort_pipe_count;
> > >  		if (pipe_count > RCU_TORTURE_PIPE_LEN) {
> > > @@ -778,7 +798,7 @@ rcu_torture_reader(void *arg)
> > >  	} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
> > >  	VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping");
> > >  	rcutorture_shutdown_absorb("rcu_torture_reader");
> > > -	if (irqreader && cur_ops->irqcapable)
> > > +	if (irqreader && cur_ops->irq_capable)
> > >  		del_timer_sync(&t);
> > >  	while (!kthread_should_stop())
> > >  		schedule_timeout_uninterruptible(1);
> > > @@ -1078,6 +1098,7 @@ rcu_torture_init(void)
> > >  	int firsterr = 0;
> > >  	static struct rcu_torture_ops *torture_ops[] =
> > >  		{ &rcu_ops, &rcu_sync_ops, &rcu_bh_ops, &rcu_bh_sync_ops,
> > > +		  &rcu_bh_expedited_ops,
> > >  		  &srcu_ops, &sched_ops, &sched_ops_sync, };
> > >  
> > >  	mutex_lock(&fullstop_mutex);
> > > diff --git a/kernel/rcutree.c b/kernel/rcutree.c
> > > index d2a372f..bf2c21d 100644
> > > --- a/kernel/rcutree.c
> > > +++ b/kernel/rcutree.c
> > > @@ -89,6 +89,7 @@ void rcu_qsctr_inc(int cpu)
> > >  	struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
> > >  	rdp->passed_quiesc = 1;
> > >  	rdp->passed_quiesc_completed = rdp->completed;
> > > +	synchronize_rcu_expedited_qs(cpu);
> > >  }
> > >  
> > >  void rcu_bh_qsctr_inc(int cpu)
> > 
> > -- 
> > Mathieu Desnoyers
> > OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68
> > --
> > To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Mathieu Desnoyers
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F  BA06 3F25 A8FE 3BAE 9A68

      reply	other threads:[~2009-04-29 13:35 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-04-29  4:53 [PATCH RFC] v2 not-so-expedited "big hammer" RCU grace periods Paul E. McKenney
2009-04-29  5:58 ` Mathieu Desnoyers
2009-04-29 13:23   ` Paul E. McKenney
2009-04-29 13:34     ` Mathieu Desnoyers [this message]

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=20090429133449.GB1966@Krystal \
    --to=mathieu.desnoyers@polymtl.ca \
    --cc=akpm@linux-foundation.org \
    --cc=benh@kernel.crashing.org \
    --cc=dada1@cosmosbay.com \
    --cc=davem@davemloft.net \
    --cc=jeff.chua.linux@gmail.com \
    --cc=jengelh@medozas.de \
    --cc=laijs@cn.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=paulmck@linux.vnet.ibm.com \
    --cc=paulus@samba.org \
    --cc=r000n@r000n.net \
    --cc=torvalds@linux-foundation.org \
    --cc=zbr@ioremap.net \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).