Commit ea0d4c8377
Changed files (1)
lib
std
Thread
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