Message ID | 20230714141218.879715585@infradead.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | futex: More Futex2 bits | expand |
On Fri, Jul 14, 2023, at 15:39, Peter Zijlstra wrote: > > +++ b/include/linux/syscalls.h > @@ -563,6 +563,9 @@ asmlinkage long sys_set_robust_list(stru > asmlinkage long sys_futex_waitv(struct futex_waitv *waiters, > unsigned int nr_futexes, unsigned int flags, > struct __kernel_timespec __user *timeout, clockid_t clockid); > + > +asmlinkage long sys_futex_wake(void __user *uaddr, int nr, unsigned > int flags, u64 mask); > + You can't really use 'u64' arguments in portable syscalls, it causes a couple of problems, both with defining the user space wrappers, and with compat mode. Variants that would work include: - using 'unsigned long' instead of 'u64' - passing 'mask' by reference, as in splice() - passing the mask in two u32-bit arguments like in llseek() Not sure if any of the above work for you. Arnd
On Fri, Jul 14, 2023 at 04:26:45PM +0200, Arnd Bergmann wrote: > On Fri, Jul 14, 2023, at 15:39, Peter Zijlstra wrote: > > > > +++ b/include/linux/syscalls.h > > @@ -563,6 +563,9 @@ asmlinkage long sys_set_robust_list(stru > > asmlinkage long sys_futex_waitv(struct futex_waitv *waiters, > > unsigned int nr_futexes, unsigned int flags, > > struct __kernel_timespec __user *timeout, clockid_t clockid); > > + > > +asmlinkage long sys_futex_wake(void __user *uaddr, int nr, unsigned > > int flags, u64 mask); > > + > > You can't really use 'u64' arguments in portable syscalls, it causes > a couple of problems, both with defining the user space wrappers, > and with compat mode. > > Variants that would work include: > > - using 'unsigned long' instead of 'u64' > - passing 'mask' by reference, as in splice() > - passing the mask in two u32-bit arguments like in llseek() > > Not sure if any of the above work for you. Durr, I was hoping they'd use register pairs, but yeah I can see how that would be very hard to do in generic code. Hurmph.. using 2 u32s is unfortunate on 64bit, while unsigned long would limit 64bit futexes to 64bit machines (perhaps not too bad). Using unsigned long would help with the futex_wait() thing as well. I'll ponder things a bit. Obviously I only did build x86_64 ;-)
On Fri, Jul 14, 2023, at 16:47, Peter Zijlstra wrote: > On Fri, Jul 14, 2023 at 04:26:45PM +0200, Arnd Bergmann wrote: >> On Fri, Jul 14, 2023, at 15:39, Peter Zijlstra wrote: >> > >> > +++ b/include/linux/syscalls.h >> > @@ -563,6 +563,9 @@ asmlinkage long sys_set_robust_list(stru >> > asmlinkage long sys_futex_waitv(struct futex_waitv *waiters, >> > unsigned int nr_futexes, unsigned int flags, >> > struct __kernel_timespec __user *timeout, clockid_t clockid); >> > + >> > +asmlinkage long sys_futex_wake(void __user *uaddr, int nr, unsigned >> > int flags, u64 mask); >> > + >> >> You can't really use 'u64' arguments in portable syscalls, it causes >> a couple of problems, both with defining the user space wrappers, >> and with compat mode. >> >> Variants that would work include: >> >> - using 'unsigned long' instead of 'u64' >> - passing 'mask' by reference, as in splice() >> - passing the mask in two u32-bit arguments like in llseek() >> >> Not sure if any of the above work for you. > > Durr, I was hoping they'd use register pairs, but yeah I can see how > that would be very hard to do in generic code. It kind of works to just use register pairs, the actual problem you run into here is that: - depending on the architecture, the register pairs need to be even/odd pairs, so there are two different ways that 32-bit architectures handle it - The compat handler needs to explicitly name the registers that are used, so to make your version above work correctly, we'd need three entry points, for native 64-bit, compat 32-bit odd/even pairs and compat 32-bit even/odd pairs. > Hurmph.. using 2 u32s is unfortunate on 64bit, while unsigned long > would limit 64bit futexes to 64bit machines (perhaps not too bad). > > Using unsigned long would help with the futex_wait() thing as well. > > I'll ponder things a bit. > > Obviously I only did build x86_64 ;-) I suspect that restricting the futexes to native work size is ok since many 32-bit architectures don't have 64-bit atomic instructions anyway (armv6k+ and i586tsc+ being the obvious exceptions), so userspace code that relies on it becomes nonportable. Arnd
--- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -491,3 +491,4 @@ 559 common futex_waitv sys_futex_waitv 560 common set_mempolicy_home_node sys_ni_syscall 561 common cachestat sys_cachestat +562 common futex_wake sys_futex_wake --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -465,3 +465,4 @@ 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat +452 common futex_wake sys_futex_wake --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -909,6 +909,8 @@ __SYSCALL(__NR_futex_waitv, sys_futex_wa __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node) #define __NR_cachestat 451 __SYSCALL(__NR_cachestat, sys_cachestat) +#define __NR_futex_wake 452 +__SYSCALL(__NR_futex_wake, sys_futex_wake) /* * Please add new compat syscalls above this comment and update --- a/arch/ia64/kernel/syscalls/syscall.tbl +++ b/arch/ia64/kernel/syscalls/syscall.tbl @@ -372,3 +372,4 @@ 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat +452 common futex_wake sys_futex_wake --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -451,3 +451,4 @@ 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat +452 common futex_wake sys_futex_wake --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -457,3 +457,4 @@ 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat +452 common futex_wake sys_futex_wake --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -390,3 +390,4 @@ 449 n32 futex_waitv sys_futex_waitv 450 n32 set_mempolicy_home_node sys_set_mempolicy_home_node 451 n32 cachestat sys_cachestat +452 n32 futex_wake sys_futex_wake --- a/arch/mips/kernel/syscalls/syscall_n64.tbl +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl @@ -366,3 +366,4 @@ 449 n64 futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 n64 cachestat sys_cachestat +452 n64 futex_wake sys_futex_wake --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -439,3 +439,4 @@ 449 o32 futex_waitv sys_futex_waitv 450 o32 set_mempolicy_home_node sys_set_mempolicy_home_node 451 o32 cachestat sys_cachestat +452 o32 futex_wake sys_futex_wake --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -450,3 +450,4 @@ 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat +452 common futex_wake sys_futex_wake --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -538,3 +538,4 @@ 449 common futex_waitv sys_futex_waitv 450 nospu set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat +452 common futex_wake sys_futex_wake --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -454,3 +454,4 @@ 449 common futex_waitv sys_futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat sys_cachestat +452 common futex_wake sys_futex_wake sys_futex_wake --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -454,3 +454,4 @@ 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat +452 common futex_wake sys_futex_wake --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -497,3 +497,4 @@ 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat +452 common futex_wake sys_futex_wake --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -456,3 +456,4 @@ 449 i386 futex_waitv sys_futex_waitv 450 i386 set_mempolicy_home_node sys_set_mempolicy_home_node 451 i386 cachestat sys_cachestat +452 i386 futex_wake sys_futex_wake --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -373,6 +373,7 @@ 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat +452 common futex_wake sys_futex_wake # # Due to a historical design error, certain syscalls are numbered differently --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -422,3 +422,4 @@ 449 common futex_waitv sys_futex_waitv 450 common set_mempolicy_home_node sys_set_mempolicy_home_node 451 common cachestat sys_cachestat +452 common futex_wake sys_futex_wake --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -563,6 +563,9 @@ asmlinkage long sys_set_robust_list(stru asmlinkage long sys_futex_waitv(struct futex_waitv *waiters, unsigned int nr_futexes, unsigned int flags, struct __kernel_timespec __user *timeout, clockid_t clockid); + +asmlinkage long sys_futex_wake(void __user *uaddr, int nr, unsigned int flags, u64 mask); + asmlinkage long sys_nanosleep(struct __kernel_timespec __user *rqtp, struct __kernel_timespec __user *rmtp); asmlinkage long sys_nanosleep_time32(struct old_timespec32 __user *rqtp, --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -816,12 +816,13 @@ __SYSCALL(__NR_process_mrelease, sys_pro __SYSCALL(__NR_futex_waitv, sys_futex_waitv) #define __NR_set_mempolicy_home_node 450 __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node) - #define __NR_cachestat 451 __SYSCALL(__NR_cachestat, sys_cachestat) +#define __NR_futex_wake 452 +__SYSCALL(__NR_futex_wake, sys_futex_wake) #undef __NR_syscalls -#define __NR_syscalls 452 +#define __NR_syscalls 453 /* * 32 bit systems traditionally used different --- a/kernel/futex/syscalls.c +++ b/kernel/futex/syscalls.c @@ -309,6 +309,43 @@ SYSCALL_DEFINE5(futex_waitv, struct fute return ret; } +/* + * sys_futex_wake - Wake a number of futexes + * @uaddr: Address of the futex(es) to wake + * @nr: Number of the futexes to wake + * @flags: FUTEX2 flags + * @mask: bitmask + * + * Identical to the traditional FUTEX_WAKE_BITSET op, except it matches futex_waitv() above + * in that it enables u64 futex values and has a new flags set. + * + * NOTE: u64 futexes are not actually supported yet, but both these interfaces + * should allow for this to happen. + */ + +SYSCALL_DEFINE4(futex_wake, + void __user *, uaddr, + int, nr, + unsigned int, flags, + u64, mask) +{ + int bits; + + if (flags & ~FUTEX2_MASK) + return -EINVAL; + + if ((flags & FUTEX2_64) != FUTEX2_32) + return -EINVAL; + + flags = futex2_to_flags(flags); + bits = 8 * futex_size(flags); + + if (bits < 64 && mask >> bits) + return -EINVAL; + + return futex_wake(uaddr, flags, nr, mask); +} + #ifdef CONFIG_COMPAT COMPAT_SYSCALL_DEFINE2(set_robust_list, struct compat_robust_list_head __user *, head, --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -87,6 +87,7 @@ COND_SYSCALL_COMPAT(set_robust_list); COND_SYSCALL(get_robust_list); COND_SYSCALL_COMPAT(get_robust_list); COND_SYSCALL(futex_waitv); +COND_SYSCALL(futex_wake); COND_SYSCALL(kexec_load); COND_SYSCALL_COMPAT(kexec_load); COND_SYSCALL(init_module);
To complement sys_futex_waitv() add sys_futex_wake(). Together they provide the basic Futex2 WAIT/WAKE functionality. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> --- arch/alpha/kernel/syscalls/syscall.tbl | 1 arch/arm/tools/syscall.tbl | 1 arch/arm64/include/asm/unistd32.h | 2 + arch/ia64/kernel/syscalls/syscall.tbl | 1 arch/m68k/kernel/syscalls/syscall.tbl | 1 arch/microblaze/kernel/syscalls/syscall.tbl | 1 arch/mips/kernel/syscalls/syscall_n32.tbl | 1 arch/mips/kernel/syscalls/syscall_n64.tbl | 1 arch/mips/kernel/syscalls/syscall_o32.tbl | 1 arch/parisc/kernel/syscalls/syscall.tbl | 1 arch/powerpc/kernel/syscalls/syscall.tbl | 1 arch/s390/kernel/syscalls/syscall.tbl | 1 arch/sh/kernel/syscalls/syscall.tbl | 1 arch/sparc/kernel/syscalls/syscall.tbl | 1 arch/x86/entry/syscalls/syscall_32.tbl | 1 arch/x86/entry/syscalls/syscall_64.tbl | 1 arch/xtensa/kernel/syscalls/syscall.tbl | 1 include/linux/syscalls.h | 3 ++ include/uapi/asm-generic/unistd.h | 5 ++- kernel/futex/syscalls.c | 37 ++++++++++++++++++++++++++++ kernel/sys_ni.c | 1 21 files changed, 62 insertions(+), 2 deletions(-)