Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

futex: Flag conversion

Futex has 3 sets of flags:

- legacy futex op bits
- futex2 flags
- internal flags

Add a few helpers to convert from the API flags into the internal
flags.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: André Almeida <andrealmeid@igalia.com>
Link: https://lore.kernel.org/r/20230921105247.722140574@noisy.programming.kicks-ass.net

+71 -20
+60 -3
kernel/futex/futex.h
··· 5 5 #include <linux/futex.h> 6 6 #include <linux/rtmutex.h> 7 7 #include <linux/sched/wake_q.h> 8 + #include <linux/compat.h> 8 9 9 10 #ifdef CONFIG_PREEMPT_RT 10 11 #include <linux/rcuwait.h> ··· 17 16 * Futex flags used to encode options to functions and preserve them across 18 17 * restarts. 19 18 */ 19 + #define FLAGS_SIZE_8 0x00 20 + #define FLAGS_SIZE_16 0x01 21 + #define FLAGS_SIZE_32 0x02 22 + #define FLAGS_SIZE_64 0x03 23 + 24 + #define FLAGS_SIZE_MASK 0x03 25 + 20 26 #ifdef CONFIG_MMU 21 - # define FLAGS_SHARED 0x01 27 + # define FLAGS_SHARED 0x10 22 28 #else 23 29 /* 24 30 * NOMMU does not have per process address space. Let the compiler optimize ··· 33 25 */ 34 26 # define FLAGS_SHARED 0x00 35 27 #endif 36 - #define FLAGS_CLOCKRT 0x02 37 - #define FLAGS_HAS_TIMEOUT 0x04 28 + #define FLAGS_CLOCKRT 0x20 29 + #define FLAGS_HAS_TIMEOUT 0x40 30 + #define FLAGS_NUMA 0x80 31 + 32 + /* FUTEX_ to FLAGS_ */ 33 + static inline unsigned int futex_to_flags(unsigned int op) 34 + { 35 + unsigned int flags = FLAGS_SIZE_32; 36 + 37 + if (!(op & FUTEX_PRIVATE_FLAG)) 38 + flags |= FLAGS_SHARED; 39 + 40 + if (op & FUTEX_CLOCK_REALTIME) 41 + flags |= FLAGS_CLOCKRT; 42 + 43 + return flags; 44 + } 45 + 46 + /* FUTEX2_ to FLAGS_ */ 47 + static inline unsigned int futex2_to_flags(unsigned int flags2) 48 + { 49 + unsigned int flags = flags2 & FUTEX2_SIZE_MASK; 50 + 51 + if (!(flags2 & FUTEX2_PRIVATE)) 52 + flags |= FLAGS_SHARED; 53 + 54 + if (flags2 & FUTEX2_NUMA) 55 + flags |= FLAGS_NUMA; 56 + 57 + return flags; 58 + } 59 + 60 + static inline unsigned int futex_size(unsigned int flags) 61 + { 62 + return 1 << (flags & FLAGS_SIZE_MASK); 63 + } 64 + 65 + static inline bool futex_flags_valid(unsigned int flags) 66 + { 67 + /* Only 64bit futexes for 64bit code */ 68 + if (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall()) { 69 + if ((flags & FLAGS_SIZE_MASK) == FLAGS_SIZE_64) 70 + return false; 71 + } 72 + 73 + /* Only 32bit futexes are implemented -- for now */ 74 + if ((flags & FLAGS_SIZE_MASK) != FLAGS_SIZE_32) 75 + return false; 76 + 77 + return true; 78 + } 38 79 39 80 #ifdef CONFIG_FAIL_FUTEX 40 81 extern bool should_fail_futex(bool fshared);
+9 -15
kernel/futex/syscalls.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 3 - #include <linux/compat.h> 4 3 #include <linux/syscalls.h> 5 4 #include <linux/time_namespace.h> 6 5 ··· 84 85 long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, 85 86 u32 __user *uaddr2, u32 val2, u32 val3) 86 87 { 88 + unsigned int flags = futex_to_flags(op); 87 89 int cmd = op & FUTEX_CMD_MASK; 88 - unsigned int flags = 0; 89 90 90 - if (!(op & FUTEX_PRIVATE_FLAG)) 91 - flags |= FLAGS_SHARED; 92 - 93 - if (op & FUTEX_CLOCK_REALTIME) { 94 - flags |= FLAGS_CLOCKRT; 95 - if (cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI && 91 + if (flags & FLAGS_CLOCKRT) { 92 + if (cmd != FUTEX_WAIT_BITSET && 93 + cmd != FUTEX_WAIT_REQUEUE_PI && 96 94 cmd != FUTEX_LOCK_PI2) 97 95 return -ENOSYS; 98 96 } ··· 197 201 unsigned int i; 198 202 199 203 for (i = 0; i < nr_futexes; i++) { 204 + unsigned int flags; 205 + 200 206 if (copy_from_user(&aux, &uwaitv[i], sizeof(aux))) 201 207 return -EFAULT; 202 208 203 209 if ((aux.flags & ~FUTEX2_VALID_MASK) || aux.__reserved) 204 210 return -EINVAL; 205 211 206 - if (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall()) { 207 - if ((aux.flags & FUTEX2_SIZE_MASK) == FUTEX2_SIZE_U64) 208 - return -EINVAL; 209 - } 210 - 211 - if ((aux.flags & FUTEX2_SIZE_MASK) != FUTEX2_SIZE_U32) 212 + flags = futex2_to_flags(aux.flags); 213 + if (!futex_flags_valid(flags)) 212 214 return -EINVAL; 213 215 214 - futexv[i].w.flags = aux.flags; 216 + futexv[i].w.flags = flags; 215 217 futexv[i].w.val = aux.val; 216 218 futexv[i].w.uaddr = aux.uaddr; 217 219 futexv[i].q = futex_q_init;
+2 -2
kernel/futex/waitwake.c
··· 419 419 */ 420 420 retry: 421 421 for (i = 0; i < count; i++) { 422 - if ((vs[i].w.flags & FUTEX_PRIVATE_FLAG) && retry) 422 + if (!(vs[i].w.flags & FLAGS_SHARED) && retry) 423 423 continue; 424 424 425 425 ret = get_futex_key(u64_to_user_ptr(vs[i].w.uaddr), 426 - !(vs[i].w.flags & FUTEX_PRIVATE_FLAG), 426 + vs[i].w.flags & FLAGS_SHARED, 427 427 &vs[i].q.key, FUTEX_READ); 428 428 429 429 if (unlikely(ret))