From 8c1ab65c0f548d20b7f177bdb736daaf603340e1 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 15:54:38 +0200 Subject: Adding upstream version 0.0~git20221206.8b7148f. Signed-off-by: Daniel Baumann --- libc-top-half/musl/src/thread/__wait.c | 55 ++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 libc-top-half/musl/src/thread/__wait.c (limited to 'libc-top-half/musl/src/thread/__wait.c') diff --git a/libc-top-half/musl/src/thread/__wait.c b/libc-top-half/musl/src/thread/__wait.c new file mode 100644 index 0000000..c0e4aac --- /dev/null +++ b/libc-top-half/musl/src/thread/__wait.c @@ -0,0 +1,55 @@ +#include "pthread_impl.h" +#ifndef __wasilibc_unmodified_upstream +#include "assert.h" +#endif + +#ifndef __wasilibc_unmodified_upstream +// Use WebAssembly's `wait` instruction to implement a futex. Note that `op` is +// unused but retained as a parameter to match the original signature of the +// syscall and that, for `max_wait_ns`, -1 (or any negative number) means wait +// indefinitely. +// +// Adapted from Emscripten: see +// https://github.com/emscripten-core/emscripten/blob/058a9fff/system/lib/pthread/emscripten_futex_wait.c#L111-L150. +int __wasilibc_futex_wait(volatile void *addr, int op, int val, int64_t max_wait_ns) +{ + if ((((intptr_t)addr) & 3) != 0) { + return -EINVAL; + } + + int ret = __builtin_wasm_memory_atomic_wait32((int *)addr, val, max_wait_ns); + + // memory.atomic.wait32 returns: + // 0 => "ok", woken by another agent. + // 1 => "not-equal", loaded value != expected value + // 2 => "timed-out", the timeout expired + if (ret == 1) { + return -EWOULDBLOCK; + } + if (ret == 2) { + return -ETIMEDOUT; + } + assert(ret == 0); + return 0; +} +#endif + +void __wait(volatile int *addr, volatile int *waiters, int val, int priv) +{ + int spins=100; + if (priv) priv = FUTEX_PRIVATE; + while (spins-- && (!waiters || !*waiters)) { + if (*addr==val) a_spin(); + else return; + } + if (waiters) a_inc(waiters); + while (*addr==val) { +#ifdef __wasilibc_unmodified_upstream + __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS + || __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0); +#else + __wasilibc_futex_wait(addr, FUTEX_WAIT, val, 0); +#endif + } + if (waiters) a_dec(waiters); +} -- cgit v1.2.3