authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-17 01:14:16-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:50-07:00
log752d38612f97d7c9aa203615bdde772a71b1330f
tree82327354d6f301d4162200bda6944ed254d7f386
parent81e7e9fdbbb822c413649479dd572ffcd244543a

std.Io.Threaded: fix -fsingle-threaded build


1 files changed, 77 insertions(+), 0 deletions(-)

lib/std/Io/Threaded.zig+77
......@@ -265,6 +265,10 @@ const have_flock_open_flags = @hasField(posix.O, "EXLOCK");
265265const have_networking = builtin.os.tag != .wasi;
266266const have_flock = @TypeOf(posix.system.flock) != void;
267267const have_sendmmsg = builtin.os.tag == .linux;
268const have_futex = switch (builtin.cpu.arch) {
269 .wasm32, .wasm64 => builtin.cpu.has(.wasm, .atomics),
270 else => true,
271};
268272
269273const openat_sym = if (posix.lfs64_abi) posix.system.openat64 else posix.system.openat;
270274const 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
733737fn 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
743748fn 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
753759fn 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
761768fn 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
791799fn 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
835844fn 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