[tip: locking/futex] futex: Relax the rcu_assign_pointer() assignment of mm->futex_phash in futex_mm_init()
From: tip-bot2 for Ingo Molnar
Date: Sun May 11 2025 - 04:11:52 EST
The following commit has been merged into the locking/futex branch of tip:
Commit-ID: 094ac8cff7858bee5fa4554f6ea66c964f8e160e
Gitweb: https://git.kernel.org/tip/094ac8cff7858bee5fa4554f6ea66c964f8e160e
Author: Ingo Molnar <mingo@xxxxxxxxxx>
AuthorDate: Sat, 10 May 2025 10:45:28 +02:00
Committer: Ingo Molnar <mingo@xxxxxxxxxx>
CommitterDate: Sun, 11 May 2025 10:02:12 +02:00
futex: Relax the rcu_assign_pointer() assignment of mm->futex_phash in futex_mm_init()
The following commit added an rcu_assign_pointer() assignment to
futex_mm_init() in <linux/futex.h>:
bd54df5ea7ca ("futex: Allow to resize the private local hash")
Which breaks the build on older compilers (gcc-9, x86-64 defconfig):
CC io_uring/futex.o
In file included from ./arch/x86/include/generated/asm/rwonce.h:1,
from ./include/linux/compiler.h:390,
from ./include/linux/array_size.h:5,
from ./include/linux/kernel.h:16,
from io_uring/futex.c:2:
./include/linux/futex.h: In function 'futex_mm_init':
./include/linux/rcupdate.h:555:36: error: dereferencing pointer to incomplete type 'struct futex_private_hash'
The problem is that this variant of rcu_assign_pointer() wants to
know the full type of 'struct futex_private_hash', which type
is local to futex.c:
kernel/futex/core.c:struct futex_private_hash {
There are a couple of mechanical solutions for this bug:
- we can uninline futex_mm_init() and move it into futex/core.c
- or we can share the structure definition with kernel/fork.c.
But both of these solutions have disadvantages: the first one adds
runtime overhead, while the second one dis-encapsulates private
futex types.
A third solution, implemented by this patch, is to just initialize
mm->futex_phash with NULL like the patch below, it's not like this
new MM's ->futex_phash can be observed externally until the task
is inserted into the task list, which guarantees full store ordering.
The relaxation of this initialization might also give a tiny speedup
on certain platforms.
Fixes: bd54df5ea7ca ("futex: Allow to resize the private local hash")
Signed-off-by: Ingo Molnar <mingo@xxxxxxxxxx>
Cc: André Almeida <andrealmeid@xxxxxxxxxx>
Cc: Darren Hart <dvhart@xxxxxxxxxxxxx>
Cc: Davidlohr Bueso <dave@xxxxxxxxxxxx>
Cc: Juri Lelli <juri.lelli@xxxxxxxxxx>
Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
Cc: Valentin Schneider <vschneid@xxxxxxxxxx>
Cc: Waiman Long <longman@xxxxxxxxxx>
Link: https://lore.kernel.org/r/aB8SI00EHBri23lB@xxxxxxxxx
---
include/linux/futex.h | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/include/linux/futex.h b/include/linux/futex.h
index eccc997..168ffd5 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -88,7 +88,14 @@ void futex_hash_free(struct mm_struct *mm);
static inline void futex_mm_init(struct mm_struct *mm)
{
- rcu_assign_pointer(mm->futex_phash, NULL);
+ /*
+ * No need for rcu_assign_pointer() here, as we can rely on
+ * tasklist_lock write-ordering in copy_process(), before
+ * the task's MM becomes visible and the ->futex_phash
+ * becomes externally observable:
+ */
+ mm->futex_phash = NULL;
+
mutex_init(&mm->futex_hash_lock);
}