aboutsummaryrefslogtreecommitdiff
path: root/lib/std/Thread
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2023-06-19 12:10:32 +0200
committerLuuk de Gram <luuk@degram.dev>2023-06-26 20:00:57 +0200
commitea0d4c8377aeabe1ef588e82cbdd9aa729adbce0 (patch)
tree3da8d930fcd180b72053ea25cfa081d52084d8ac /lib/std/Thread
parent062eb6f3c0027e8a371e6865963645b70e49b84e (diff)
downloadzig-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.zig45
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