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");...@@ -265,6 +265,10 @@ const have_flock_open_flags = @hasField(posix.O, "EXLOCK");
265const have_networking = builtin.os.tag != .wasi;265const have_networking = builtin.os.tag != .wasi;
266const have_flock = @TypeOf(posix.system.flock) != void;266const have_flock = @TypeOf(posix.system.flock) != void;
267const have_sendmmsg = builtin.os.tag == .linux;267const 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
269const openat_sym = if (posix.lfs64_abi) posix.system.openat64 else posix.system.openat;273const openat_sym = if (posix.lfs64_abi) posix.system.openat64 else posix.system.openat;
270const fstat_sym = if (posix.lfs64_abi) posix.system.fstat64 else posix.system.fstat;274const fstat_sym = if (posix.lfs64_abi) posix.system.fstat64 else posix.system.fstat;
...@@ -731,6 +735,7 @@ fn checkCancel(t: *Threaded) error{Canceled}!void {...@@ -731,6 +735,7 @@ fn checkCancel(t: *Threaded) error{Canceled}!void {
731}735}
732736
733fn mutexLock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) Io.Cancelable!void {737fn 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.
734 const t: *Threaded = @ptrCast(@alignCast(userdata));739 const t: *Threaded = @ptrCast(@alignCast(userdata));
735 if (prev_state == .contended) {740 if (prev_state == .contended) {
736 try futexWait(t, @ptrCast(&mutex.state), @intFromEnum(Io.Mutex.State.contended));741 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...@@ -741,6 +746,7 @@ fn mutexLock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex
741}746}
742747
743fn mutexLockUncancelable(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void {748fn mutexLockUncancelable(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void {
749 if (builtin.single_threaded) unreachable; // Interface should have prevented this.
744 _ = userdata;750 _ = userdata;
745 if (prev_state == .contended) {751 if (prev_state == .contended) {
746 futexWaitUncancelable(@ptrCast(&mutex.state), @intFromEnum(Io.Mutex.State.contended));752 futexWaitUncancelable(@ptrCast(&mutex.state), @intFromEnum(Io.Mutex.State.contended));
...@@ -751,6 +757,7 @@ fn mutexLockUncancelable(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mute...@@ -751,6 +757,7 @@ fn mutexLockUncancelable(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mute
751}757}
752758
753fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void {759fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) void {
760 if (builtin.single_threaded) unreachable; // Interface should have prevented this.
754 _ = userdata;761 _ = userdata;
755 _ = prev_state;762 _ = prev_state;
756 if (@atomicRmw(Io.Mutex.State, &mutex.state, .Xchg, .unlocked, .release) == .contended) {763 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...@@ -759,6 +766,7 @@ fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mut
759}766}
760767
761fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) void {768fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) void {
769 if (builtin.single_threaded) unreachable; // Deadlock.
762 const t: *Threaded = @ptrCast(@alignCast(userdata));770 const t: *Threaded = @ptrCast(@alignCast(userdata));
763 const t_io = t.io();771 const t_io = t.io();
764 comptime assert(@TypeOf(cond.state) == u64);772 comptime assert(@TypeOf(cond.state) == u64);
...@@ -789,6 +797,7 @@ fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex:...@@ -789,6 +797,7 @@ fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex:
789}797}
790798
791fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) Io.Cancelable!void {799fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) Io.Cancelable!void {
800 if (builtin.single_threaded) unreachable; // Deadlock.
792 const t: *Threaded = @ptrCast(@alignCast(userdata));801 const t: *Threaded = @ptrCast(@alignCast(userdata));
793 comptime assert(@TypeOf(cond.state) == u64);802 comptime assert(@TypeOf(cond.state) == u64);
794 const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state);803 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...@@ -833,6 +842,7 @@ fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) I
833}842}
834843
835fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition.Wake) void {844fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition.Wake) void {
845 if (builtin.single_threaded) unreachable; // Nothing to wake up.
836 const t: *Threaded = @ptrCast(@alignCast(userdata));846 const t: *Threaded = @ptrCast(@alignCast(userdata));
837 _ = t;847 _ = t;
838 comptime assert(@TypeOf(cond.state) == u64);848 comptime assert(@TypeOf(cond.state) == u64);
...@@ -4007,6 +4017,32 @@ fn futexWait(t: *Threaded, ptr: *const std.atomic.Value(u32), expect: u32) Io.Ca...@@ -4007,6 +4017,32 @@ fn futexWait(t: *Threaded, ptr: *const std.atomic.Value(u32), expect: u32) Io.Ca
4007 return;4017 return;
4008 }4018 }
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
4010 @compileError("TODO");4046 @compileError("TODO");
4011}4047}
40124048
...@@ -4054,6 +4090,31 @@ pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) voi...@@ -4054,6 +4090,31 @@ pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) voi
4054 return;4090 return;
4055 }4091 }
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
4057 @compileError("TODO");4118 @compileError("TODO");
4058}4119}
40594120
...@@ -4119,6 +4180,22 @@ pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void {...@@ -4119,6 +4180,22 @@ pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void {
4119 }4180 }
4120 }4181 }
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
4122 @compileError("TODO");4199 @compileError("TODO");
4123}4200}
41244201