authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-21 07:24:47-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:51-07:00
log0107e584ef4c8071b9ab71f20aae83a5cfb91921
tree5f3011d6e191b3bcb622cb5f9e941c345a805758
parentd257b1337a1b0cbe5b2694518017216aa1d2ef1a

std.Io.Threaded: implement Windows futex functions


1 files changed, 32 insertions(+), 34 deletions(-)

lib/std/Io/Threaded.zig+32-34
...@@ -4880,10 +4880,7 @@ fn futexWait(t: *Threaded, ptr: *const std.atomic.Value(u32), expect: u32) Io.Ca...@@ -4880,10 +4880,7 @@ fn futexWait(t: *Threaded, ptr: *const std.atomic.Value(u32), expect: u32) Io.Ca
4880 .FAULT => unreachable, // ptr was invalid4880 .FAULT => unreachable, // ptr was invalid
4881 else => unreachable,4881 else => unreachable,
4882 };4882 };
4883 return;4883 } else if (native_os.isDarwin()) {
4884 }
4885
4886 if (native_os.isDarwin()) {
4887 const c = std.c;4884 const c = std.c;
4888 const flags: c.UL = .{4885 const flags: c.UL = .{
4889 .op = .COMPARE_AND_WAIT,4886 .op = .COMPARE_AND_WAIT,
...@@ -4907,10 +4904,7 @@ fn futexWait(t: *Threaded, ptr: *const std.atomic.Value(u32), expect: u32) Io.Ca...@@ -4907,10 +4904,7 @@ fn futexWait(t: *Threaded, ptr: *const std.atomic.Value(u32), expect: u32) Io.Ca
4907 .TIMEDOUT => unreachable,4904 .TIMEDOUT => unreachable,
4908 else => unreachable,4905 else => unreachable,
4909 };4906 };
4910 return;4907 } else if (builtin.cpu.arch.isWasm()) {
4911 }
4912
4913 if (builtin.cpu.arch.isWasm()) {
4914 comptime assert(builtin.cpu.has(.wasm, .atomics));4908 comptime assert(builtin.cpu.has(.wasm, .atomics));
4915 try t.checkCancel();4909 try t.checkCancel();
4916 const timeout: i64 = -1;4910 const timeout: i64 = -1;
...@@ -4933,10 +4927,16 @@ fn futexWait(t: *Threaded, ptr: *const std.atomic.Value(u32), expect: u32) Io.Ca...@@ -4933,10 +4927,16 @@ fn futexWait(t: *Threaded, ptr: *const std.atomic.Value(u32), expect: u32) Io.Ca
4933 2 => assert(!is_debug), // timeout4927 2 => assert(!is_debug), // timeout
4934 else => assert(!is_debug),4928 else => assert(!is_debug),
4935 }4929 }
4936 return;4930 } else if (is_windows) {
4931 try t.checkCancel();
4932 switch (windows.ntdll.RtlWaitOnAddress(ptr, &expect, @sizeOf(@TypeOf(expect)), null)) {
4933 .SUCCESS => {},
4934 .CANCELLED => return error.Canceled,
4935 else => recoverableOsBugDetected(),
4936 }
4937 } else {
4938 @compileError("TODO");
4937 }4939 }
4938
4939 @compileError("TODO");
4940}4940}
49414941
4942pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) void {4942pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) void {
...@@ -4954,10 +4954,7 @@ pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) voi...@@ -4954,10 +4954,7 @@ pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) voi
4954 .FAULT => unreachable, // ptr was invalid4954 .FAULT => unreachable, // ptr was invalid
4955 else => unreachable,4955 else => unreachable,
4956 };4956 };
4957 return;4957 } else if (native_os.isDarwin()) {
4958 }
4959
4960 if (native_os.isDarwin()) {
4961 const c = std.c;4958 const c = std.c;
4962 const flags: c.UL = .{4959 const flags: c.UL = .{
4963 .op = .COMPARE_AND_WAIT,4960 .op = .COMPARE_AND_WAIT,
...@@ -4980,10 +4977,7 @@ pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) voi...@@ -4980,10 +4977,7 @@ pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) voi
4980 .TIMEDOUT => unreachable,4977 .TIMEDOUT => unreachable,
4981 else => unreachable,4978 else => unreachable,
4982 };4979 };
4983 return;4980 } else if (builtin.cpu.arch.isWasm()) {
4984 }
4985
4986 if (builtin.cpu.arch.isWasm()) {
4987 comptime assert(builtin.cpu.has(.wasm, .atomics));4981 comptime assert(builtin.cpu.has(.wasm, .atomics));
4988 const timeout: i64 = -1;4982 const timeout: i64 = -1;
4989 const signed_expect: i32 = @bitCast(expect);4983 const signed_expect: i32 = @bitCast(expect);
...@@ -5005,10 +4999,14 @@ pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) voi...@@ -5005,10 +4999,14 @@ pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) voi
5005 2 => assert(!is_debug), // timeout4999 2 => assert(!is_debug), // timeout
5006 else => assert(!is_debug),5000 else => assert(!is_debug),
5007 }5001 }
5008 return;5002 } else if (is_windows) {
5003 switch (windows.ntdll.RtlWaitOnAddress(ptr, &expect, @sizeOf(@TypeOf(expect)), null)) {
5004 .SUCCESS, .CANCELLED => {},
5005 else => recoverableOsBugDetected(),
5006 }
5007 } else {
5008 @compileError("TODO");
5009 }5009 }
5010
5011 @compileError("TODO");
5012}5010}
50135011
5014pub fn futexWaitDurationUncancelable(ptr: *const std.atomic.Value(u32), expect: u32, timeout: Io.Duration) void {5012pub fn futexWaitDurationUncancelable(ptr: *const std.atomic.Value(u32), expect: u32, timeout: Io.Duration) void {
...@@ -5028,9 +5026,9 @@ pub fn futexWaitDurationUncancelable(ptr: *const std.atomic.Value(u32), expect:...@@ -5028,9 +5026,9 @@ pub fn futexWaitDurationUncancelable(ptr: *const std.atomic.Value(u32), expect:
5028 else => unreachable,5026 else => unreachable,
5029 };5027 };
5030 return;5028 return;
5029 } else {
5030 @compileError("TODO");
5031 }5031 }
5032
5033 @compileError("TODO");
5034}5032}
50355033
5036pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void {5034pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void {
...@@ -5049,10 +5047,7 @@ pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void {...@@ -5049,10 +5047,7 @@ pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void {
5049 .FAULT => {}, // pointer became invalid while doing the wake5047 .FAULT => {}, // pointer became invalid while doing the wake
5050 else => unreachable,5048 else => unreachable,
5051 };5049 };
5052 return;5050 } else if (native_os.isDarwin()) {
5053 }
5054
5055 if (native_os.isDarwin()) {
5056 const c = std.c;5051 const c = std.c;
5057 const flags: c.UL = .{5052 const flags: c.UL = .{
5058 .op = .COMPARE_AND_WAIT,5053 .op = .COMPARE_AND_WAIT,
...@@ -5071,9 +5066,7 @@ pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void {...@@ -5071,9 +5066,7 @@ pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void {
5071 else => assert(!is_debug),5066 else => assert(!is_debug),
5072 }5067 }
5073 }5068 }
5074 }5069 } else if (builtin.cpu.arch.isWasm()) {
5075
5076 if (builtin.cpu.arch.isWasm()) {
5077 comptime assert(builtin.cpu.has(.wasm, .atomics));5070 comptime assert(builtin.cpu.has(.wasm, .atomics));
5078 assert(max_waiters != 0);5071 assert(max_waiters != 0);
5079 const woken_count = asm volatile (5072 const woken_count = asm volatile (
...@@ -5086,10 +5079,15 @@ pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void {...@@ -5086,10 +5079,15 @@ pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void {
5086 [waiters] "r" (max_waiters),5079 [waiters] "r" (max_waiters),
5087 );5080 );
5088 _ = woken_count; // can be 0 when linker flag 'shared-memory' is not enabled5081 _ = woken_count; // can be 0 when linker flag 'shared-memory' is not enabled
5089 return;5082 } else if (is_windows) {
5083 assert(max_waiters != 0);
5084 switch (max_waiters) {
5085 1 => windows.ntdll.RtlWakeAddressSingle(ptr),
5086 else => windows.ntdll.RtlWakeAddressAll(ptr),
5087 }
5088 } else {
5089 @compileError("TODO");
5090 }5090 }
5091
5092 @compileError("TODO");
5093}5091}
50945092
5095/// A thread-safe logical boolean value which can be `set` and `unset`.5093/// A thread-safe logical boolean value which can be `set` and `unset`.