Re: [RFC 1/2] rcu: Do prepare and cleanup idle depending on in_nmi()

From: Paul E. McKenney
Date: Wed Jun 20 2018 - 10:49:09 EST


On Wed, Jun 20, 2018 at 05:47:19PM +0900, Byungchul Park wrote:
> Get rid of dependency on ->dynticks_nmi_nesting.
>
> Signed-off-by: Byungchul Park <byungchul.park@xxxxxxx>
> ---
> kernel/rcu/tree.c | 22 ++++++++++------------
> 1 file changed, 10 insertions(+), 12 deletions(-)
>
> diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> index deb2508..59ae94e 100644
> --- a/kernel/rcu/tree.c
> +++ b/kernel/rcu/tree.c
> @@ -797,6 +797,11 @@ void rcu_nmi_exit(void)
> return;
> }
>
> + if (!in_nmi()) {

Is in_nmi() sufficiently reliable for use here? In the past, there have
been tracepoints that invoked these functions between the time that the
handlers were entered and the time that software updated the state so that
the various handler-check functions (such as in_nmi()) would return true.

Steve, has there been any change in this situation?

Thanx, Paul

> + rcu_prepare_for_idle();
> + rcu_dynticks_task_enter();
> + }
> +
> /* 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. */
> @@ -824,14 +829,8 @@ void rcu_nmi_exit(void)
> */
> void rcu_irq_exit(void)
> {
> - struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_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();
> }
>
> /*
> @@ -944,6 +943,11 @@ void rcu_nmi_enter(void)
> if (rcu_dynticks_curr_cpu_in_eqs()) {
> rcu_dynticks_eqs_exit();
> incby = 1;
> +
> + if (!in_nmi()) {
> + rcu_dynticks_task_exit();
> + rcu_cleanup_after_idle();
> + }
> }
> trace_rcu_dyntick(incby == 1 ? TPS("Endirq") : TPS("++="),
> rdtp->dynticks_nmi_nesting,
> @@ -977,14 +981,8 @@ void rcu_nmi_enter(void)
> */
> void rcu_irq_enter(void)
> {
> - struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
> -
> lockdep_assert_irqs_disabled();
> - if (rdtp->dynticks_nmi_nesting == 0)
> - rcu_dynticks_task_exit();
> rcu_nmi_enter();
> - if (rdtp->dynticks_nmi_nesting == 1)
> - rcu_cleanup_after_idle();
> }
>
> /*
> --
> 1.9.1
>