Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
futex2: Implement wait and wake functions
Create a new set of futex syscalls known as futex2. This new interface is aimed to expand it with new functionalities without modifying the current complex interface. Implement wait and wake functions with support for 32 sized futexes: - futex_wait(void *uaddr, unsigned int val, unsigned int flags, struct timespec *timo) The user thread is put to sleep, waiting for a futex_wake() at uaddr, if the value at *uaddr is the same as val (otherwise, the syscall returns immediately with -EAGAIN). timo is an optional timeout value for the operation. Return 0 on success, error code otherwise. - futex_wake(void *uaddr, unsigned long nr_wake, unsigned int flags) Wake `nr_wake` threads waiting at uaddr. Return the number of woken threads on success, error code otherwise. ** The `flag` argument The flag is used to specify the size of the futex word (FUTEX_[8, 16, 32, 64]). It's mandatory to define one. By default, the timeout uses a monotonic clock, but can be used as a realtime one by using the FUTEX_REALTIME_CLOCK flag. By default, futexes are of the private type, that means that this user address will be accessed by threads that shares the same memory region. This allows for some internal optimizations, so they are faster. However, if the address needs to be shared with different processes (like using `mmap()` or `shm()`), they need to be defined as shared and the flag FUTEX_SHARED_FLAG is used to set that. By default, the operation has no NUMA-awareness, meaning that the user can't choose the memory node where the kernel side futex data will be stored. The user can choose the node where it wants to operate by setting the FUTEX_NUMA_FLAG and using the following structure (where X can be 8, 16, or 32, 64): struct futexX_numa { __uX value; __sX hint; }; This structure should be passed at the `void *uaddr` of futex functions. The address of the structure will be used to be waited/waken on, and the `value` will be compared to `val` as usual. The `hint` member is used to defined which node the futex will use. When waiting, the futex will be registered on a kernel-side table stored on that node; when waking, the futex will be searched for on that given table. That means that there's no redundancy between tables, and the wrong `hint` value will led to undesired behavior. Userspace is responsible for dealing with node migrations issues that may occur. `hint` can range from [0, MAX_NUMA_NODES], for specifying a node, or -1, to use the same node the current process is using. When not using FUTEX_NUMA_FLAG on a NUMA system, the futex will be stored on a global table on some node, defined at compilation time. ** The `timo` argument As per the Y2038 work done in the kernel, new interfaces shouldn't add timeout options known to be buggy. Given that, `timo` should be a 64bit timeout at all platforms, using an absolute timeout value. Signed-off-by: André Almeida <andrealmeid@collabora.com>
- Loading branch information
1 parent
b0a3be5
commit 60e07a8
Showing
11 changed files
with
139 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
/* | ||
* futex2 system call interface by André Almeida <andrealmeid@collabora.com> | ||
* | ||
* Copyright 2021 Collabora Ltd. | ||
*/ | ||
|
||
#include <linux/syscalls.h> | ||
|
||
#include <asm/futex.h> | ||
|
||
/* | ||
* Set of flags that futex2 operates. If we got something that is not in this | ||
* set, it can be a unsupported futex1 operation like BITSET or PI, so we | ||
* refuse to accept | ||
*/ | ||
#define FUTEX2_MASK (FUTEX_SIZE_MASK | FUTEX_SHARED_FLAG | FUTEX_CLOCK_REALTIME) | ||
|
||
static long ksys_futex_wait(void __user *uaddr, u64 val, unsigned int flags, | ||
struct __kernel_timespec __user *timo) | ||
{ | ||
unsigned int size = flags & FUTEX_SIZE_MASK, futex_flags = 0; | ||
ktime_t *kt = NULL, time; | ||
struct timespec64 ts; | ||
|
||
if (flags & ~FUTEX2_MASK) | ||
return -EINVAL; | ||
|
||
if (flags & FUTEX_SHARED_FLAG) | ||
futex_flags |= FLAGS_SHARED; | ||
|
||
if (flags & FUTEX_CLOCK_REALTIME) | ||
futex_flags |= FLAGS_CLOCKRT; | ||
|
||
if (size != FUTEX_32) | ||
return -EINVAL; | ||
|
||
if (timo) { | ||
if (get_timespec64(&ts, timo)) | ||
return -EFAULT; | ||
|
||
if (!timespec64_valid(&ts)) | ||
return -EINVAL; | ||
|
||
time = timespec64_to_ktime(ts); | ||
kt = &time; | ||
} | ||
|
||
return futex_wait(uaddr, futex_flags, val, kt, FUTEX_BITSET_MATCH_ANY); | ||
} | ||
|
||
SYSCALL_DEFINE4(futex_wait, void __user *, uaddr, u64, val, unsigned int, flags, | ||
struct __kernel_timespec __user *, timo) | ||
{ | ||
return ksys_futex_wait(uaddr, val, flags, timo); | ||
} | ||
|
||
#ifdef CONFIG_COMPAT | ||
COMPAT_SYSCALL_DEFINE4(compat_futex_wait, void __user *, uaddr, compat_u64, val, | ||
unsigned int, flags, | ||
struct __kernel_timespec __user *, timo) | ||
{ | ||
return ksys_futex_wait(uaddr, val, flags, timo); | ||
} | ||
#endif | ||
|
||
SYSCALL_DEFINE3(futex_wake, void __user *, uaddr, unsigned int, nr_wake, | ||
unsigned int, flags) | ||
{ | ||
unsigned int size = flags & FUTEX_SIZE_MASK, futex_flags = 0; | ||
|
||
if (flags & ~FUTEX2_MASK) | ||
return -EINVAL; | ||
|
||
if (flags & FUTEX_SHARED_FLAG) | ||
futex_flags |= FLAGS_SHARED; | ||
|
||
if (size != FUTEX_32) | ||
return -EINVAL; | ||
|
||
return futex_wake(uaddr, futex_flags, nr_wake, FUTEX_BITSET_MATCH_ANY); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters