diff --git a/README.adoc b/README.adoc index d3c750c..daaab1d 100644 --- a/README.adoc +++ b/README.adoc @@ -15472,6 +15472,43 @@ Questions about the C inline assembly examples: * x86_64: https://stackoverflow.com/questions/9506353/how-to-invoke-a-system-call-via-sysenter-in-inline-assembly/54956854#54956854 * ARM: https://stackoverflow.com/questions/21729497/doing-a-syscall-without-libc-using-arm-inline-assembly +==== futex system call + +This is how threads either: + +* request the kernel to sleep until they are woken up by other threads +* request the kernel to wake up other threads that are waiting on a given futex + +This syscall is rarely used on its own, and there isn't even a glibc wrapper for it: you almost always just want to use the <> or <> wrappers which use it for you to <>. + +Futexes are bit complicated, because in order to achieve their efficiency, basically nothing is guaranteed: the wait might not wait, and the wakes might not wake. So you are just basically forced to use atomic operations on the futex memory address in order to be sure of anything. + +Minimal examples: + +* link:lkmc/futex.h[]: our futex wrapper +* link:userland/linux/futex.c[]: minimal example, the main thread: +** spawns a child +** the child waits on a futex +** the main thread sleeps for one second +** the main thread wakes up the child +** the child returns ++ +So what you see is: ++ +.... +main start +child start +[wait 1s] +main after sleep +child end +.... + +===== Userland mutex implementation + +The best article to understand spinlocks is: https://eli.thegreenplace.net/2018/basics-of-futexes/ + +The example in `man futex` is also a must. + === Linux calling conventions A summary of results is shown at: xref:table-linux-calling-conventions[xrefstyle=full]. @@ -18502,7 +18539,7 @@ The following Raspberry Pi bibliography helped us get this sample up and running * https://github.com/LdB-ECM/Raspberry-Pi/blob/3b628a2c113b3997ffdb408db03093b2953e4961/Multicore/SmartStart64.S * https://github.com/LdB-ECM/Raspberry-Pi/blob/3b628a2c113b3997ffdb408db03093b2953e4961/Multicore/SmartStart32.S -The best article to understand spinlocks is: https://eli.thegreenplace.net/2018/basics-of-futexes/ +For how userland spinlocks and mutexes are implemented see <>. ====== ARM YIELD instruction diff --git a/lkmc/futex.h b/lkmc/futex.h new file mode 100644 index 0000000..880238b --- /dev/null +++ b/lkmc/futex.h @@ -0,0 +1,13 @@ +#ifndef LKMC_FUTEX_H +#define LKMC_FUTEX_H + +static int +lkmc_futex(int *uaddr, int futex_op, int val, + const struct timespec *timeout, int *uaddr2, int val3) +{ + (void)uaddr2; + return syscall(SYS_futex, uaddr, futex_op, val, + timeout, uaddr, val3); +} + +#endif diff --git a/path_properties.py b/path_properties.py index 890c0f3..93f7678 100644 --- a/path_properties.py +++ b/path_properties.py @@ -673,6 +673,10 @@ path_properties_tuples = ( gnu_extension_properties, { 'ctrl_alt_del.c': {'requires_sudo': True}, + 'futex.c': { + 'more_than_1s': True, + 'test_run_args': {'cpus': 2}, + }, 'init_env_poweroff.c': {'requires_sudo': True}, 'mmap_anonymous_touch.c': { # https://github.com/cirosantilli/linux-kernel-module-cheat/issues/103 diff --git a/userland/linux/futex.c b/userland/linux/futex.c new file mode 100644 index 0000000..00c2cbd --- /dev/null +++ b/userland/linux/futex.c @@ -0,0 +1,40 @@ +/* https://cirosantilli.com/linux-kernel-module-cheat#futex-system-call */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#include + +static int futex1, futex2; + +void* main_thread(void *arg) { + (void)arg; + puts("child start"); + lkmc_futex(&futex1, FUTEX_WAKE, 1, NULL, NULL, 0); + lkmc_futex(&futex2, FUTEX_WAIT, 0, NULL, NULL, 0); + puts("child end"); + return NULL; +} + +int main(void) { + pthread_t thread; + + puts("main start"); + assert(!pthread_create( + &thread, + NULL, + main_thread, + NULL + )); + lkmc_futex(&futex1, FUTEX_WAIT, 0, NULL, NULL, 0); + sleep(1); + puts("main after sleep"); + lkmc_futex(&futex2, FUTEX_WAKE, 1, NULL, NULL, 0); + assert(!pthread_join(thread, NULL)); +}