[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <87blmht1yr.fsf@nanos.tec.linutronix.de>
Date: Thu, 21 May 2020 23:25:32 +0200
From: Thomas Gleixner <tglx@...utronix.de>
To: paulmck@...nel.org
Cc: LKML <linux-kernel@...r.kernel.org>,
Andy Lutomirski <luto@...nel.org>,
Andrew Cooper <andrew.cooper3@...rix.com>,
X86 ML <x86@...nel.org>,
Alexandre Chartre <alexandre.chartre@...cle.com>,
Frederic Weisbecker <frederic@...nel.org>,
Paolo Bonzini <pbonzini@...hat.com>,
Sean Christopherson <sean.j.christopherson@...el.com>,
Masami Hiramatsu <mhiramat@...nel.org>,
Petr Mladek <pmladek@...e.com>,
Steven Rostedt <rostedt@...dmis.org>,
Joel Fernandes <joel@...lfernandes.org>,
Boris Ostrovsky <boris.ostrovsky@...cle.com>,
Juergen Gross <jgross@...e.com>,
Brian Gerst <brgerst@...il.com>,
Mathieu Desnoyers <mathieu.desnoyers@...icios.com>,
Josh Poimboeuf <jpoimboe@...hat.com>,
Will Deacon <will@...nel.org>,
Tom Lendacky <thomas.lendacky@....com>,
Wei Liu <wei.liu@...nel.org>,
Michael Kelley <mikelley@...rosoft.com>,
Jason Chen CJ <jason.cj.chen@...el.com>,
Zhao Yakui <yakui.zhao@...el.com>,
"Peter Zijlstra \(Intel\)" <peterz@...radead.org>
Subject: Re: [patch V9 02/39] rcu: Abstract out rcu_irq_enter_check_tick() from rcu_nmi_enter()
"Paul E. McKenney" <paulmck@...nel.org> writes:
> On Thu, May 21, 2020 at 10:05:15PM +0200, Thomas Gleixner wrote:
>> +void __rcu_irq_enter_check_tick(void);
>> +
>> +static __always_inline void rcu_irq_enter_check_tick(void)
>> +{
>> + if (context_tracking_enabled())
>> + __rcu_irq_enter_check_tick();
>
> I suggest moving the WARN_ON_ONCE(in_nmi()) check here to avoid calling
> in_nmi() twice. Because of the READ_ONCE(), the compiler cannot (had
> better not!) eliminate the double call.
Makes sense.
>> +void __rcu_irq_enter_check_tick(void)
>> +{
>> + struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
>> +
>> + // Enabling the tick is unsafe in NMI handlers.
>
> There is an extra space before the "//", probably the one that used to
> be after the ";" below. ;-)
This is caused by my fundamental and not suppressible disgust of tail
comments. They really disturb the reading flow for me.
if (foo)
return; // Because ...
makes my pattern recognition stop because the semicolon is usually the
end of the statement. But that's not the only reason.
// Because ....
if (foo)
return;
makes more sense to me because then the comment is explaining the
condition and not the outcome. The outcome is obvious when the condition
is well explained.
There are a few exceptions where I adjusted, e.g. in macros:
foo(); \
bar_or_something_else(); \
but only when the trailing backslash is properly aligned.
foo(); \
bar_or_something_else(); \
That stops the parser as well.
I know that this is a pet pieve but I can't help it to adjust it when I
have a chance to do so :)
>> + if (WARN_ON_ONCE(in_nmi()))
>> + return;
>> +
>> + RCU_LOCKDEP_WARN(rcu_dynticks_curr_cpu_in_eqs(),
>> + "Illegal rcu_irq_enter_check_tick() from extended quiescent state");
>
> The instrumentation_begin() has disappeared, presumably because
> instrumentation is already enabled in the non-RCU code that directly calls
> rcu_irq_enter_check_tick(). (I do see the calls in rcu_nmi_enter()
> below.)
Yes. The intention here is to make sure that the caller does not
misplace it. So if the call is in a non-instrumentable code path then
objtool will complain and the developer will hopefully think twice
whether this is the right place to wrap the call with instrumentation_*
annotations. I know it's based on hope :)
>> +
>> + if (!tick_nohz_full_cpu(rdp->cpu) ||
>> + !READ_ONCE(rdp->rcu_urgent_qs) ||
>> + READ_ONCE(rdp->rcu_forced_tick)) {
>> + // RCU doesn't need nohz_full help from this CPU, or it is
>> + // already getting that help.
>> + return;
>> + }
>> +
>> + // We get here only when not in an extended quiescent state and
>> + // from interrupts (as opposed to NMIs). Therefore, (1) RCU is
>> + // already watching and (2) The fact that we are in an interrupt
>> + // handler and that the rcu_node lock is an irq-disabled lock
>> + // prevents self-deadlock. So we can safely recheck under the lock.
>> + // Note that the nohz_full state currently cannot change.
>> + raw_spin_lock_rcu_node(rdp->mynode);
>> + if (rdp->rcu_urgent_qs && !rdp->rcu_forced_tick) {
>> + // A nohz_full CPU is in the kernel and RCU needs a
>> + // quiescent state. Turn on the tick!
>> + WRITE_ONCE(rdp->rcu_forced_tick, true);
>> + tick_dep_set_cpu(rdp->cpu, TICK_DEP_BIT_RCU);
>> + }
>> + raw_spin_unlock_rcu_node(rdp->mynode);
>> +}
>> #endif /* CONFIG_NO_HZ_FULL */
>>
>> /**
>> @@ -894,26 +955,7 @@ noinstr void rcu_nmi_enter(void)
>> incby = 1;
>> } else if (!in_nmi()) {
>
> This can just be "else" given the in_nmi() check in
> __rcu_irq_enter_check_tick(), right? Ah, that check got a
> WARN_ON_ONCE(), so never mind!
>
> I guess that will discourage NMI-handler calls to
> rcu_irq_enter_check_tick(). ;-)
Exactly.
> It does mean a double call to in_nmi(), though, so should that
> WARN_ON_ONCE(in_nmi()) check go into the rcu_irq_enter_check_tick()
> wrapper? Or do modern compilers figure this one out? Given the
> READ_ONCE() in preempt_count(), I have to say that I hope not.
> So see my comment above on rcu_irq_enter_check_tick().
Moving it to the wrapper is the right thing to do. Will fix.
Thanks,
tglx
Powered by blists - more mailing lists