Re: [PATCH 1/5] x86/percpu: Differentiate this_cpu_{}() and __this_cpu_{}()

From: Linus Torvalds
Date: Wed Feb 27 2019 - 11:14:35 EST


On Wed, Feb 27, 2019 at 2:16 AM Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote:
>
> Nadav Amit reported that commit:
>
> b59167ac7baf ("x86/percpu: Fix this_cpu_read()")
>
> added a bunch of constraints to all sorts of code; and while some of
> that was correct and desired, some of that seems superfluous.

Hmm.

I have the strong feeling that we should instead relax this_cpu_read()
again a bit.

In particular, making it "asm volatile" really is a big hammer
approach. It's worth noting that the *other* this_cpu_xyz ops don't
even do that.

I would suggest that instead of making "this_cpu_read()" be asm
volatile, we mark it as potentially changing the memory location it is
touching - the same way the modify/write ops do.

That still means that the read will be forced (like READ_ONCE()), but
allows gcc a bit more flexibility in instruction scheduling, I think.

Trivial (but entirely untested) patch attached.

That said, I didn't actually check how it affects code generation.
Nadav, would you check the code sequences you originally noticed?

Linus
arch/x86/include/asm/percpu.h | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index 1a19d11cfbbd..63b0f361533f 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -185,24 +185,24 @@ do { \
typeof(var) pfo_ret__; \
switch (sizeof(var)) { \
case 1: \
- asm volatile(op "b "__percpu_arg(1)",%0"\
- : "=q" (pfo_ret__) \
- : "m" (var)); \
+ asm(op "b "__percpu_arg(1)",%0"\
+ : "=q" (pfo_ret__), \
+ "+m" (var)); \
break; \
case 2: \
- asm volatile(op "w "__percpu_arg(1)",%0"\
- : "=r" (pfo_ret__) \
- : "m" (var)); \
+ asm(op "w "__percpu_arg(1)",%0"\
+ : "=r" (pfo_ret__), \
+ "+m" (var)); \
break; \
case 4: \
- asm volatile(op "l "__percpu_arg(1)",%0"\
- : "=r" (pfo_ret__) \
- : "m" (var)); \
+ asm(op "l "__percpu_arg(1)",%0"\
+ : "=r" (pfo_ret__), \
+ "+m" (var)); \
break; \
case 8: \
- asm volatile(op "q "__percpu_arg(1)",%0"\
- : "=r" (pfo_ret__) \
- : "m" (var)); \
+ asm(op "q "__percpu_arg(1)",%0"\
+ : "=r" (pfo_ret__), \
+ "+m" (var)); \
break; \
default: __bad_percpu_size(); \
} \