diff options
| author | Luuk de Gram <luuk@degram.dev> | 2023-06-19 12:10:32 +0200 |
|---|---|---|
| committer | Luuk de Gram <luuk@degram.dev> | 2023-06-26 20:00:57 +0200 |
| commit | ea0d4c8377aeabe1ef588e82cbdd9aa729adbce0 (patch) | |
| tree | 3da8d930fcd180b72053ea25cfa081d52084d8ac /lib/std/Thread | |
| parent | 062eb6f3c0027e8a371e6865963645b70e49b84e (diff) | |
| download | zig-ea0d4c8377aeabe1ef588e82cbdd9aa729adbce0.tar.gz zig-ea0d4c8377aeabe1ef588e82cbdd9aa729adbce0.zip | |
std: implement `Futex` for WebAssembly
Implements std's `Futex` for the WebAssembly target using Wasm's
`atomics` instruction set. When the `atomics` cpu feature is disabled
we emit a compile-error.
Diffstat (limited to 'lib/std/Thread')
| -rw-r--r-- | lib/std/Thread/Futex.zig | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/lib/std/Thread/Futex.zig b/lib/std/Thread/Futex.zig index 768442539b..2fe4120f68 100644 --- a/lib/std/Thread/Futex.zig +++ b/lib/std/Thread/Futex.zig @@ -73,6 +73,8 @@ else if (builtin.os.tag == .openbsd) OpenbsdImpl else if (builtin.os.tag == .dragonfly) DragonflyImpl +else if (builtin.target.isWasm()) + WasmImpl else if (std.Thread.use_pthreads) PosixImpl else @@ -446,6 +448,49 @@ const DragonflyImpl = struct { } }; +const WasmImpl = struct { + fn wait(ptr: *const Atomic(u32), expect: u32, timeout: ?u64) error{Timeout}!void { + if (!comptime std.Target.wasm.featureSetHas(builtin.target.cpu.features, .atomics)) { + @compileError("WASI target missing cpu feature 'atomics'"); + } + const to: i64 = if (timeout) |to| @intCast(i64, to) else -1; + const result = asm ( + \\local.get %[ptr] + \\local.get %[expected] + \\local.get %[timeout] + \\memory.atomic.wait32 0 + \\local.set %[ret] + : [ret] "=r" (-> u32), + : [ptr] "r" (&ptr.value), + [expected] "r" (@bitCast(i32, expect)), + [timeout] "r" (to), + ); + switch (result) { + 0 => {}, // ok + 1 => {}, // expected =! loaded + 2 => return error.Timeout, + else => unreachable, + } + } + + fn wake(ptr: *const Atomic(u32), max_waiters: u32) void { + if (!comptime std.Target.wasm.featureSetHas(builtin.target.cpu.features, .atomics)) { + @compileError("WASI target missing cpu feature 'atomics'"); + } + assert(max_waiters != 0); + const woken_count = asm ( + \\local.get %[ptr] + \\local.get %[waiters] + \\memory.atomic.notify 0 + \\local.set %[ret] + : [ret] "=r" (-> u32), + : [ptr] "r" (&ptr.value), + [waiters] "r" (max_waiters), + ); + _ = woken_count; // can be 0 when linker flag 'shared-memory' is not enabled + } +}; + /// Modified version of linux's futex and Go's sema to implement userspace wait queues with pthread: /// https://code.woboq.org/linux/linux/kernel/futex.c.html /// https://go.dev/src/runtime/sema.go |
