* [PATCH v2 0/3] arm64: Fixes for __READ_ONCE() with CONFIG_LTO=y
@ 2026-01-29 0:52 Marco Elver
2026-01-29 0:52 ` [PATCH v2 1/3] arm64: Fix non-atomic " Marco Elver
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Marco Elver @ 2026-01-29 0:52 UTC (permalink / raw)
To: elver, Peter Zijlstra, Will Deacon
Cc: Ingo Molnar, Thomas Gleixner, Boqun Feng, Waiman Long,
Bart Van Assche, llvm, Catalin Marinas, Arnd Bergmann,
linux-arm-kernel, linux-kernel
While investigating a Clang Context Analysis [1] false positive [2], I started
to dig deeper into arm64's __READ_ONCE() implementation with LTO. That rabbit
hole led me to find one critical bug with the current implementation (patch 1),
and subtle improvements that then enabled me to fix the original false positive.
Patch 1 fixes a bug where READ_ONCE() on types larger than 8 bytes (non-atomic
fallback) incorrectly qualified the pointer rather than the pointee as volatile.
This resulted in a lack of "once" semantics for large struct loads.
Patch 2 refactors the macro to use TYPEOF_UNQUAL and eliminates the ternary
conditional.
Building on the refactor, patch 3 fixes the context analysis false positive, by
helping its alias analysis "see through" the __READ_ONCE despite the inline asm.
## Note on Alternative for Patch 3
An alternative considered for the Context Analysis fix was introducing a helper
function to redirect the pointer alias; specifically passing a pointer to
const-pointer does not invalidate an alias either (casting away the const is a
deliberate escape hatch, albeit somewhat unusual looking). This approach was
slightly more verbose, so the simpler approach was chosen for now. It is
preserved here for future reference in case we need it for something else:
static __always_inline void __set_pointer_opaque(void *const *dst, const void *val)
{
*(void **)dst = (void *)val;
}
...
__set_pointer_opaque((void *const *)&__ret, &__u.__val);
...
[1] https://docs.kernel.org/next/dev-tools/context-analysis.html
[2] https://lore.kernel.org/all/202601221040.TeM0ihff-lkp@intel.com/
---
v2:
* Add __rwonce_typeof_unqual() as fallback for old compilers.
v1: https://lore.kernel.org/all/20260126002936.2676435-1-elver@google.com/
Marco Elver (3):
arm64: Fix non-atomic __READ_ONCE() with CONFIG_LTO=y
arm64: Optimize __READ_ONCE() with CONFIG_LTO=y
arm64, compiler-context-analysis: Permit alias analysis through
__READ_ONCE() with CONFIG_LTO=y
arch/arm64/include/asm/rwonce.h | 29 ++++++++++++++++++++++++-----
1 file changed, 24 insertions(+), 5 deletions(-)
--
2.53.0.rc1.217.geba53bf80e-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 1/3] arm64: Fix non-atomic __READ_ONCE() with CONFIG_LTO=y
2026-01-29 0:52 [PATCH v2 0/3] arm64: Fixes for __READ_ONCE() with CONFIG_LTO=y Marco Elver
@ 2026-01-29 0:52 ` Marco Elver
2026-01-29 1:21 ` Boqun Feng
2026-01-29 0:52 ` [PATCH v2 2/3] arm64: Optimize " Marco Elver
2026-01-29 0:52 ` [PATCH v2 3/3] arm64, compiler-context-analysis: Permit alias analysis through " Marco Elver
2 siblings, 1 reply; 12+ messages in thread
From: Marco Elver @ 2026-01-29 0:52 UTC (permalink / raw)
To: elver, Peter Zijlstra, Will Deacon
Cc: Ingo Molnar, Thomas Gleixner, Boqun Feng, Waiman Long,
Bart Van Assche, llvm, Catalin Marinas, Arnd Bergmann,
linux-arm-kernel, linux-kernel, stable
The implementation of __READ_ONCE() under CONFIG_LTO=y incorrectly
qualified the fallback "once" access for types larger than 8 bytes,
which are not atomic but should still happen "once" and suppress common
compiler optimizations.
The cast `volatile typeof(__x)` applied the volatile qualifier to the
pointer type itself rather than the pointee. This created a volatile
pointer to a non-volatile type, which violated __READ_ONCE() semantics.
Fix this by casting to `volatile typeof(*__x) *`.
With a defconfig + LTO + debug options build, we see the following
functions to be affected:
xen_manage_runstate_time (884 -> 944 bytes)
xen_steal_clock (248 -> 340 bytes)
^-- use __READ_ONCE() to load vcpu_runstate_info structs
Fixes: e35123d83ee3 ("arm64: lto: Strengthen READ_ONCE() to acquire when CONFIG_LTO=y")
Cc: <stable@vger.kernel.org>
Signed-off-by: Marco Elver <elver@google.com>
---
arch/arm64/include/asm/rwonce.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/rwonce.h b/arch/arm64/include/asm/rwonce.h
index 78beceec10cd..fc0fb42b0b64 100644
--- a/arch/arm64/include/asm/rwonce.h
+++ b/arch/arm64/include/asm/rwonce.h
@@ -58,7 +58,7 @@
default: \
atomic = 0; \
} \
- atomic ? (typeof(*__x))__u.__val : (*(volatile typeof(__x))__x);\
+ atomic ? (typeof(*__x))__u.__val : (*(volatile typeof(*__x) *)__x);\
})
#endif /* !BUILD_VDSO */
--
2.53.0.rc1.217.geba53bf80e-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 2/3] arm64: Optimize __READ_ONCE() with CONFIG_LTO=y
2026-01-29 0:52 [PATCH v2 0/3] arm64: Fixes for __READ_ONCE() with CONFIG_LTO=y Marco Elver
2026-01-29 0:52 ` [PATCH v2 1/3] arm64: Fix non-atomic " Marco Elver
@ 2026-01-29 0:52 ` Marco Elver
2026-01-29 10:03 ` David Laight
2026-01-29 0:52 ` [PATCH v2 3/3] arm64, compiler-context-analysis: Permit alias analysis through " Marco Elver
2 siblings, 1 reply; 12+ messages in thread
From: Marco Elver @ 2026-01-29 0:52 UTC (permalink / raw)
To: elver, Peter Zijlstra, Will Deacon
Cc: Ingo Molnar, Thomas Gleixner, Boqun Feng, Waiman Long,
Bart Van Assche, llvm, Catalin Marinas, Arnd Bergmann,
linux-arm-kernel, linux-kernel
Rework arm64 LTO __READ_ONCE() to improve code generation as follows:
1. Replace _Generic-based __unqual_scalar_typeof() with more complete
__rwonce_typeof_unqual(). This strips qualifiers from all types, not
just integer types, which is required to be able to assign (must be
non-const) to __u.__val in the non-atomic case (required for #2).
Once our minimum compiler versions are bumped, this just becomes
TYPEOF_UNQUAL() (or typeof_unqual() should we decide to adopt C23
naming). Sadly the fallback version of __rwonce_typeof_unqual() cannot
be used as a general TYPEOF_UNQUAL() fallback (see code comments).
One subtle point here is that non-integer types of __val could be const
or volatile within the union with the old __unqual_scalar_typeof(), if
the passed variable is const or volatile. This would then result in a
forced load from the stack if __u.__val is volatile; in the case of
const, it does look odd if the underlying storage changes, but the
compiler is told said member is "const" -- it smells like UB.
2. Eliminate the atomic flag and ternary conditional expression. Move
the fallback volatile load into the default case of the switch,
ensuring __u is unconditionally initialized across all paths.
The statement expression now unconditionally returns __u.__val.
This refactoring appears to help the compiler improve (or fix) code
generation.
With a defconfig + LTO + debug options builds, we observe different
codegen for the following functions:
btrfs_reclaim_sweep (708 -> 1032 bytes)
btrfs_sinfo_bg_reclaim_threshold_store (200 -> 204 bytes)
check_mem_access (3652 -> 3692 bytes) [inlined bpf_map_is_rdonly]
console_flush_all (1268 -> 1264 bytes)
console_lock_spinning_disable_and_check (180 -> 176 bytes)
igb_add_filter (640 -> 636 bytes)
igb_config_tx_modes (2404 -> 2400 bytes)
kvm_vcpu_on_spin (480 -> 476 bytes)
map_freeze (376 -> 380 bytes)
netlink_bind (1664 -> 1656 bytes)
nmi_cpu_backtrace (404 -> 400 bytes)
set_rps_cpu (516 -> 520 bytes)
swap_cluster_readahead (944 -> 932 bytes)
tcp_accecn_third_ack (328 -> 336 bytes)
tcp_create_openreq_child (1764 -> 1772 bytes)
tcp_data_queue (5784 -> 5892 bytes)
tcp_ecn_rcv_synack (620 -> 628 bytes)
xen_manage_runstate_time (944 -> 896 bytes)
xen_steal_clock (340 -> 296 bytes)
Increase of some functions are due to more aggressive inlining due to
better codegen (in this build, e.g. bpf_map_is_rdonly is no longer
present due to being inlined completely).
Signed-off-by: Marco Elver <elver@google.com>
---
v2:
* Add __rwonce_typeof_unqual() as fallback for old compilers.
---
arch/arm64/include/asm/rwonce.h | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/include/asm/rwonce.h b/arch/arm64/include/asm/rwonce.h
index fc0fb42b0b64..712de3238f9a 100644
--- a/arch/arm64/include/asm/rwonce.h
+++ b/arch/arm64/include/asm/rwonce.h
@@ -19,6 +19,23 @@
"ldapr" #sfx "\t" #regs, \
ARM64_HAS_LDAPR)
+#ifdef USE_TYPEOF_UNQUAL
+#define __rwonce_typeof_unqual(x) TYPEOF_UNQUAL(x)
+#else
+/*
+ * Fallback for older compilers to infer an unqualified type.
+ *
+ * Uses the fact that auto is supposed to drop qualifiers. Unlike
+ * typeof_unqual(), the type must be complete (defines an unevaluated local
+ * variable); this must trivially hold because __READ_ONCE() returns a value.
+ *
+ * Another caveat is that because of array-to-pointer decay, an array is
+ * inferred as a pointer type; this is fine for __READ_ONCE usage, but is
+ * unsuitable as a general fallback implementation for TYPEOF_UNQUAL.
+ */
+#define __rwonce_typeof_unqual(x) typeof(({ auto ____t = (x); ____t; }))
+#endif
+
/*
* When building with LTO, there is an increased risk of the compiler
* converting an address dependency headed by a READ_ONCE() invocation
@@ -32,8 +49,7 @@
#define __READ_ONCE(x) \
({ \
typeof(&(x)) __x = &(x); \
- int atomic = 1; \
- union { __unqual_scalar_typeof(*__x) __val; char __c[1]; } __u; \
+ union { __rwonce_typeof_unqual(*__x) __val; char __c[1]; } __u; \
switch (sizeof(x)) { \
case 1: \
asm volatile(__LOAD_RCPC(b, %w0, %1) \
@@ -56,9 +72,9 @@
: "Q" (*__x) : "memory"); \
break; \
default: \
- atomic = 0; \
+ __u.__val = *(volatile typeof(*__x) *)__x; \
} \
- atomic ? (typeof(*__x))__u.__val : (*(volatile typeof(*__x) *)__x);\
+ __u.__val; \
})
#endif /* !BUILD_VDSO */
--
2.53.0.rc1.217.geba53bf80e-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v2 3/3] arm64, compiler-context-analysis: Permit alias analysis through __READ_ONCE() with CONFIG_LTO=y
2026-01-29 0:52 [PATCH v2 0/3] arm64: Fixes for __READ_ONCE() with CONFIG_LTO=y Marco Elver
2026-01-29 0:52 ` [PATCH v2 1/3] arm64: Fix non-atomic " Marco Elver
2026-01-29 0:52 ` [PATCH v2 2/3] arm64: Optimize " Marco Elver
@ 2026-01-29 0:52 ` Marco Elver
2026-01-29 2:41 ` Boqun Feng
2026-01-29 9:52 ` David Laight
2 siblings, 2 replies; 12+ messages in thread
From: Marco Elver @ 2026-01-29 0:52 UTC (permalink / raw)
To: elver, Peter Zijlstra, Will Deacon
Cc: Ingo Molnar, Thomas Gleixner, Boqun Feng, Waiman Long,
Bart Van Assche, llvm, Catalin Marinas, Arnd Bergmann,
linux-arm-kernel, linux-kernel, kernel test robot
When enabling Clang's Context Analysis (aka. Thread Safety Analysis) on
kernel/futex/core.o (see Peter's changes at [1]), in arm64 LTO builds we
could see:
| kernel/futex/core.c:982:1: warning: spinlock 'atomic ? __u.__val : q->lock_ptr' is still held at the end of function [-Wthread-safety-analysis]
| 982 | }
| | ^
| kernel/futex/core.c:976:2: note: spinlock acquired here
| 976 | spin_lock(lock_ptr);
| | ^
| kernel/futex/core.c:982:1: warning: expecting spinlock 'q->lock_ptr' to be held at the end of function [-Wthread-safety-analysis]
| 982 | }
| | ^
| kernel/futex/core.c:966:6: note: spinlock acquired here
| 966 | void futex_q_lockptr_lock(struct futex_q *q)
| | ^
| 2 warnings generated.
Where we have:
extern void futex_q_lockptr_lock(struct futex_q *q) __acquires(q->lock_ptr);
..
void futex_q_lockptr_lock(struct futex_q *q)
{
spinlock_t *lock_ptr;
/*
* See futex_unqueue() why lock_ptr can change.
*/
guard(rcu)();
retry:
>> lock_ptr = READ_ONCE(q->lock_ptr);
spin_lock(lock_ptr);
...
}
The READ_ONCE() above is expanded to arm64's LTO __READ_ONCE(). Here,
Clang Thread Safety Analysis's alias analysis resolves 'lock_ptr' to
'atomic ? __u.__val : q->lock_ptr', and considers this the identity of
the context lock given it can't see through the inline assembly;
however, we simply want 'q->lock_ptr' as the canonical context lock.
While for code generation the compiler simplified to __u.__val for
pointers (8 byte case -> atomic), TSA's analysis (a) happens much
earlier on the AST, and (b) would be the wrong deduction.
Now that we've gotten rid of the 'atomic' ternary comparison, we can
return '__u.__val' through a pointer that we initialize with '&x', but
then change with a pointer-to-pointer. When READ_ONCE()'ing a context
lock pointer, TSA's alias analysis does not invalidate the initial alias
when updated through the pointer-to-pointer, and we make it effectively
"see through" the __READ_ONCE().
Code generation is unchanged.
Link: https://lkml.kernel.org/r/20260121110704.221498346@infradead.org [1]
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202601221040.TeM0ihff-lkp@intel.com/
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Marco Elver <elver@google.com>
---
v2:
* Rebase.
---
arch/arm64/include/asm/rwonce.h | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/rwonce.h b/arch/arm64/include/asm/rwonce.h
index 712de3238f9a..3a50a1d0d17e 100644
--- a/arch/arm64/include/asm/rwonce.h
+++ b/arch/arm64/include/asm/rwonce.h
@@ -48,8 +48,11 @@
*/
#define __READ_ONCE(x) \
({ \
- typeof(&(x)) __x = &(x); \
+ auto __x = &(x); \
+ auto __ret = (__rwonce_typeof_unqual(*__x) *)__x; \
+ auto __retp = &__ret; \
union { __rwonce_typeof_unqual(*__x) __val; char __c[1]; } __u; \
+ *__retp = &__u.__val; \
switch (sizeof(x)) { \
case 1: \
asm volatile(__LOAD_RCPC(b, %w0, %1) \
@@ -74,7 +77,7 @@
default: \
__u.__val = *(volatile typeof(*__x) *)__x; \
} \
- __u.__val; \
+ *__ret; \
})
#endif /* !BUILD_VDSO */
--
2.53.0.rc1.217.geba53bf80e-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/3] arm64: Fix non-atomic __READ_ONCE() with CONFIG_LTO=y
2026-01-29 0:52 ` [PATCH v2 1/3] arm64: Fix non-atomic " Marco Elver
@ 2026-01-29 1:21 ` Boqun Feng
2026-01-29 1:32 ` Marco Elver
0 siblings, 1 reply; 12+ messages in thread
From: Boqun Feng @ 2026-01-29 1:21 UTC (permalink / raw)
To: Marco Elver
Cc: Peter Zijlstra, Will Deacon, Ingo Molnar, Thomas Gleixner,
Boqun Feng, Waiman Long, Bart Van Assche, llvm, Catalin Marinas,
Arnd Bergmann, linux-arm-kernel, linux-kernel, stable
On Thu, Jan 29, 2026 at 01:52:32AM +0100, Marco Elver wrote:
> The implementation of __READ_ONCE() under CONFIG_LTO=y incorrectly
> qualified the fallback "once" access for types larger than 8 bytes,
> which are not atomic but should still happen "once" and suppress common
> compiler optimizations.
>
> The cast `volatile typeof(__x)` applied the volatile qualifier to the
> pointer type itself rather than the pointee. This created a volatile
> pointer to a non-volatile type, which violated __READ_ONCE() semantics.
>
> Fix this by casting to `volatile typeof(*__x) *`.
I guess a `volatile typeof(x) *` also works. Either way, good catch!
Reviewed-by: Boqun Feng <boqun@kernel.org>
Regards,
Boqun
>
> With a defconfig + LTO + debug options build, we see the following
> functions to be affected:
>
> xen_manage_runstate_time (884 -> 944 bytes)
> xen_steal_clock (248 -> 340 bytes)
> ^-- use __READ_ONCE() to load vcpu_runstate_info structs
>
> Fixes: e35123d83ee3 ("arm64: lto: Strengthen READ_ONCE() to acquire when CONFIG_LTO=y")
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Marco Elver <elver@google.com>
> ---
> arch/arm64/include/asm/rwonce.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm64/include/asm/rwonce.h b/arch/arm64/include/asm/rwonce.h
> index 78beceec10cd..fc0fb42b0b64 100644
> --- a/arch/arm64/include/asm/rwonce.h
> +++ b/arch/arm64/include/asm/rwonce.h
> @@ -58,7 +58,7 @@
> default: \
> atomic = 0; \
> } \
> - atomic ? (typeof(*__x))__u.__val : (*(volatile typeof(__x))__x);\
> + atomic ? (typeof(*__x))__u.__val : (*(volatile typeof(*__x) *)__x);\
> })
>
> #endif /* !BUILD_VDSO */
> --
> 2.53.0.rc1.217.geba53bf80e-goog
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/3] arm64: Fix non-atomic __READ_ONCE() with CONFIG_LTO=y
2026-01-29 1:21 ` Boqun Feng
@ 2026-01-29 1:32 ` Marco Elver
0 siblings, 0 replies; 12+ messages in thread
From: Marco Elver @ 2026-01-29 1:32 UTC (permalink / raw)
To: Boqun Feng
Cc: Peter Zijlstra, Will Deacon, Ingo Molnar, Thomas Gleixner,
Boqun Feng, Waiman Long, Bart Van Assche, llvm, Catalin Marinas,
Arnd Bergmann, linux-arm-kernel, linux-kernel, stable
On Thu, 29 Jan 2026 at 02:21, Boqun Feng <boqun@kernel.org> wrote:
>
> On Thu, Jan 29, 2026 at 01:52:32AM +0100, Marco Elver wrote:
> > The implementation of __READ_ONCE() under CONFIG_LTO=y incorrectly
> > qualified the fallback "once" access for types larger than 8 bytes,
> > which are not atomic but should still happen "once" and suppress common
> > compiler optimizations.
> >
> > The cast `volatile typeof(__x)` applied the volatile qualifier to the
> > pointer type itself rather than the pointee. This created a volatile
> > pointer to a non-volatile type, which violated __READ_ONCE() semantics.
> >
> > Fix this by casting to `volatile typeof(*__x) *`.
>
> I guess a `volatile typeof(x) *` also works. Either way, good catch!
x might expand to some big expression, so better to refer to it only
once, and then use the same-typed *__x as a proxy. Semantically the
same, but compile-times ought to be better this way.
> Reviewed-by: Boqun Feng <boqun@kernel.org>
Thanks!
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 3/3] arm64, compiler-context-analysis: Permit alias analysis through __READ_ONCE() with CONFIG_LTO=y
2026-01-29 0:52 ` [PATCH v2 3/3] arm64, compiler-context-analysis: Permit alias analysis through " Marco Elver
@ 2026-01-29 2:41 ` Boqun Feng
2026-01-29 9:52 ` David Laight
1 sibling, 0 replies; 12+ messages in thread
From: Boqun Feng @ 2026-01-29 2:41 UTC (permalink / raw)
To: Marco Elver
Cc: Peter Zijlstra, Will Deacon, Ingo Molnar, Thomas Gleixner,
Boqun Feng, Waiman Long, Bart Van Assche, llvm, Catalin Marinas,
Arnd Bergmann, linux-arm-kernel, linux-kernel, kernel test robot
On Thu, Jan 29, 2026 at 01:52:34AM +0100, Marco Elver wrote:
> When enabling Clang's Context Analysis (aka. Thread Safety Analysis) on
> kernel/futex/core.o (see Peter's changes at [1]), in arm64 LTO builds we
> could see:
>
> | kernel/futex/core.c:982:1: warning: spinlock 'atomic ? __u.__val : q->lock_ptr' is still held at the end of function [-Wthread-safety-analysis]
> | 982 | }
> | | ^
> | kernel/futex/core.c:976:2: note: spinlock acquired here
> | 976 | spin_lock(lock_ptr);
> | | ^
> | kernel/futex/core.c:982:1: warning: expecting spinlock 'q->lock_ptr' to be held at the end of function [-Wthread-safety-analysis]
> | 982 | }
> | | ^
> | kernel/futex/core.c:966:6: note: spinlock acquired here
> | 966 | void futex_q_lockptr_lock(struct futex_q *q)
> | | ^
> | 2 warnings generated.
>
> Where we have:
>
> extern void futex_q_lockptr_lock(struct futex_q *q) __acquires(q->lock_ptr);
> ..
> void futex_q_lockptr_lock(struct futex_q *q)
> {
> spinlock_t *lock_ptr;
>
> /*
> * See futex_unqueue() why lock_ptr can change.
> */
> guard(rcu)();
> retry:
> >> lock_ptr = READ_ONCE(q->lock_ptr);
> spin_lock(lock_ptr);
> ...
> }
>
> The READ_ONCE() above is expanded to arm64's LTO __READ_ONCE(). Here,
> Clang Thread Safety Analysis's alias analysis resolves 'lock_ptr' to
> 'atomic ? __u.__val : q->lock_ptr', and considers this the identity of
> the context lock given it can't see through the inline assembly;
> however, we simply want 'q->lock_ptr' as the canonical context lock.
> While for code generation the compiler simplified to __u.__val for
> pointers (8 byte case -> atomic), TSA's analysis (a) happens much
> earlier on the AST, and (b) would be the wrong deduction.
>
> Now that we've gotten rid of the 'atomic' ternary comparison, we can
> return '__u.__val' through a pointer that we initialize with '&x', but
> then change with a pointer-to-pointer. When READ_ONCE()'ing a context
> lock pointer, TSA's alias analysis does not invalidate the initial alias
> when updated through the pointer-to-pointer, and we make it effectively
> "see through" the __READ_ONCE().
>
Seems reasonable to me, but I don't have the compiler knowledge to do a
full review, so:
Tested-by: Boqun Feng <boqun@kernel.org>
We also have similar issues for asm-based smp_load_acquire(), to trigger
that, you can just replace `READ_ONCE(q->lock_ptr)` with
`smp_load_acquire(&q->lock_ptr)`.
Regards,
Boqun
> Code generation is unchanged.
>
> Link: https://lkml.kernel.org/r/20260121110704.221498346@infradead.org [1]
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202601221040.TeM0ihff-lkp@intel.com/
> Cc: Peter Zijlstra <peterz@infradead.org>
> Signed-off-by: Marco Elver <elver@google.com>
> ---
> v2:
> * Rebase.
> ---
> arch/arm64/include/asm/rwonce.h | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/include/asm/rwonce.h b/arch/arm64/include/asm/rwonce.h
> index 712de3238f9a..3a50a1d0d17e 100644
> --- a/arch/arm64/include/asm/rwonce.h
> +++ b/arch/arm64/include/asm/rwonce.h
> @@ -48,8 +48,11 @@
> */
> #define __READ_ONCE(x) \
> ({ \
> - typeof(&(x)) __x = &(x); \
> + auto __x = &(x); \
> + auto __ret = (__rwonce_typeof_unqual(*__x) *)__x; \
> + auto __retp = &__ret; \
> union { __rwonce_typeof_unqual(*__x) __val; char __c[1]; } __u; \
> + *__retp = &__u.__val; \
> switch (sizeof(x)) { \
> case 1: \
> asm volatile(__LOAD_RCPC(b, %w0, %1) \
> @@ -74,7 +77,7 @@
> default: \
> __u.__val = *(volatile typeof(*__x) *)__x; \
> } \
> - __u.__val; \
> + *__ret; \
> })
>
> #endif /* !BUILD_VDSO */
> --
> 2.53.0.rc1.217.geba53bf80e-goog
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 3/3] arm64, compiler-context-analysis: Permit alias analysis through __READ_ONCE() with CONFIG_LTO=y
2026-01-29 0:52 ` [PATCH v2 3/3] arm64, compiler-context-analysis: Permit alias analysis through " Marco Elver
2026-01-29 2:41 ` Boqun Feng
@ 2026-01-29 9:52 ` David Laight
2026-01-30 12:04 ` Marco Elver
1 sibling, 1 reply; 12+ messages in thread
From: David Laight @ 2026-01-29 9:52 UTC (permalink / raw)
To: Marco Elver
Cc: Peter Zijlstra, Will Deacon, Ingo Molnar, Thomas Gleixner,
Boqun Feng, Waiman Long, Bart Van Assche, llvm, Catalin Marinas,
Arnd Bergmann, linux-arm-kernel, linux-kernel, kernel test robot
On Thu, 29 Jan 2026 01:52:34 +0100
Marco Elver <elver@google.com> wrote:
> When enabling Clang's Context Analysis (aka. Thread Safety Analysis) on
> kernel/futex/core.o (see Peter's changes at [1]), in arm64 LTO builds we
> could see:
>
> | kernel/futex/core.c:982:1: warning: spinlock 'atomic ? __u.__val : q->lock_ptr' is still held at the end of function [-Wthread-safety-analysis]
> | 982 | }
> | | ^
> | kernel/futex/core.c:976:2: note: spinlock acquired here
> | 976 | spin_lock(lock_ptr);
> | | ^
> | kernel/futex/core.c:982:1: warning: expecting spinlock 'q->lock_ptr' to be held at the end of function [-Wthread-safety-analysis]
> | 982 | }
> | | ^
> | kernel/futex/core.c:966:6: note: spinlock acquired here
> | 966 | void futex_q_lockptr_lock(struct futex_q *q)
> | | ^
> | 2 warnings generated.
>
> Where we have:
>
> extern void futex_q_lockptr_lock(struct futex_q *q) __acquires(q->lock_ptr);
> ..
> void futex_q_lockptr_lock(struct futex_q *q)
> {
> spinlock_t *lock_ptr;
>
> /*
> * See futex_unqueue() why lock_ptr can change.
> */
> guard(rcu)();
> retry:
> >> lock_ptr = READ_ONCE(q->lock_ptr);
> spin_lock(lock_ptr);
> ...
> }
>
> The READ_ONCE() above is expanded to arm64's LTO __READ_ONCE(). Here,
> Clang Thread Safety Analysis's alias analysis resolves 'lock_ptr' to
> 'atomic ? __u.__val : q->lock_ptr',
Doesn't the previous patch remove that conditional?
This description should really refer to the code before this patch.
> and considers this the identity of
> the context lock given it can't see through the inline assembly;
> however, we simply want 'q->lock_ptr' as the canonical context lock.
> While for code generation the compiler simplified to __u.__val for
> pointers (8 byte case -> atomic), TSA's analysis (a) happens much
> earlier on the AST, and (b) would be the wrong deduction.
>
> Now that we've gotten rid of the 'atomic' ternary comparison, we can
> return '__u.__val' through a pointer that we initialize with '&x', but
> then change with a pointer-to-pointer. When READ_ONCE()'ing a context
> lock pointer, TSA's alias analysis does not invalidate the initial alias
> when updated through the pointer-to-pointer, and we make it effectively
> "see through" the __READ_ONCE().
Some of that need to be a comment in the code.
I also suspect you've just found a bug in the TSA logic.
>
> Code generation is unchanged.
>
> Link: https://lkml.kernel.org/r/20260121110704.221498346@infradead.org [1]
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202601221040.TeM0ihff-lkp@intel.com/
> Cc: Peter Zijlstra <peterz@infradead.org>
> Signed-off-by: Marco Elver <elver@google.com>
> ---
> v2:
> * Rebase.
> ---
> arch/arm64/include/asm/rwonce.h | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/include/asm/rwonce.h b/arch/arm64/include/asm/rwonce.h
> index 712de3238f9a..3a50a1d0d17e 100644
> --- a/arch/arm64/include/asm/rwonce.h
> +++ b/arch/arm64/include/asm/rwonce.h
> @@ -48,8 +48,11 @@
> */
> #define __READ_ONCE(x) \
> ({ \
> - typeof(&(x)) __x = &(x); \
> + auto __x = &(x); \
> + auto __ret = (__rwonce_typeof_unqual(*__x) *)__x; \
> + auto __retp = &__ret; \
> union { __rwonce_typeof_unqual(*__x) __val; char __c[1]; } __u; \
Can you define __val using typeof(__ret)?
Saves expanding the macro twice (although it isn't the horrid
__unqual_scaler_typeof() any more).
David
> + *__retp = &__u.__val; \
> switch (sizeof(x)) { \
> case 1: \
> asm volatile(__LOAD_RCPC(b, %w0, %1) \
> @@ -74,7 +77,7 @@
> default: \
> __u.__val = *(volatile typeof(*__x) *)__x; \
> } \
> - __u.__val; \
> + *__ret; \
> })
>
> #endif /* !BUILD_VDSO */
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 2/3] arm64: Optimize __READ_ONCE() with CONFIG_LTO=y
2026-01-29 0:52 ` [PATCH v2 2/3] arm64: Optimize " Marco Elver
@ 2026-01-29 10:03 ` David Laight
2026-01-29 10:12 ` Marco Elver
0 siblings, 1 reply; 12+ messages in thread
From: David Laight @ 2026-01-29 10:03 UTC (permalink / raw)
To: Marco Elver
Cc: Peter Zijlstra, Will Deacon, Ingo Molnar, Thomas Gleixner,
Boqun Feng, Waiman Long, Bart Van Assche, llvm, Catalin Marinas,
Arnd Bergmann, linux-arm-kernel, linux-kernel
On Thu, 29 Jan 2026 01:52:33 +0100
Marco Elver <elver@google.com> wrote:
> Rework arm64 LTO __READ_ONCE() to improve code generation as follows:
>
> 1. Replace _Generic-based __unqual_scalar_typeof() with more complete
> __rwonce_typeof_unqual(). This strips qualifiers from all types, not
> just integer types, which is required to be able to assign (must be
> non-const) to __u.__val in the non-atomic case (required for #2).
>
> Once our minimum compiler versions are bumped, this just becomes
> TYPEOF_UNQUAL() (or typeof_unqual() should we decide to adopt C23
> naming). Sadly the fallback version of __rwonce_typeof_unqual() cannot
> be used as a general TYPEOF_UNQUAL() fallback (see code comments).
>
> One subtle point here is that non-integer types of __val could be const
> or volatile within the union with the old __unqual_scalar_typeof(), if
> the passed variable is const or volatile. This would then result in a
> forced load from the stack if __u.__val is volatile; in the case of
> const, it does look odd if the underlying storage changes, but the
> compiler is told said member is "const" -- it smells like UB.
>
> 2. Eliminate the atomic flag and ternary conditional expression. Move
> the fallback volatile load into the default case of the switch,
> ensuring __u is unconditionally initialized across all paths.
> The statement expression now unconditionally returns __u.__val.
>
...
> Signed-off-by: Marco Elver <elver@google.com>
> ---
> v2:
> * Add __rwonce_typeof_unqual() as fallback for old compilers.
> ---
> arch/arm64/include/asm/rwonce.h | 24 ++++++++++++++++++++----
> 1 file changed, 20 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/include/asm/rwonce.h b/arch/arm64/include/asm/rwonce.h
> index fc0fb42b0b64..712de3238f9a 100644
> --- a/arch/arm64/include/asm/rwonce.h
> +++ b/arch/arm64/include/asm/rwonce.h
> @@ -19,6 +19,23 @@
> "ldapr" #sfx "\t" #regs, \
> ARM64_HAS_LDAPR)
>
> +#ifdef USE_TYPEOF_UNQUAL
> +#define __rwonce_typeof_unqual(x) TYPEOF_UNQUAL(x)
> +#else
> +/*
> + * Fallback for older compilers to infer an unqualified type.
> + *
> + * Uses the fact that auto is supposed to drop qualifiers. Unlike
Maybe:
In all versions of clang 'auto' correctly drops qualifiers.
A reminder in here that this is clang only might also clarify things.
> + * typeof_unqual(), the type must be complete (defines an unevaluated local
> + * variable); this must trivially hold because __READ_ONCE() returns a value.
Not sure that is needed.
> + *
> + * Another caveat is that because of array-to-pointer decay, an array is
> + * inferred as a pointer type; this is fine for __READ_ONCE usage, but is
> + * unsuitable as a general fallback implementation for TYPEOF_UNQUAL.
gcc < 11.0 stops it being used elsewhere.
Something shorter?
The arrary-to-pointer decay doesn't matter here.
David
> + */
> +#define __rwonce_typeof_unqual(x) typeof(({ auto ____t = (x); ____t; }))
> +#endif
> +
> /*
> * When building with LTO, there is an increased risk of the compiler
> * converting an address dependency headed by a READ_ONCE() invocation
> @@ -32,8 +49,7 @@
> #define __READ_ONCE(x) \
> ({ \
> typeof(&(x)) __x = &(x); \
> - int atomic = 1; \
> - union { __unqual_scalar_typeof(*__x) __val; char __c[1]; } __u; \
> + union { __rwonce_typeof_unqual(*__x) __val; char __c[1]; } __u; \
> switch (sizeof(x)) { \
> case 1: \
> asm volatile(__LOAD_RCPC(b, %w0, %1) \
> @@ -56,9 +72,9 @@
> : "Q" (*__x) : "memory"); \
> break; \
> default: \
> - atomic = 0; \
> + __u.__val = *(volatile typeof(*__x) *)__x; \
> } \
> - atomic ? (typeof(*__x))__u.__val : (*(volatile typeof(*__x) *)__x);\
> + __u.__val; \
> })
>
> #endif /* !BUILD_VDSO */
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 2/3] arm64: Optimize __READ_ONCE() with CONFIG_LTO=y
2026-01-29 10:03 ` David Laight
@ 2026-01-29 10:12 ` Marco Elver
2026-01-29 10:39 ` David Laight
0 siblings, 1 reply; 12+ messages in thread
From: Marco Elver @ 2026-01-29 10:12 UTC (permalink / raw)
To: David Laight
Cc: Peter Zijlstra, Will Deacon, Ingo Molnar, Thomas Gleixner,
Boqun Feng, Waiman Long, Bart Van Assche, llvm, Catalin Marinas,
Arnd Bergmann, linux-arm-kernel, linux-kernel
On Thu, 29 Jan 2026 at 11:03, David Laight <david.laight.linux@gmail.com> wrote:
>
> On Thu, 29 Jan 2026 01:52:33 +0100
> Marco Elver <elver@google.com> wrote:
>
> > Rework arm64 LTO __READ_ONCE() to improve code generation as follows:
> >
> > 1. Replace _Generic-based __unqual_scalar_typeof() with more complete
> > __rwonce_typeof_unqual(). This strips qualifiers from all types, not
> > just integer types, which is required to be able to assign (must be
> > non-const) to __u.__val in the non-atomic case (required for #2).
> >
> > Once our minimum compiler versions are bumped, this just becomes
> > TYPEOF_UNQUAL() (or typeof_unqual() should we decide to adopt C23
> > naming). Sadly the fallback version of __rwonce_typeof_unqual() cannot
> > be used as a general TYPEOF_UNQUAL() fallback (see code comments).
> >
> > One subtle point here is that non-integer types of __val could be const
> > or volatile within the union with the old __unqual_scalar_typeof(), if
> > the passed variable is const or volatile. This would then result in a
> > forced load from the stack if __u.__val is volatile; in the case of
> > const, it does look odd if the underlying storage changes, but the
> > compiler is told said member is "const" -- it smells like UB.
> >
> > 2. Eliminate the atomic flag and ternary conditional expression. Move
> > the fallback volatile load into the default case of the switch,
> > ensuring __u is unconditionally initialized across all paths.
> > The statement expression now unconditionally returns __u.__val.
> >
> ...
> > Signed-off-by: Marco Elver <elver@google.com>
> > ---
> > v2:
> > * Add __rwonce_typeof_unqual() as fallback for old compilers.
> > ---
> > arch/arm64/include/asm/rwonce.h | 24 ++++++++++++++++++++----
> > 1 file changed, 20 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/rwonce.h b/arch/arm64/include/asm/rwonce.h
> > index fc0fb42b0b64..712de3238f9a 100644
> > --- a/arch/arm64/include/asm/rwonce.h
> > +++ b/arch/arm64/include/asm/rwonce.h
> > @@ -19,6 +19,23 @@
> > "ldapr" #sfx "\t" #regs, \
> > ARM64_HAS_LDAPR)
> >
> > +#ifdef USE_TYPEOF_UNQUAL
> > +#define __rwonce_typeof_unqual(x) TYPEOF_UNQUAL(x)
> > +#else
> > +/*
> > + * Fallback for older compilers to infer an unqualified type.
> > + *
> > + * Uses the fact that auto is supposed to drop qualifiers. Unlike
>
> Maybe:
> In all versions of clang 'auto' correctly drops qualifiers.
> A reminder in here that this is clang only might also clarify things.
Will add.
> > + * typeof_unqual(), the type must be complete (defines an unevaluated local
> > + * variable); this must trivially hold because __READ_ONCE() returns a value.
>
> Not sure that is needed.
Trying to warn against someone copy-pasting this as a TYPEOF_UNQUAL
fallback implementation. typeof() and typeof_unqual() do happily take
incomplete struct declarations. E.g. this works:
struct foo;
...
struct foo *f;
typeof_unqual(*f) *x = f;
Whereas with the __rwonce_typeof_unqual() fallback this doesn't work.
I can try to make it clearer.
> > + *
> > + * Another caveat is that because of array-to-pointer decay, an array is
> > + * inferred as a pointer type; this is fine for __READ_ONCE usage, but is
> > + * unsuitable as a general fallback implementation for TYPEOF_UNQUAL.
>
> gcc < 11.0 stops it being used elsewhere.
> Something shorter?
> The arrary-to-pointer decay doesn't matter here.
Ack.
Thanks!
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 2/3] arm64: Optimize __READ_ONCE() with CONFIG_LTO=y
2026-01-29 10:12 ` Marco Elver
@ 2026-01-29 10:39 ` David Laight
0 siblings, 0 replies; 12+ messages in thread
From: David Laight @ 2026-01-29 10:39 UTC (permalink / raw)
To: Marco Elver
Cc: Peter Zijlstra, Will Deacon, Ingo Molnar, Thomas Gleixner,
Boqun Feng, Waiman Long, Bart Van Assche, llvm, Catalin Marinas,
Arnd Bergmann, linux-arm-kernel, linux-kernel
On Thu, 29 Jan 2026 11:12:49 +0100
Marco Elver <elver@google.com> wrote:
> On Thu, 29 Jan 2026 at 11:03, David Laight <david.laight.linux@gmail.com> wrote:
> >
> > On Thu, 29 Jan 2026 01:52:33 +0100
> > Marco Elver <elver@google.com> wrote:
> >
> > > Rework arm64 LTO __READ_ONCE() to improve code generation as follows:
> > >
> > > 1. Replace _Generic-based __unqual_scalar_typeof() with more complete
> > > __rwonce_typeof_unqual(). This strips qualifiers from all types, not
> > > just integer types, which is required to be able to assign (must be
> > > non-const) to __u.__val in the non-atomic case (required for #2).
> > >
> > > Once our minimum compiler versions are bumped, this just becomes
> > > TYPEOF_UNQUAL() (or typeof_unqual() should we decide to adopt C23
> > > naming). Sadly the fallback version of __rwonce_typeof_unqual() cannot
> > > be used as a general TYPEOF_UNQUAL() fallback (see code comments).
> > >
> > > One subtle point here is that non-integer types of __val could be const
> > > or volatile within the union with the old __unqual_scalar_typeof(), if
> > > the passed variable is const or volatile. This would then result in a
> > > forced load from the stack if __u.__val is volatile; in the case of
> > > const, it does look odd if the underlying storage changes, but the
> > > compiler is told said member is "const" -- it smells like UB.
> > >
> > > 2. Eliminate the atomic flag and ternary conditional expression. Move
> > > the fallback volatile load into the default case of the switch,
> > > ensuring __u is unconditionally initialized across all paths.
> > > The statement expression now unconditionally returns __u.__val.
> > >
> > ...
> > > Signed-off-by: Marco Elver <elver@google.com>
> > > ---
> > > v2:
> > > * Add __rwonce_typeof_unqual() as fallback for old compilers.
> > > ---
> > > arch/arm64/include/asm/rwonce.h | 24 ++++++++++++++++++++----
> > > 1 file changed, 20 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/arch/arm64/include/asm/rwonce.h b/arch/arm64/include/asm/rwonce.h
> > > index fc0fb42b0b64..712de3238f9a 100644
> > > --- a/arch/arm64/include/asm/rwonce.h
> > > +++ b/arch/arm64/include/asm/rwonce.h
> > > @@ -19,6 +19,23 @@
> > > "ldapr" #sfx "\t" #regs, \
> > > ARM64_HAS_LDAPR)
> > >
> > > +#ifdef USE_TYPEOF_UNQUAL
> > > +#define __rwonce_typeof_unqual(x) TYPEOF_UNQUAL(x)
> > > +#else
> > > +/*
> > > + * Fallback for older compilers to infer an unqualified type.
> > > + *
> > > + * Uses the fact that auto is supposed to drop qualifiers. Unlike
> >
> > Maybe:
> > In all versions of clang 'auto' correctly drops qualifiers.
> > A reminder in here that this is clang only might also clarify things.
>
> Will add.
>
> > > + * typeof_unqual(), the type must be complete (defines an unevaluated local
> > > + * variable); this must trivially hold because __READ_ONCE() returns a value.
> >
> > Not sure that is needed.
>
> Trying to warn against someone copy-pasting this as a TYPEOF_UNQUAL
> fallback implementation. typeof() and typeof_unqual() do happily take
> incomplete struct declarations. E.g. this works:
>
> struct foo;
> ...
> struct foo *f;
> typeof_unqual(*f) *x = f;
>
> Whereas with the __rwonce_typeof_unqual() fallback this doesn't work.
> I can try to make it clearer.
It fails to compile - they'll find out soon enough :-)
gcc < 11 and the array/pointer decay are probably more relevant.
Could catch out the unwary.
David
>
> > > + *
> > > + * Another caveat is that because of array-to-pointer decay, an array is
> > > + * inferred as a pointer type; this is fine for __READ_ONCE usage, but is
> > > + * unsuitable as a general fallback implementation for TYPEOF_UNQUAL.
> >
> > gcc < 11.0 stops it being used elsewhere.
> > Something shorter?
> > The array-to-pointer decay doesn't matter here.
>
> Ack.
>
> Thanks!
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 3/3] arm64, compiler-context-analysis: Permit alias analysis through __READ_ONCE() with CONFIG_LTO=y
2026-01-29 9:52 ` David Laight
@ 2026-01-30 12:04 ` Marco Elver
0 siblings, 0 replies; 12+ messages in thread
From: Marco Elver @ 2026-01-30 12:04 UTC (permalink / raw)
To: David Laight
Cc: Peter Zijlstra, Will Deacon, Ingo Molnar, Thomas Gleixner,
Boqun Feng, Waiman Long, Bart Van Assche, llvm, Catalin Marinas,
Arnd Bergmann, linux-arm-kernel, linux-kernel, kernel test robot
On Thu, 29 Jan 2026 at 12:31, David Laight <david.laight.linux@gmail.com> wrote:
>
> On Thu, 29 Jan 2026 01:52:34 +0100
> Marco Elver <elver@google.com> wrote:
>
> > When enabling Clang's Context Analysis (aka. Thread Safety Analysis) on
> > kernel/futex/core.o (see Peter's changes at [1]), in arm64 LTO builds we
> > could see:
> >
> > | kernel/futex/core.c:982:1: warning: spinlock 'atomic ? __u.__val : q->lock_ptr' is still held at the end of function [-Wthread-safety-analysis]
> > | 982 | }
> > | | ^
> > | kernel/futex/core.c:976:2: note: spinlock acquired here
> > | 976 | spin_lock(lock_ptr);
> > | | ^
> > | kernel/futex/core.c:982:1: warning: expecting spinlock 'q->lock_ptr' to be held at the end of function [-Wthread-safety-analysis]
> > | 982 | }
> > | | ^
> > | kernel/futex/core.c:966:6: note: spinlock acquired here
> > | 966 | void futex_q_lockptr_lock(struct futex_q *q)
> > | | ^
> > | 2 warnings generated.
> >
> > Where we have:
> >
> > extern void futex_q_lockptr_lock(struct futex_q *q) __acquires(q->lock_ptr);
> > ..
> > void futex_q_lockptr_lock(struct futex_q *q)
> > {
> > spinlock_t *lock_ptr;
> >
> > /*
> > * See futex_unqueue() why lock_ptr can change.
> > */
> > guard(rcu)();
> > retry:
> > >> lock_ptr = READ_ONCE(q->lock_ptr);
> > spin_lock(lock_ptr);
> > ...
> > }
> >
> > The READ_ONCE() above is expanded to arm64's LTO __READ_ONCE(). Here,
> > Clang Thread Safety Analysis's alias analysis resolves 'lock_ptr' to
> > 'atomic ? __u.__val : q->lock_ptr',
>
> Doesn't the previous patch remove that conditional?
> This description should really refer to the code before this patch.
Will word-smith this a bit. But this refers to the state of where the
original issue was found that spawned all this.
> > and considers this the identity of
> > the context lock given it can't see through the inline assembly;
> > however, we simply want 'q->lock_ptr' as the canonical context lock.
> > While for code generation the compiler simplified to __u.__val for
> > pointers (8 byte case -> atomic), TSA's analysis (a) happens much
> > earlier on the AST, and (b) would be the wrong deduction.
> >
> > Now that we've gotten rid of the 'atomic' ternary comparison, we can
> > return '__u.__val' through a pointer that we initialize with '&x', but
> > then change with a pointer-to-pointer. When READ_ONCE()'ing a context
> > lock pointer, TSA's alias analysis does not invalidate the initial alias
> > when updated through the pointer-to-pointer, and we make it effectively
> > "see through" the __READ_ONCE().
>
> Some of that need to be a comment in the code.
> I also suspect you've just found a bug in the TSA logic.
Adding a comment. From a soundness POV, yes it's a bug, but I think
reassigning a pointer via a pointer-to-pointer in the same scope is
just pointless, so I'm willing to keep this as a deliberate escape
hatch (might need to add a test to Clang to capture this and discuss
if someone wants to change).
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-01-30 12:05 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-29 0:52 [PATCH v2 0/3] arm64: Fixes for __READ_ONCE() with CONFIG_LTO=y Marco Elver
2026-01-29 0:52 ` [PATCH v2 1/3] arm64: Fix non-atomic " Marco Elver
2026-01-29 1:21 ` Boqun Feng
2026-01-29 1:32 ` Marco Elver
2026-01-29 0:52 ` [PATCH v2 2/3] arm64: Optimize " Marco Elver
2026-01-29 10:03 ` David Laight
2026-01-29 10:12 ` Marco Elver
2026-01-29 10:39 ` David Laight
2026-01-29 0:52 ` [PATCH v2 3/3] arm64, compiler-context-analysis: Permit alias analysis through " Marco Elver
2026-01-29 2:41 ` Boqun Feng
2026-01-29 9:52 ` David Laight
2026-01-30 12:04 ` Marco Elver
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox