Re: [patch 8/8] x86/vdso: Implement __vdso_futex_robust_try_unlock()
From: Mathieu Desnoyers
Date: Mon Mar 16 2026 - 15:23:47 EST
On 2026-03-16 13:13, Thomas Gleixner wrote:
When the FUTEX_ROBUST_UNLOCK mechanism is used for unlocking (PI-)futexes,[...]
then the unlock sequence in userspace looks like this:
1) robust_list_set_op_pending(mutex);
2) robust_list_remove(mutex);
lval = gettid();
3) if (atomic_try_cmpxchg(&mutex->lock, lval, 0))
4) robust_list_clear_op_pending();
else
5) sys_futex(OP,...FUTEX_ROBUST_UNLOCK);
When then the original task exits before reaching #6 then the kernel robust
list handling observes the pending op entry and tries to fix up user space.
There is no #6.
[...]
+
+uint32_t __vdso_futex_robust_try_unlock(uint32_t *lock, uint32_t tid, void *pop)
I'm not sure I see the link between "list_pending_op" and @pop ?
+{
+ asm volatile (
+ ".global __vdso_futex_robust_try_unlock_cs_start \n"
+ ".global __vdso_futex_robust_try_unlock_cs_success \n"
+ ".global __vdso_futex_robust_try_unlock_cs_end \n"
Those .global are fragile: they depend on making sure the compiler does
not emit those symbols more than once per compile unit (due to
optimizations).
I understand that you want to skip the "iteration on a section" within
the kernel fast path, and I agree with that intent, but I think we can
achieve that goal with more robustness by:
- emitting those as triplets within a dedicated section,
- validating that the section only contains a single triplet within the
vdso2c script.
This would fail immediately in the vsdo2c script if the compiler does
not do as expected rather than silently fail to cover part of the
emitted code range.
[...]
+ : [tid] "+a" (tid)
Could use a few comments:
- "tid" sits in eax.
+ : [ptr] "D" (lock),
- "lock" sits in edi/rdi.
+ [pop] "d" (pop),
This constraint puts the unmasked "pop" pointer into edx/rdx.
+ [val] "r" (0)
+ ASM_PAD_CONSTRAINT
The masked "pop" pointer sits in esi/rsi.
[...]
+ * disabled or this is a 32-bit kernel then ZF is authoritive no matter
authoritative
+
+static __always_inline void __user *x86_futex_robust_unlock_get_pop(struct pt_regs *regs)
+{
+ return (void __user *)regs->dx;
When userspace is compat 32-bit, with a 64-bit kernel, are we sure that
the 32 upper bits are cleared ? If not can we rely on
compat_robust_list_clear_pending to ignore those top bits in
put_user(0U, pop) ?
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com