From 282d0be41047fec9e11d418a59a4c4faccf4bfc5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 23 Jul 2026 11:35:48 +0200 Subject: [PATCH] um: nommu: add SMP futex operations The asm-generic futex implementation only supports UP operations, and the normal (MMU) implementation from uaccess.c isn't built nor would it work. Since NOMMU shares address space anyway, it's all trivial and we can just make a trivial implementation. Link: https://patch.msgid.link/20260723113633.d8373755f77c.I0a83e5ca6be6c95a81d4b2ec69677bbea5889d7d@changeid Signed-off-by: Johannes Berg --- arch/um/include/asm/futex.h | 51 ++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/arch/um/include/asm/futex.h b/arch/um/include/asm/futex.h index 785fd6649aa2..07ab81f09281 100644 --- a/arch/um/include/asm/futex.h +++ b/arch/um/include/asm/futex.h @@ -12,7 +12,56 @@ int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr) int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, u32 newval); #else +#include #include -#endif + +#ifdef CONFIG_SMP +static inline int +arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr) +{ + u32 oldval, newval; + u32 *p = (u32 __force *)uaddr; + + do { + oldval = READ_ONCE(*p); + + switch (op) { + case FUTEX_OP_SET: + newval = oparg; + break; + case FUTEX_OP_ADD: + newval = oldval + oparg; + break; + case FUTEX_OP_OR: + newval = oldval | oparg; + break; + case FUTEX_OP_ANDN: + newval = oldval & ~oparg; + break; + case FUTEX_OP_XOR: + newval = oldval ^ oparg; + break; + default: + return -ENOSYS; + } + } while (!try_cmpxchg(p, &oldval, newval)); + + *oval = oldval; + return 0; +} + +static inline int +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + u32 oldval, u32 newval) +{ + u32 *p = (u32 __force *)uaddr; + + *uval = cmpxchg(p, oldval, newval); + + return 0; +} +#endif /* CONFIG_SMP */ + +#endif /* CONFIG_MMU */ #endif