Skip to content

Commit 1501e8d

Browse files
committed
std.Io.Threaded: fix -fsingle-threaded build
1 parent 0349628 commit 1501e8d

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

lib/std/Io/Threaded.zig

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,10 @@ const have_flock_open_flags = @hasField(posix.O, "EXLOCK");
265265
const have_networking = builtin.os.tag != .wasi;
266266
const have_flock = @TypeOf(posix.system.flock) != void;
267267
const have_sendmmsg = builtin.os.tag == .linux;
268+
const have_futex = switch (builtin.cpu.arch) {
269+
.wasm32, .wasm64 => builtin.cpu.has(.wasm, .atomics),
270+
else => true,
271+
};
268272

269273
const openat_sym = if (posix.lfs64_abi) posix.system.openat64 else posix.system.openat;
270274
const fstat_sym = if (posix.lfs64_abi) posix.system.fstat64 else posix.system.fstat;
@@ -731,6 +735,7 @@ fn checkCancel(t: *Threaded) error{Canceled}!void {
731735
}
732736

733737
fn mutexLock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) Io.Cancelable!void {
738+
if (builtin.single_threaded) unreachable; // Interface should have prevented this.
734739
const t: *Threaded = @ptrCast(@alignCast(userdata));
735740
if (prev_state == .contended) {
736741
try futexWait(t, @ptrCast(&mutex.state), @intFromEnum(Io.Mutex.State.contended));
@@ -741,6 +746,7 @@ fn mutexLock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex
741746
}
742747

743748
fn mutexLockUncancelable(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void {
749+
if (builtin.single_threaded) unreachable; // Interface should have prevented this.
744750
_ = userdata;
745751
if (prev_state == .contended) {
746752
futexWaitUncancelable(@ptrCast(&mutex.state), @intFromEnum(Io.Mutex.State.contended));
@@ -751,6 +757,7 @@ fn mutexLockUncancelable(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mute
751757
}
752758

753759
fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void {
760+
if (builtin.single_threaded) unreachable; // Interface should have prevented this.
754761
_ = userdata;
755762
_ = prev_state;
756763
if (@atomicRmw(Io.Mutex.State, &mutex.state, .Xchg, .unlocked, .release) == .contended) {
@@ -759,6 +766,7 @@ fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mut
759766
}
760767

761768
fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) void {
769+
if (builtin.single_threaded) unreachable; // Deadlock.
762770
const t: *Threaded = @ptrCast(@alignCast(userdata));
763771
const t_io = t.io();
764772
comptime assert(@TypeOf(cond.state) == u64);
@@ -789,6 +797,7 @@ fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex:
789797
}
790798

791799
fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) Io.Cancelable!void {
800+
if (builtin.single_threaded) unreachable; // Deadlock.
792801
const t: *Threaded = @ptrCast(@alignCast(userdata));
793802
comptime assert(@TypeOf(cond.state) == u64);
794803
const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state);
@@ -833,6 +842,7 @@ fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) I
833842
}
834843

835844
fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition.Wake) void {
845+
if (builtin.single_threaded) unreachable; // Nothing to wake up.
836846
const t: *Threaded = @ptrCast(@alignCast(userdata));
837847
_ = t;
838848
comptime assert(@TypeOf(cond.state) == u64);
@@ -4007,6 +4017,32 @@ fn futexWait(t: *Threaded, ptr: *const std.atomic.Value(u32), expect: u32) Io.Ca
40074017
return;
40084018
}
40094019

4020+
if (builtin.cpu.arch.isWasm()) {
4021+
comptime assert(builtin.cpu.has(.wasm, .atomics));
4022+
try t.checkCancel();
4023+
const timeout: i64 = -1;
4024+
const signed_expect: i32 = @bitCast(expect);
4025+
const result = asm volatile (
4026+
\\local.get %[ptr]
4027+
\\local.get %[expected]
4028+
\\local.get %[timeout]
4029+
\\memory.atomic.wait32 0
4030+
\\local.set %[ret]
4031+
: [ret] "=r" (-> u32),
4032+
: [ptr] "r" (&ptr.raw),
4033+
[expected] "r" (signed_expect),
4034+
[timeout] "r" (timeout),
4035+
);
4036+
const is_debug = builtin.mode == .Debug;
4037+
switch (result) {
4038+
0 => {}, // ok
4039+
1 => {}, // expected != loaded
4040+
2 => assert(!is_debug), // timeout
4041+
else => assert(!is_debug),
4042+
}
4043+
return;
4044+
}
4045+
40104046
@compileError("TODO");
40114047
}
40124048

@@ -4054,6 +4090,31 @@ pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) voi
40544090
return;
40554091
}
40564092

4093+
if (builtin.cpu.arch.isWasm()) {
4094+
comptime assert(builtin.cpu.has(.wasm, .atomics));
4095+
const timeout: i64 = -1;
4096+
const signed_expect: i32 = @bitCast(expect);
4097+
const result = asm volatile (
4098+
\\local.get %[ptr]
4099+
\\local.get %[expected]
4100+
\\local.get %[timeout]
4101+
\\memory.atomic.wait32 0
4102+
\\local.set %[ret]
4103+
: [ret] "=r" (-> u32),
4104+
: [ptr] "r" (&ptr.raw),
4105+
[expected] "r" (signed_expect),
4106+
[timeout] "r" (timeout),
4107+
);
4108+
const is_debug = builtin.mode == .Debug;
4109+
switch (result) {
4110+
0 => {}, // ok
4111+
1 => {}, // expected != loaded
4112+
2 => assert(!is_debug), // timeout
4113+
else => assert(!is_debug),
4114+
}
4115+
return;
4116+
}
4117+
40574118
@compileError("TODO");
40584119
}
40594120

@@ -4119,6 +4180,22 @@ pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void {
41194180
}
41204181
}
41214182

4183+
if (builtin.cpu.arch.isWasm()) {
4184+
comptime assert(builtin.cpu.has(.wasm, .atomics));
4185+
assert(max_waiters != 0);
4186+
const woken_count = asm volatile (
4187+
\\local.get %[ptr]
4188+
\\local.get %[waiters]
4189+
\\memory.atomic.notify 0
4190+
\\local.set %[ret]
4191+
: [ret] "=r" (-> u32),
4192+
: [ptr] "r" (&ptr.raw),
4193+
[waiters] "r" (max_waiters),
4194+
);
4195+
_ = woken_count; // can be 0 when linker flag 'shared-memory' is not enabled
4196+
return;
4197+
}
4198+
41224199
@compileError("TODO");
41234200
}
41244201

0 commit comments

Comments
 (0)