Re: [PATCH tip/core/rcu 01/19] rcu: Refactor rcu_{nmi,irq}_{enter,exit}()

2018-08-30 Thread Byungchul Park
On Thu, Aug 30, 2018 at 02:10:32PM -0400, Steven Rostedt wrote:
> On Wed, 29 Aug 2018 15:20:29 -0700
> "Paul E. McKenney"  wrote:
> 
> > This commit also changes order of execution from this:
> > 
> > rcu_dynticks_task_exit();
> > rcu_dynticks_eqs_exit();
> > trace_rcu_dyntick();
> > rcu_cleanup_after_idle();
> > 
> > To this:
> > 
> > rcu_dynticks_task_exit();
> > rcu_dynticks_eqs_exit();
> > rcu_cleanup_after_idle();
> > trace_rcu_dyntick();
> > 
> > In other words, the calls to trace_rcu_dyntick() and trace_rcu_dyntick()
> 
> How is trace_rcu_dyntick() and trace_rcu_dyntick reversed ? ;-)
> 
> > are reversed.  This has no functional effect because the real
> > concern is whether a given call is before or after the call to
> > rcu_dynticks_eqs_exit(), and this patch does not change that.  Before the
> > call to rcu_dynticks_eqs_exit(), RCU is not yet watching the current
> > CPU and after that call RCU is watching.
> > 
> > A similar switch in calling order happens on the idle-entry path, with
> > similar lack of effect for the same reasons.
> > 
> > Suggested-by: Paul E. McKenney 
> > Signed-off-by: Byungchul Park 
> > Signed-off-by: Paul E. McKenney 
> > ---
> >  kernel/rcu/tree.c | 61 +++
> >  1 file changed, 41 insertions(+), 20 deletions(-)
> > 
> > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> > index 0b760c1369f7..0adf77923e8b 100644
> > --- a/kernel/rcu/tree.c
> > +++ b/kernel/rcu/tree.c
> > @@ -771,17 +771,18 @@ void rcu_user_enter(void)
> >  #endif /* CONFIG_NO_HZ_FULL */
> >  
> >  /**
> > - * rcu_nmi_exit - inform RCU of exit from NMI context
> > + * rcu_nmi_exit_common - inform RCU of exit from NMI context
> > + * @irq: Is this call from rcu_irq_exit?
> >   *
> >   * If we are returning from the outermost NMI handler that interrupted an
> >   * RCU-idle period, update rdtp->dynticks and rdtp->dynticks_nmi_nesting
> >   * to let the RCU grace-period handling know that the CPU is back to
> >   * being RCU-idle.
> >   *
> > - * If you add or remove a call to rcu_nmi_exit(), be sure to test
> > + * If you add or remove a call to rcu_nmi_exit_common(), be sure to test
> >   * with CONFIG_RCU_EQS_DEBUG=y.
> 
> As this is a static function, this description doesn't make sense. You
> need to move the description down to the new rcu_nmi_exit() below.

Right.. I should've done that.

Thanks you Steve.

Byungchul

> Other than that...
> 
> Reviewed-by: Steven Rostedt (VMware) 
> 
> -- Steve
> 
> 
> >   */
> > -void rcu_nmi_exit(void)
> > +static __always_inline void rcu_nmi_exit_common(bool irq)
> >  {
> > struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
> >  
> > @@ -807,7 +808,22 @@ void rcu_nmi_exit(void)
> > /* This NMI interrupted an RCU-idle CPU, restore RCU-idleness. */
> > trace_rcu_dyntick(TPS("Startirq"), rdtp->dynticks_nmi_nesting, 0, 
> > rdtp->dynticks);
> > WRITE_ONCE(rdtp->dynticks_nmi_nesting, 0); /* Avoid store tearing. */
> > +
> > +   if (irq)
> > +   rcu_prepare_for_idle();
> > +
> > rcu_dynticks_eqs_enter();
> > +
> > +   if (irq)
> > +   rcu_dynticks_task_enter();
> > +}
> > +
> > +/**
> > + * rcu_nmi_exit - inform RCU of exit from NMI context
> > + */
> > +void rcu_nmi_exit(void)
> > +{
> > +   rcu_nmi_exit_common(false);
> >  }
> >  
> >  /**
> > @@ -831,14 +847,8 @@ void rcu_nmi_exit(void)
> >   */
> >  void rcu_irq_exit(void)
> >  {
> > -   struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
> > -
> > lockdep_assert_irqs_disabled();
> > -   if (rdtp->dynticks_nmi_nesting == 1)
> > -   rcu_prepare_for_idle();
> > -   rcu_nmi_exit();
> > -   if (rdtp->dynticks_nmi_nesting == 0)
> > -   rcu_dynticks_task_enter();
> > +   rcu_nmi_exit_common(true);
> >  }
> >  
> >  /*
> > @@ -921,7 +931,8 @@ void rcu_user_exit(void)
> >  #endif /* CONFIG_NO_HZ_FULL */
> >  
> >  /**
> > - * rcu_nmi_enter - inform RCU of entry to NMI context
> > + * rcu_nmi_enter_common - inform RCU of entry to NMI context
> > + * @irq: Is this call from rcu_irq_enter?
> >   *
> >   * If the CPU was idle from RCU's viewpoint, update rdtp->dynticks and
> >   * rdtp->dynticks_nmi_nesting to let the RCU grace-period handling know
> > @@ -929,10 +940,10 @@ void rcu_user_exit(void)
> >   * long as the nesting level does not overflow an int.  (You will probably
> >   * run out of stack space first.)
> >   *
> > - * If you add or remove a call to rcu_nmi_enter(), be sure to test
> > + * If you add or remove a call to rcu_nmi_enter_common(), be sure to test
> >   * with CONFIG_RCU_EQS_DEBUG=y.
> >   */
> > -void rcu_nmi_enter(void)
> > +static __always_inline void rcu_nmi_enter_common(bool irq)
> >  {
> > struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
> > long incby = 2;
> > @@ -949,7 +960,15 @@ void rcu_nmi_enter(void)
> >  * period (observation due to Andy Lutomirski).
> >  */
> > if (rcu_dynticks_curr_cpu_in_eqs()) {
> > +
> > +   if (irq)
> > 

Re: [PATCH tip/core/rcu 01/19] rcu: Refactor rcu_{nmi,irq}_{enter,exit}()

2018-08-30 Thread Byungchul Park
On Thu, Aug 30, 2018 at 02:10:32PM -0400, Steven Rostedt wrote:
> On Wed, 29 Aug 2018 15:20:29 -0700
> "Paul E. McKenney"  wrote:
> 
> > This commit also changes order of execution from this:
> > 
> > rcu_dynticks_task_exit();
> > rcu_dynticks_eqs_exit();
> > trace_rcu_dyntick();
> > rcu_cleanup_after_idle();
> > 
> > To this:
> > 
> > rcu_dynticks_task_exit();
> > rcu_dynticks_eqs_exit();
> > rcu_cleanup_after_idle();
> > trace_rcu_dyntick();
> > 
> > In other words, the calls to trace_rcu_dyntick() and trace_rcu_dyntick()
> 
> How is trace_rcu_dyntick() and trace_rcu_dyntick reversed ? ;-)
> 
> > are reversed.  This has no functional effect because the real
> > concern is whether a given call is before or after the call to
> > rcu_dynticks_eqs_exit(), and this patch does not change that.  Before the
> > call to rcu_dynticks_eqs_exit(), RCU is not yet watching the current
> > CPU and after that call RCU is watching.
> > 
> > A similar switch in calling order happens on the idle-entry path, with
> > similar lack of effect for the same reasons.
> > 
> > Suggested-by: Paul E. McKenney 
> > Signed-off-by: Byungchul Park 
> > Signed-off-by: Paul E. McKenney 
> > ---
> >  kernel/rcu/tree.c | 61 +++
> >  1 file changed, 41 insertions(+), 20 deletions(-)
> > 
> > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> > index 0b760c1369f7..0adf77923e8b 100644
> > --- a/kernel/rcu/tree.c
> > +++ b/kernel/rcu/tree.c
> > @@ -771,17 +771,18 @@ void rcu_user_enter(void)
> >  #endif /* CONFIG_NO_HZ_FULL */
> >  
> >  /**
> > - * rcu_nmi_exit - inform RCU of exit from NMI context
> > + * rcu_nmi_exit_common - inform RCU of exit from NMI context
> > + * @irq: Is this call from rcu_irq_exit?
> >   *
> >   * If we are returning from the outermost NMI handler that interrupted an
> >   * RCU-idle period, update rdtp->dynticks and rdtp->dynticks_nmi_nesting
> >   * to let the RCU grace-period handling know that the CPU is back to
> >   * being RCU-idle.
> >   *
> > - * If you add or remove a call to rcu_nmi_exit(), be sure to test
> > + * If you add or remove a call to rcu_nmi_exit_common(), be sure to test
> >   * with CONFIG_RCU_EQS_DEBUG=y.
> 
> As this is a static function, this description doesn't make sense. You
> need to move the description down to the new rcu_nmi_exit() below.

Right.. I should've done that.

Thanks you Steve.

Byungchul

> Other than that...
> 
> Reviewed-by: Steven Rostedt (VMware) 
> 
> -- Steve
> 
> 
> >   */
> > -void rcu_nmi_exit(void)
> > +static __always_inline void rcu_nmi_exit_common(bool irq)
> >  {
> > struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
> >  
> > @@ -807,7 +808,22 @@ void rcu_nmi_exit(void)
> > /* This NMI interrupted an RCU-idle CPU, restore RCU-idleness. */
> > trace_rcu_dyntick(TPS("Startirq"), rdtp->dynticks_nmi_nesting, 0, 
> > rdtp->dynticks);
> > WRITE_ONCE(rdtp->dynticks_nmi_nesting, 0); /* Avoid store tearing. */
> > +
> > +   if (irq)
> > +   rcu_prepare_for_idle();
> > +
> > rcu_dynticks_eqs_enter();
> > +
> > +   if (irq)
> > +   rcu_dynticks_task_enter();
> > +}
> > +
> > +/**
> > + * rcu_nmi_exit - inform RCU of exit from NMI context
> > + */
> > +void rcu_nmi_exit(void)
> > +{
> > +   rcu_nmi_exit_common(false);
> >  }
> >  
> >  /**
> > @@ -831,14 +847,8 @@ void rcu_nmi_exit(void)
> >   */
> >  void rcu_irq_exit(void)
> >  {
> > -   struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
> > -
> > lockdep_assert_irqs_disabled();
> > -   if (rdtp->dynticks_nmi_nesting == 1)
> > -   rcu_prepare_for_idle();
> > -   rcu_nmi_exit();
> > -   if (rdtp->dynticks_nmi_nesting == 0)
> > -   rcu_dynticks_task_enter();
> > +   rcu_nmi_exit_common(true);
> >  }
> >  
> >  /*
> > @@ -921,7 +931,8 @@ void rcu_user_exit(void)
> >  #endif /* CONFIG_NO_HZ_FULL */
> >  
> >  /**
> > - * rcu_nmi_enter - inform RCU of entry to NMI context
> > + * rcu_nmi_enter_common - inform RCU of entry to NMI context
> > + * @irq: Is this call from rcu_irq_enter?
> >   *
> >   * If the CPU was idle from RCU's viewpoint, update rdtp->dynticks and
> >   * rdtp->dynticks_nmi_nesting to let the RCU grace-period handling know
> > @@ -929,10 +940,10 @@ void rcu_user_exit(void)
> >   * long as the nesting level does not overflow an int.  (You will probably
> >   * run out of stack space first.)
> >   *
> > - * If you add or remove a call to rcu_nmi_enter(), be sure to test
> > + * If you add or remove a call to rcu_nmi_enter_common(), be sure to test
> >   * with CONFIG_RCU_EQS_DEBUG=y.
> >   */
> > -void rcu_nmi_enter(void)
> > +static __always_inline void rcu_nmi_enter_common(bool irq)
> >  {
> > struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
> > long incby = 2;
> > @@ -949,7 +960,15 @@ void rcu_nmi_enter(void)
> >  * period (observation due to Andy Lutomirski).
> >  */
> > if (rcu_dynticks_curr_cpu_in_eqs()) {
> > +
> > +   if (irq)
> > 

Re: [PATCH tip/core/rcu 01/19] rcu: Refactor rcu_{nmi,irq}_{enter,exit}()

2018-08-30 Thread Paul E. McKenney
On Thu, Aug 30, 2018 at 02:10:32PM -0400, Steven Rostedt wrote:
> On Wed, 29 Aug 2018 15:20:29 -0700
> "Paul E. McKenney"  wrote:
> 
> > This commit also changes order of execution from this:
> > 
> > rcu_dynticks_task_exit();
> > rcu_dynticks_eqs_exit();
> > trace_rcu_dyntick();
> > rcu_cleanup_after_idle();
> > 
> > To this:
> > 
> > rcu_dynticks_task_exit();
> > rcu_dynticks_eqs_exit();
> > rcu_cleanup_after_idle();
> > trace_rcu_dyntick();
> > 
> > In other words, the calls to trace_rcu_dyntick() and trace_rcu_dyntick()
> 
> How is trace_rcu_dyntick() and trace_rcu_dyntick reversed ? ;-)

Very carefully?

I changed the first trace_rcu_dyntick() to rcu_cleanup_after_idle(),
good catch!

> > are reversed.  This has no functional effect because the real
> > concern is whether a given call is before or after the call to
> > rcu_dynticks_eqs_exit(), and this patch does not change that.  Before the
> > call to rcu_dynticks_eqs_exit(), RCU is not yet watching the current
> > CPU and after that call RCU is watching.
> > 
> > A similar switch in calling order happens on the idle-entry path, with
> > similar lack of effect for the same reasons.
> > 
> > Suggested-by: Paul E. McKenney 
> > Signed-off-by: Byungchul Park 
> > Signed-off-by: Paul E. McKenney 
> > ---
> >  kernel/rcu/tree.c | 61 +++
> >  1 file changed, 41 insertions(+), 20 deletions(-)
> > 
> > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> > index 0b760c1369f7..0adf77923e8b 100644
> > --- a/kernel/rcu/tree.c
> > +++ b/kernel/rcu/tree.c
> > @@ -771,17 +771,18 @@ void rcu_user_enter(void)
> >  #endif /* CONFIG_NO_HZ_FULL */
> >  
> >  /**
> > - * rcu_nmi_exit - inform RCU of exit from NMI context
> > + * rcu_nmi_exit_common - inform RCU of exit from NMI context
> > + * @irq: Is this call from rcu_irq_exit?
> >   *
> >   * If we are returning from the outermost NMI handler that interrupted an
> >   * RCU-idle period, update rdtp->dynticks and rdtp->dynticks_nmi_nesting
> >   * to let the RCU grace-period handling know that the CPU is back to
> >   * being RCU-idle.
> >   *
> > - * If you add or remove a call to rcu_nmi_exit(), be sure to test
> > + * If you add or remove a call to rcu_nmi_exit_common(), be sure to test
> >   * with CONFIG_RCU_EQS_DEBUG=y.
> 
> As this is a static function, this description doesn't make sense. You
> need to move the description down to the new rcu_nmi_exit() below.

Heh!  This will give git a chance to show off its conflict-resolution
capabilities!!!  Let's see how it does...

Not bad!  It resolved the conflicts automatically despite the code
movement.  Nice!!!  ;-)

> Other than that...
> 
> Reviewed-by: Steven Rostedt (VMware) 

Of course my penalty for my lack of faith in git is a second rebase
to pull this in.  ;-)

Thank you for your review and comments!

Thanx, Paul

> -- Steve
> 
> 
> >   */
> > -void rcu_nmi_exit(void)
> > +static __always_inline void rcu_nmi_exit_common(bool irq)
> >  {
> > struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
> >  
> > @@ -807,7 +808,22 @@ void rcu_nmi_exit(void)
> > /* This NMI interrupted an RCU-idle CPU, restore RCU-idleness. */
> > trace_rcu_dyntick(TPS("Startirq"), rdtp->dynticks_nmi_nesting, 0, 
> > rdtp->dynticks);
> > WRITE_ONCE(rdtp->dynticks_nmi_nesting, 0); /* Avoid store tearing. */
> > +
> > +   if (irq)
> > +   rcu_prepare_for_idle();
> > +
> > rcu_dynticks_eqs_enter();
> > +
> > +   if (irq)
> > +   rcu_dynticks_task_enter();
> > +}
> > +
> > +/**
> > + * rcu_nmi_exit - inform RCU of exit from NMI context
> > + */
> > +void rcu_nmi_exit(void)
> > +{
> > +   rcu_nmi_exit_common(false);
> >  }
> >  
> >  /**
> > @@ -831,14 +847,8 @@ void rcu_nmi_exit(void)
> >   */
> >  void rcu_irq_exit(void)
> >  {
> > -   struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
> > -
> > lockdep_assert_irqs_disabled();
> > -   if (rdtp->dynticks_nmi_nesting == 1)
> > -   rcu_prepare_for_idle();
> > -   rcu_nmi_exit();
> > -   if (rdtp->dynticks_nmi_nesting == 0)
> > -   rcu_dynticks_task_enter();
> > +   rcu_nmi_exit_common(true);
> >  }
> >  
> >  /*
> > @@ -921,7 +931,8 @@ void rcu_user_exit(void)
> >  #endif /* CONFIG_NO_HZ_FULL */
> >  
> >  /**
> > - * rcu_nmi_enter - inform RCU of entry to NMI context
> > + * rcu_nmi_enter_common - inform RCU of entry to NMI context
> > + * @irq: Is this call from rcu_irq_enter?
> >   *
> >   * If the CPU was idle from RCU's viewpoint, update rdtp->dynticks and
> >   * rdtp->dynticks_nmi_nesting to let the RCU grace-period handling know
> > @@ -929,10 +940,10 @@ void rcu_user_exit(void)
> >   * long as the nesting level does not overflow an int.  (You will probably
> >   * run out of stack space first.)
> >   *
> > - * If you add or remove a call to rcu_nmi_enter(), be sure to test
> > + * If you add or remove a call to rcu_nmi_enter_common(), be sure 

Re: [PATCH tip/core/rcu 01/19] rcu: Refactor rcu_{nmi,irq}_{enter,exit}()

2018-08-30 Thread Paul E. McKenney
On Thu, Aug 30, 2018 at 02:10:32PM -0400, Steven Rostedt wrote:
> On Wed, 29 Aug 2018 15:20:29 -0700
> "Paul E. McKenney"  wrote:
> 
> > This commit also changes order of execution from this:
> > 
> > rcu_dynticks_task_exit();
> > rcu_dynticks_eqs_exit();
> > trace_rcu_dyntick();
> > rcu_cleanup_after_idle();
> > 
> > To this:
> > 
> > rcu_dynticks_task_exit();
> > rcu_dynticks_eqs_exit();
> > rcu_cleanup_after_idle();
> > trace_rcu_dyntick();
> > 
> > In other words, the calls to trace_rcu_dyntick() and trace_rcu_dyntick()
> 
> How is trace_rcu_dyntick() and trace_rcu_dyntick reversed ? ;-)

Very carefully?

I changed the first trace_rcu_dyntick() to rcu_cleanup_after_idle(),
good catch!

> > are reversed.  This has no functional effect because the real
> > concern is whether a given call is before or after the call to
> > rcu_dynticks_eqs_exit(), and this patch does not change that.  Before the
> > call to rcu_dynticks_eqs_exit(), RCU is not yet watching the current
> > CPU and after that call RCU is watching.
> > 
> > A similar switch in calling order happens on the idle-entry path, with
> > similar lack of effect for the same reasons.
> > 
> > Suggested-by: Paul E. McKenney 
> > Signed-off-by: Byungchul Park 
> > Signed-off-by: Paul E. McKenney 
> > ---
> >  kernel/rcu/tree.c | 61 +++
> >  1 file changed, 41 insertions(+), 20 deletions(-)
> > 
> > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> > index 0b760c1369f7..0adf77923e8b 100644
> > --- a/kernel/rcu/tree.c
> > +++ b/kernel/rcu/tree.c
> > @@ -771,17 +771,18 @@ void rcu_user_enter(void)
> >  #endif /* CONFIG_NO_HZ_FULL */
> >  
> >  /**
> > - * rcu_nmi_exit - inform RCU of exit from NMI context
> > + * rcu_nmi_exit_common - inform RCU of exit from NMI context
> > + * @irq: Is this call from rcu_irq_exit?
> >   *
> >   * If we are returning from the outermost NMI handler that interrupted an
> >   * RCU-idle period, update rdtp->dynticks and rdtp->dynticks_nmi_nesting
> >   * to let the RCU grace-period handling know that the CPU is back to
> >   * being RCU-idle.
> >   *
> > - * If you add or remove a call to rcu_nmi_exit(), be sure to test
> > + * If you add or remove a call to rcu_nmi_exit_common(), be sure to test
> >   * with CONFIG_RCU_EQS_DEBUG=y.
> 
> As this is a static function, this description doesn't make sense. You
> need to move the description down to the new rcu_nmi_exit() below.

Heh!  This will give git a chance to show off its conflict-resolution
capabilities!!!  Let's see how it does...

Not bad!  It resolved the conflicts automatically despite the code
movement.  Nice!!!  ;-)

> Other than that...
> 
> Reviewed-by: Steven Rostedt (VMware) 

Of course my penalty for my lack of faith in git is a second rebase
to pull this in.  ;-)

Thank you for your review and comments!

Thanx, Paul

> -- Steve
> 
> 
> >   */
> > -void rcu_nmi_exit(void)
> > +static __always_inline void rcu_nmi_exit_common(bool irq)
> >  {
> > struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
> >  
> > @@ -807,7 +808,22 @@ void rcu_nmi_exit(void)
> > /* This NMI interrupted an RCU-idle CPU, restore RCU-idleness. */
> > trace_rcu_dyntick(TPS("Startirq"), rdtp->dynticks_nmi_nesting, 0, 
> > rdtp->dynticks);
> > WRITE_ONCE(rdtp->dynticks_nmi_nesting, 0); /* Avoid store tearing. */
> > +
> > +   if (irq)
> > +   rcu_prepare_for_idle();
> > +
> > rcu_dynticks_eqs_enter();
> > +
> > +   if (irq)
> > +   rcu_dynticks_task_enter();
> > +}
> > +
> > +/**
> > + * rcu_nmi_exit - inform RCU of exit from NMI context
> > + */
> > +void rcu_nmi_exit(void)
> > +{
> > +   rcu_nmi_exit_common(false);
> >  }
> >  
> >  /**
> > @@ -831,14 +847,8 @@ void rcu_nmi_exit(void)
> >   */
> >  void rcu_irq_exit(void)
> >  {
> > -   struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
> > -
> > lockdep_assert_irqs_disabled();
> > -   if (rdtp->dynticks_nmi_nesting == 1)
> > -   rcu_prepare_for_idle();
> > -   rcu_nmi_exit();
> > -   if (rdtp->dynticks_nmi_nesting == 0)
> > -   rcu_dynticks_task_enter();
> > +   rcu_nmi_exit_common(true);
> >  }
> >  
> >  /*
> > @@ -921,7 +931,8 @@ void rcu_user_exit(void)
> >  #endif /* CONFIG_NO_HZ_FULL */
> >  
> >  /**
> > - * rcu_nmi_enter - inform RCU of entry to NMI context
> > + * rcu_nmi_enter_common - inform RCU of entry to NMI context
> > + * @irq: Is this call from rcu_irq_enter?
> >   *
> >   * If the CPU was idle from RCU's viewpoint, update rdtp->dynticks and
> >   * rdtp->dynticks_nmi_nesting to let the RCU grace-period handling know
> > @@ -929,10 +940,10 @@ void rcu_user_exit(void)
> >   * long as the nesting level does not overflow an int.  (You will probably
> >   * run out of stack space first.)
> >   *
> > - * If you add or remove a call to rcu_nmi_enter(), be sure to test
> > + * If you add or remove a call to rcu_nmi_enter_common(), be sure 

Re: [PATCH tip/core/rcu 01/19] rcu: Refactor rcu_{nmi,irq}_{enter,exit}()

2018-08-30 Thread Steven Rostedt
On Wed, 29 Aug 2018 15:20:29 -0700
"Paul E. McKenney"  wrote:

> This commit also changes order of execution from this:
> 
>   rcu_dynticks_task_exit();
>   rcu_dynticks_eqs_exit();
>   trace_rcu_dyntick();
>   rcu_cleanup_after_idle();
> 
> To this:
> 
>   rcu_dynticks_task_exit();
>   rcu_dynticks_eqs_exit();
>   rcu_cleanup_after_idle();
>   trace_rcu_dyntick();
> 
> In other words, the calls to trace_rcu_dyntick() and trace_rcu_dyntick()

How is trace_rcu_dyntick() and trace_rcu_dyntick reversed ? ;-)

> are reversed.  This has no functional effect because the real
> concern is whether a given call is before or after the call to
> rcu_dynticks_eqs_exit(), and this patch does not change that.  Before the
> call to rcu_dynticks_eqs_exit(), RCU is not yet watching the current
> CPU and after that call RCU is watching.
> 
> A similar switch in calling order happens on the idle-entry path, with
> similar lack of effect for the same reasons.
> 
> Suggested-by: Paul E. McKenney 
> Signed-off-by: Byungchul Park 
> Signed-off-by: Paul E. McKenney 
> ---
>  kernel/rcu/tree.c | 61 +++
>  1 file changed, 41 insertions(+), 20 deletions(-)
> 
> diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> index 0b760c1369f7..0adf77923e8b 100644
> --- a/kernel/rcu/tree.c
> +++ b/kernel/rcu/tree.c
> @@ -771,17 +771,18 @@ void rcu_user_enter(void)
>  #endif /* CONFIG_NO_HZ_FULL */
>  
>  /**
> - * rcu_nmi_exit - inform RCU of exit from NMI context
> + * rcu_nmi_exit_common - inform RCU of exit from NMI context
> + * @irq: Is this call from rcu_irq_exit?
>   *
>   * If we are returning from the outermost NMI handler that interrupted an
>   * RCU-idle period, update rdtp->dynticks and rdtp->dynticks_nmi_nesting
>   * to let the RCU grace-period handling know that the CPU is back to
>   * being RCU-idle.
>   *
> - * If you add or remove a call to rcu_nmi_exit(), be sure to test
> + * If you add or remove a call to rcu_nmi_exit_common(), be sure to test
>   * with CONFIG_RCU_EQS_DEBUG=y.

As this is a static function, this description doesn't make sense. You
need to move the description down to the new rcu_nmi_exit() below.

Other than that...

Reviewed-by: Steven Rostedt (VMware) 

-- Steve


>   */
> -void rcu_nmi_exit(void)
> +static __always_inline void rcu_nmi_exit_common(bool irq)
>  {
>   struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
>  
> @@ -807,7 +808,22 @@ void rcu_nmi_exit(void)
>   /* This NMI interrupted an RCU-idle CPU, restore RCU-idleness. */
>   trace_rcu_dyntick(TPS("Startirq"), rdtp->dynticks_nmi_nesting, 0, 
> rdtp->dynticks);
>   WRITE_ONCE(rdtp->dynticks_nmi_nesting, 0); /* Avoid store tearing. */
> +
> + if (irq)
> + rcu_prepare_for_idle();
> +
>   rcu_dynticks_eqs_enter();
> +
> + if (irq)
> + rcu_dynticks_task_enter();
> +}
> +
> +/**
> + * rcu_nmi_exit - inform RCU of exit from NMI context
> + */
> +void rcu_nmi_exit(void)
> +{
> + rcu_nmi_exit_common(false);
>  }
>  
>  /**
> @@ -831,14 +847,8 @@ void rcu_nmi_exit(void)
>   */
>  void rcu_irq_exit(void)
>  {
> - struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
> -
>   lockdep_assert_irqs_disabled();
> - if (rdtp->dynticks_nmi_nesting == 1)
> - rcu_prepare_for_idle();
> - rcu_nmi_exit();
> - if (rdtp->dynticks_nmi_nesting == 0)
> - rcu_dynticks_task_enter();
> + rcu_nmi_exit_common(true);
>  }
>  
>  /*
> @@ -921,7 +931,8 @@ void rcu_user_exit(void)
>  #endif /* CONFIG_NO_HZ_FULL */
>  
>  /**
> - * rcu_nmi_enter - inform RCU of entry to NMI context
> + * rcu_nmi_enter_common - inform RCU of entry to NMI context
> + * @irq: Is this call from rcu_irq_enter?
>   *
>   * If the CPU was idle from RCU's viewpoint, update rdtp->dynticks and
>   * rdtp->dynticks_nmi_nesting to let the RCU grace-period handling know
> @@ -929,10 +940,10 @@ void rcu_user_exit(void)
>   * long as the nesting level does not overflow an int.  (You will probably
>   * run out of stack space first.)
>   *
> - * If you add or remove a call to rcu_nmi_enter(), be sure to test
> + * If you add or remove a call to rcu_nmi_enter_common(), be sure to test
>   * with CONFIG_RCU_EQS_DEBUG=y.
>   */
> -void rcu_nmi_enter(void)
> +static __always_inline void rcu_nmi_enter_common(bool irq)
>  {
>   struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
>   long incby = 2;
> @@ -949,7 +960,15 @@ void rcu_nmi_enter(void)
>* period (observation due to Andy Lutomirski).
>*/
>   if (rcu_dynticks_curr_cpu_in_eqs()) {
> +
> + if (irq)
> + rcu_dynticks_task_exit();
> +
>   rcu_dynticks_eqs_exit();
> +
> + if (irq)
> + rcu_cleanup_after_idle();
> +
>   incby = 1;
>   }
>   trace_rcu_dyntick(incby == 1 ? TPS("Endirq") : TPS("++="),
> @@ -960,6 +979,14 @@ void rcu_nmi_enter(void)
>   barrier();

Re: [PATCH tip/core/rcu 01/19] rcu: Refactor rcu_{nmi,irq}_{enter,exit}()

2018-08-30 Thread Steven Rostedt
On Wed, 29 Aug 2018 15:20:29 -0700
"Paul E. McKenney"  wrote:

> This commit also changes order of execution from this:
> 
>   rcu_dynticks_task_exit();
>   rcu_dynticks_eqs_exit();
>   trace_rcu_dyntick();
>   rcu_cleanup_after_idle();
> 
> To this:
> 
>   rcu_dynticks_task_exit();
>   rcu_dynticks_eqs_exit();
>   rcu_cleanup_after_idle();
>   trace_rcu_dyntick();
> 
> In other words, the calls to trace_rcu_dyntick() and trace_rcu_dyntick()

How is trace_rcu_dyntick() and trace_rcu_dyntick reversed ? ;-)

> are reversed.  This has no functional effect because the real
> concern is whether a given call is before or after the call to
> rcu_dynticks_eqs_exit(), and this patch does not change that.  Before the
> call to rcu_dynticks_eqs_exit(), RCU is not yet watching the current
> CPU and after that call RCU is watching.
> 
> A similar switch in calling order happens on the idle-entry path, with
> similar lack of effect for the same reasons.
> 
> Suggested-by: Paul E. McKenney 
> Signed-off-by: Byungchul Park 
> Signed-off-by: Paul E. McKenney 
> ---
>  kernel/rcu/tree.c | 61 +++
>  1 file changed, 41 insertions(+), 20 deletions(-)
> 
> diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> index 0b760c1369f7..0adf77923e8b 100644
> --- a/kernel/rcu/tree.c
> +++ b/kernel/rcu/tree.c
> @@ -771,17 +771,18 @@ void rcu_user_enter(void)
>  #endif /* CONFIG_NO_HZ_FULL */
>  
>  /**
> - * rcu_nmi_exit - inform RCU of exit from NMI context
> + * rcu_nmi_exit_common - inform RCU of exit from NMI context
> + * @irq: Is this call from rcu_irq_exit?
>   *
>   * If we are returning from the outermost NMI handler that interrupted an
>   * RCU-idle period, update rdtp->dynticks and rdtp->dynticks_nmi_nesting
>   * to let the RCU grace-period handling know that the CPU is back to
>   * being RCU-idle.
>   *
> - * If you add or remove a call to rcu_nmi_exit(), be sure to test
> + * If you add or remove a call to rcu_nmi_exit_common(), be sure to test
>   * with CONFIG_RCU_EQS_DEBUG=y.

As this is a static function, this description doesn't make sense. You
need to move the description down to the new rcu_nmi_exit() below.

Other than that...

Reviewed-by: Steven Rostedt (VMware) 

-- Steve


>   */
> -void rcu_nmi_exit(void)
> +static __always_inline void rcu_nmi_exit_common(bool irq)
>  {
>   struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
>  
> @@ -807,7 +808,22 @@ void rcu_nmi_exit(void)
>   /* This NMI interrupted an RCU-idle CPU, restore RCU-idleness. */
>   trace_rcu_dyntick(TPS("Startirq"), rdtp->dynticks_nmi_nesting, 0, 
> rdtp->dynticks);
>   WRITE_ONCE(rdtp->dynticks_nmi_nesting, 0); /* Avoid store tearing. */
> +
> + if (irq)
> + rcu_prepare_for_idle();
> +
>   rcu_dynticks_eqs_enter();
> +
> + if (irq)
> + rcu_dynticks_task_enter();
> +}
> +
> +/**
> + * rcu_nmi_exit - inform RCU of exit from NMI context
> + */
> +void rcu_nmi_exit(void)
> +{
> + rcu_nmi_exit_common(false);
>  }
>  
>  /**
> @@ -831,14 +847,8 @@ void rcu_nmi_exit(void)
>   */
>  void rcu_irq_exit(void)
>  {
> - struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
> -
>   lockdep_assert_irqs_disabled();
> - if (rdtp->dynticks_nmi_nesting == 1)
> - rcu_prepare_for_idle();
> - rcu_nmi_exit();
> - if (rdtp->dynticks_nmi_nesting == 0)
> - rcu_dynticks_task_enter();
> + rcu_nmi_exit_common(true);
>  }
>  
>  /*
> @@ -921,7 +931,8 @@ void rcu_user_exit(void)
>  #endif /* CONFIG_NO_HZ_FULL */
>  
>  /**
> - * rcu_nmi_enter - inform RCU of entry to NMI context
> + * rcu_nmi_enter_common - inform RCU of entry to NMI context
> + * @irq: Is this call from rcu_irq_enter?
>   *
>   * If the CPU was idle from RCU's viewpoint, update rdtp->dynticks and
>   * rdtp->dynticks_nmi_nesting to let the RCU grace-period handling know
> @@ -929,10 +940,10 @@ void rcu_user_exit(void)
>   * long as the nesting level does not overflow an int.  (You will probably
>   * run out of stack space first.)
>   *
> - * If you add or remove a call to rcu_nmi_enter(), be sure to test
> + * If you add or remove a call to rcu_nmi_enter_common(), be sure to test
>   * with CONFIG_RCU_EQS_DEBUG=y.
>   */
> -void rcu_nmi_enter(void)
> +static __always_inline void rcu_nmi_enter_common(bool irq)
>  {
>   struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
>   long incby = 2;
> @@ -949,7 +960,15 @@ void rcu_nmi_enter(void)
>* period (observation due to Andy Lutomirski).
>*/
>   if (rcu_dynticks_curr_cpu_in_eqs()) {
> +
> + if (irq)
> + rcu_dynticks_task_exit();
> +
>   rcu_dynticks_eqs_exit();
> +
> + if (irq)
> + rcu_cleanup_after_idle();
> +
>   incby = 1;
>   }
>   trace_rcu_dyntick(incby == 1 ? TPS("Endirq") : TPS("++="),
> @@ -960,6 +979,14 @@ void rcu_nmi_enter(void)
>   barrier();

[PATCH tip/core/rcu 01/19] rcu: Refactor rcu_{nmi,irq}_{enter,exit}()

2018-08-29 Thread Paul E. McKenney
From: Byungchul Park 

When entering or exiting irq or NMI handlers, the current code uses
->dynticks_nmi_nesting to detect if it is in the outermost handler,
that is, the one interrupting or returning to an RCU-idle context (the
idle loop or nohz_full usermode execution).  When entering the outermost
handler via an interrupt (as opposed to NMI), it is necessary to invoke
rcu_dynticks_task_exit() just before the CPU is marked non-idle from an
RCU perspective and to invoke rcu_cleanup_after_idle() just after the
CPU is marked non-idle.  Similarly, when exiting the outermost handler
via an interrupt, it is necessary to invoke rcu_prepare_for_idle() just
before marking the CPU idle and to invoke rcu_dynticks_task_enter()
just after marking the CPU idle.

The decision to execute these four functions is currently taken in
rcu_irq_enter() and rcu_irq_exit() as follows:

   rcu_irq_enter()
  /* A conditional branch with ->dynticks_nmi_nesting */
  rcu_nmi_enter()
 /* A conditional branch with ->dynticks */
  /* A conditional branch with ->dynticks_nmi_nesting */

   rcu_irq_exit()
  /* A conditional branch with ->dynticks_nmi_nesting */
  rcu_nmi_exit()
 /* A conditional branch with ->dynticks_nmi_nesting */
  /* A conditional branch with ->dynticks_nmi_nesting */

   rcu_nmi_enter()
  /* A conditional branch with ->dynticks */

   rcu_nmi_exit()
  /* A conditional branch with ->dynticks_nmi_nesting */

This works, but the conditional branches in rcu_irq_enter() and
rcu_irq_exit() are redundant with those in rcu_nmi_enter() and
rcu_nmi_exit(), respectively.  Redundant branches are not something
we want in the to/from-idle fastpaths, so this commit refactors
rcu_{nmi,irq}_{enter,exit}() so they use a common inlined function passed
a constant argument as follows:

   rcu_irq_enter() inlining rcu_nmi_enter_common(irq=true)
  /* A conditional branch with ->dynticks */

   rcu_irq_exit() inlining rcu_nmi_exit_common(irq=true)
  /* A conditional branch with ->dynticks_nmi_nesting */

   rcu_nmi_enter() inlining rcu_nmi_enter_common(irq=false)
  /* A conditional branch with ->dynticks */

   rcu_nmi_exit() inlining rcu_nmi_exit_common(irq=false)
  /* A conditional branch with ->dynticks_nmi_nesting */

The combination of the constant function argument and the inlining allows
the compiler to discard the conditionals that previously controlled
execution of rcu_dynticks_task_exit(), rcu_cleanup_after_idle(),
rcu_prepare_for_idle(), and rcu_dynticks_task_enter().  This reduces both
the to-idle and from-idle path lengths by two conditional branches each,
and improves readability as well.

This commit also changes order of execution from this:

rcu_dynticks_task_exit();
rcu_dynticks_eqs_exit();
trace_rcu_dyntick();
rcu_cleanup_after_idle();

To this:

rcu_dynticks_task_exit();
rcu_dynticks_eqs_exit();
rcu_cleanup_after_idle();
trace_rcu_dyntick();

In other words, the calls to trace_rcu_dyntick() and trace_rcu_dyntick()
are reversed.  This has no functional effect because the real
concern is whether a given call is before or after the call to
rcu_dynticks_eqs_exit(), and this patch does not change that.  Before the
call to rcu_dynticks_eqs_exit(), RCU is not yet watching the current
CPU and after that call RCU is watching.

A similar switch in calling order happens on the idle-entry path, with
similar lack of effect for the same reasons.

Suggested-by: Paul E. McKenney 
Signed-off-by: Byungchul Park 
Signed-off-by: Paul E. McKenney 
---
 kernel/rcu/tree.c | 61 +++
 1 file changed, 41 insertions(+), 20 deletions(-)

diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 0b760c1369f7..0adf77923e8b 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -771,17 +771,18 @@ void rcu_user_enter(void)
 #endif /* CONFIG_NO_HZ_FULL */
 
 /**
- * rcu_nmi_exit - inform RCU of exit from NMI context
+ * rcu_nmi_exit_common - inform RCU of exit from NMI context
+ * @irq: Is this call from rcu_irq_exit?
  *
  * If we are returning from the outermost NMI handler that interrupted an
  * RCU-idle period, update rdtp->dynticks and rdtp->dynticks_nmi_nesting
  * to let the RCU grace-period handling know that the CPU is back to
  * being RCU-idle.
  *
- * If you add or remove a call to rcu_nmi_exit(), be sure to test
+ * If you add or remove a call to rcu_nmi_exit_common(), be sure to test
  * with CONFIG_RCU_EQS_DEBUG=y.
  */
-void rcu_nmi_exit(void)
+static __always_inline void rcu_nmi_exit_common(bool irq)
 {
struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
 
@@ -807,7 +808,22 @@ void rcu_nmi_exit(void)
/* This NMI interrupted an RCU-idle CPU, restore RCU-idleness. */
trace_rcu_dyntick(TPS("Startirq"), rdtp->dynticks_nmi_nesting, 0, 
rdtp->dynticks);
WRITE_ONCE(rdtp->dynticks_nmi_nesting, 0); /* Avoid store tearing. */
+
+   if 

[PATCH tip/core/rcu 01/19] rcu: Refactor rcu_{nmi,irq}_{enter,exit}()

2018-08-29 Thread Paul E. McKenney
From: Byungchul Park 

When entering or exiting irq or NMI handlers, the current code uses
->dynticks_nmi_nesting to detect if it is in the outermost handler,
that is, the one interrupting or returning to an RCU-idle context (the
idle loop or nohz_full usermode execution).  When entering the outermost
handler via an interrupt (as opposed to NMI), it is necessary to invoke
rcu_dynticks_task_exit() just before the CPU is marked non-idle from an
RCU perspective and to invoke rcu_cleanup_after_idle() just after the
CPU is marked non-idle.  Similarly, when exiting the outermost handler
via an interrupt, it is necessary to invoke rcu_prepare_for_idle() just
before marking the CPU idle and to invoke rcu_dynticks_task_enter()
just after marking the CPU idle.

The decision to execute these four functions is currently taken in
rcu_irq_enter() and rcu_irq_exit() as follows:

   rcu_irq_enter()
  /* A conditional branch with ->dynticks_nmi_nesting */
  rcu_nmi_enter()
 /* A conditional branch with ->dynticks */
  /* A conditional branch with ->dynticks_nmi_nesting */

   rcu_irq_exit()
  /* A conditional branch with ->dynticks_nmi_nesting */
  rcu_nmi_exit()
 /* A conditional branch with ->dynticks_nmi_nesting */
  /* A conditional branch with ->dynticks_nmi_nesting */

   rcu_nmi_enter()
  /* A conditional branch with ->dynticks */

   rcu_nmi_exit()
  /* A conditional branch with ->dynticks_nmi_nesting */

This works, but the conditional branches in rcu_irq_enter() and
rcu_irq_exit() are redundant with those in rcu_nmi_enter() and
rcu_nmi_exit(), respectively.  Redundant branches are not something
we want in the to/from-idle fastpaths, so this commit refactors
rcu_{nmi,irq}_{enter,exit}() so they use a common inlined function passed
a constant argument as follows:

   rcu_irq_enter() inlining rcu_nmi_enter_common(irq=true)
  /* A conditional branch with ->dynticks */

   rcu_irq_exit() inlining rcu_nmi_exit_common(irq=true)
  /* A conditional branch with ->dynticks_nmi_nesting */

   rcu_nmi_enter() inlining rcu_nmi_enter_common(irq=false)
  /* A conditional branch with ->dynticks */

   rcu_nmi_exit() inlining rcu_nmi_exit_common(irq=false)
  /* A conditional branch with ->dynticks_nmi_nesting */

The combination of the constant function argument and the inlining allows
the compiler to discard the conditionals that previously controlled
execution of rcu_dynticks_task_exit(), rcu_cleanup_after_idle(),
rcu_prepare_for_idle(), and rcu_dynticks_task_enter().  This reduces both
the to-idle and from-idle path lengths by two conditional branches each,
and improves readability as well.

This commit also changes order of execution from this:

rcu_dynticks_task_exit();
rcu_dynticks_eqs_exit();
trace_rcu_dyntick();
rcu_cleanup_after_idle();

To this:

rcu_dynticks_task_exit();
rcu_dynticks_eqs_exit();
rcu_cleanup_after_idle();
trace_rcu_dyntick();

In other words, the calls to trace_rcu_dyntick() and trace_rcu_dyntick()
are reversed.  This has no functional effect because the real
concern is whether a given call is before or after the call to
rcu_dynticks_eqs_exit(), and this patch does not change that.  Before the
call to rcu_dynticks_eqs_exit(), RCU is not yet watching the current
CPU and after that call RCU is watching.

A similar switch in calling order happens on the idle-entry path, with
similar lack of effect for the same reasons.

Suggested-by: Paul E. McKenney 
Signed-off-by: Byungchul Park 
Signed-off-by: Paul E. McKenney 
---
 kernel/rcu/tree.c | 61 +++
 1 file changed, 41 insertions(+), 20 deletions(-)

diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 0b760c1369f7..0adf77923e8b 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -771,17 +771,18 @@ void rcu_user_enter(void)
 #endif /* CONFIG_NO_HZ_FULL */
 
 /**
- * rcu_nmi_exit - inform RCU of exit from NMI context
+ * rcu_nmi_exit_common - inform RCU of exit from NMI context
+ * @irq: Is this call from rcu_irq_exit?
  *
  * If we are returning from the outermost NMI handler that interrupted an
  * RCU-idle period, update rdtp->dynticks and rdtp->dynticks_nmi_nesting
  * to let the RCU grace-period handling know that the CPU is back to
  * being RCU-idle.
  *
- * If you add or remove a call to rcu_nmi_exit(), be sure to test
+ * If you add or remove a call to rcu_nmi_exit_common(), be sure to test
  * with CONFIG_RCU_EQS_DEBUG=y.
  */
-void rcu_nmi_exit(void)
+static __always_inline void rcu_nmi_exit_common(bool irq)
 {
struct rcu_dynticks *rdtp = this_cpu_ptr(_dynticks);
 
@@ -807,7 +808,22 @@ void rcu_nmi_exit(void)
/* This NMI interrupted an RCU-idle CPU, restore RCU-idleness. */
trace_rcu_dyntick(TPS("Startirq"), rdtp->dynticks_nmi_nesting, 0, 
rdtp->dynticks);
WRITE_ONCE(rdtp->dynticks_nmi_nesting, 0); /* Avoid store tearing. */
+
+   if