diff options
| author | Thomas Gleixner <tglx@kernel.org> | 2026-06-02 11:09:59 +0200 |
|---|---|---|
| committer | Peter Zijlstra <peterz@infradead.org> | 2026-06-03 11:38:51 +0200 |
| commit | 042df0c1d48609a85580dcbaff498c95ced20a5f (patch) | |
| tree | dec68717e0917a52adf84e5943c2fb762a2387c5 /include/linux/futex.h | |
| parent | 3ca9595d9fb6cce6633a5b03d98c2aecb5499838 (diff) | |
| download | lwn-042df0c1d48609a85580dcbaff498c95ced20a5f.tar.gz lwn-042df0c1d48609a85580dcbaff498c95ced20a5f.zip | |
futex: Add robust futex unlock IP range
There will be a VDSO function to unlock robust futexes in user space. The
unlock sequence is racy vs. clearing the list_pending_op pointer in the
tasks robust list head. To plug this race the kernel needs to know the
instruction window. As the VDSO is per MM the addresses are stored in
mm_struct::futex.
Architectures which implement support for this have to update these
addresses when the VDSO is (re)mapped and indicate the pending op pointer
size which is matching the IP.
Arguably this could be resolved by chasing mm->context->vdso->image, but
that's architecture specific and requires to touch quite some cache
lines. Having it in mm::futex reduces the cache line impact and avoids
having yet another set of architecture specific functionality.
To support multi size robust list applications (gaming) this provides two
ranges when COMPAT is enabled.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: André Almeida <andrealmeid@igalia.com>
Link: https://patch.msgid.link/20260602090535.718926819@kernel.org
Diffstat (limited to 'include/linux/futex.h')
| -rw-r--r-- | include/linux/futex.h | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/include/linux/futex.h b/include/linux/futex.h index 9e6218c2be66..cb2a182547dd 100644 --- a/include/linux/futex.h +++ b/include/linux/futex.h @@ -81,11 +81,9 @@ int futex_hash_prctl(unsigned long arg2, unsigned long arg3, unsigned long arg4) #ifdef CONFIG_FUTEX_PRIVATE_HASH int futex_hash_allocate_default(void); void futex_hash_free(struct mm_struct *mm); -void futex_mm_init(struct mm_struct *mm); #else /* CONFIG_FUTEX_PRIVATE_HASH */ static inline int futex_hash_allocate_default(void) { return 0; } static inline int futex_hash_free(struct mm_struct *mm) { return 0; } -static inline void futex_mm_init(struct mm_struct *mm) { } #endif /* !CONFIG_FUTEX_PRIVATE_HASH */ #else /* CONFIG_FUTEX */ @@ -104,7 +102,24 @@ static inline int futex_hash_prctl(unsigned long arg2, unsigned long arg3, unsig } static inline int futex_hash_allocate_default(void) { return 0; } static inline int futex_hash_free(struct mm_struct *mm) { return 0; } -static inline void futex_mm_init(struct mm_struct *mm) { } #endif /* !CONFIG_FUTEX */ +#ifdef CONFIG_FUTEX_ROBUST_UNLOCK +void futex_reset_cs_ranges(struct futex_mm_data *fd); + +static inline void futex_set_vdso_cs_range(struct futex_mm_data *fd, unsigned int idx, + unsigned long start, unsigned long end, bool sz32) +{ + fd->unlock.cs_ranges[idx].start_ip = start; + fd->unlock.cs_ranges[idx].len = end - start; + fd->unlock.cs_ranges[idx].pop_size32 = sz32; +} +#endif /* CONFIG_FUTEX_ROBUST_UNLOCK */ + +#if defined(CONFIG_FUTEX_PRIVATE_HASH) || defined(CONFIG_FUTEX_ROBUST_UNLOCK) +void futex_mm_init(struct mm_struct *mm); +#else +static inline void futex_mm_init(struct mm_struct *mm) { } +#endif + #endif /* _LINUX_FUTEX_H */ |
