From 4319c8924ed2a73abdc8f4caa80703d2949be810 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 7 Jan 2026 20:20:03 -0800 Subject: [PATCH 1/2] std.Io.Threaded: clock_nanosleep is not linux-only clock_nanosleep is specified by POSIX but not implemented on these hereby shamed operating systems: * macOS * OpenBSD (which defines TIMER_ABSTIME for some reason...?) --- lib/std/Io/Threaded.zig | 14 ++++++-------- lib/std/c.zig | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 065665532c963a7214881f373c748d3d252be77c..a3764dc91c6e95e5327baed69c6036da7f90a3f0 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -9664,14 +9664,12 @@ fn nowWasi(clock: Io.Clock) Io.Clock.Error!Io.Timestamp { fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { const t: *Threaded = @ptrCast(@alignCast(userdata)); if (use_parking_sleep) return parking_sleep.sleep(timeout); - switch (native_os) { - .wasi => return sleepWasi(t, timeout), - .linux => return sleepLinux(timeout), - else => return sleepPosix(t, timeout), - } + if (native_os == .wasi) return sleepWasi(t, timeout); + if (@TypeOf(posix.system.clock_nanosleep) != void) return sleepPosix(timeout); + return sleepNanosleep(t, timeout); } -fn sleepLinux(timeout: Io.Timeout) Io.SleepError!void { +fn sleepPosix(timeout: Io.Timeout) Io.SleepError!void { const clock_id: posix.clockid_t = clockToPosix(switch (timeout) { .none => .awake, .duration => |d| d.clock, @@ -9685,7 +9683,7 @@ fn sleepLinux(timeout: Io.Timeout) Io.SleepError!void { var timespec: posix.timespec = timestampToPosix(deadline_nanoseconds); const syscall: Syscall = try .start(); while (true) { - switch (std.os.linux.errno(std.os.linux.clock_nanosleep(clock_id, .{ .ABSTIME = switch (timeout) { + switch (posix.errno(posix.system.clock_nanosleep(clock_id, .{ .ABSTIME = switch (timeout) { .none, .duration => false, .deadline => true, } }, ×pec, ×pec))) { @@ -9737,7 +9735,7 @@ fn sleepWasi(t: *Threaded, timeout: Io.Timeout) Io.SleepError!void { syscall.finish(); } -fn sleepPosix(t: *Threaded, timeout: Io.Timeout) Io.SleepError!void { +fn sleepNanosleep(t: *Threaded, timeout: Io.Timeout) Io.SleepError!void { const t_io = ioBasic(t); const sec_type = @typeInfo(posix.timespec).@"struct".fields[0].type; const nsec_type = @typeInfo(posix.timespec).@"struct".fields[1].type; diff --git a/lib/std/c.zig b/lib/std/c.zig index e1a4def3687f82b41c3d7e9b56062a549466561a..da499e63328c6095ac84436e6ce216cb9b3237bd 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -11078,6 +11078,20 @@ pub extern "c" fn pthread_getthreadid_np() c_int; pub extern "c" fn pthread_set_name_np(thread: pthread_t, name: [*:0]const u8) void; pub extern "c" fn pthread_get_name_np(thread: pthread_t, name: [*:0]u8, len: usize) void; +pub const TIMER = switch (native_os) { + .linux, .emscripten => std.os.linux.TIMER, + .openbsd, .netbsd, .wasi, .windows, .freebsd => packed struct(u32) { + ABSTIME: bool, + _: u31 = 0, + }, + else => void, +}; + +pub const clock_nanosleep = switch (native_os) { + .linux, .emscripten, .netbsd, .wasi, .windows, .freebsd => private.clock_nanosleep, + else => {}, +}; + // OS-specific bits. These are protected from being used on the wrong OS by // comptime assertions inside each OS-specific file. @@ -11467,6 +11481,7 @@ const private = struct { extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; extern "c" fn msync(addr: *align(page_size) const anyopaque, len: usize, flags: c_int) c_int; extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; + extern "c" fn clock_nanosleep(clockid: clockid_t, flags: TIMER, t: *const timespec, remain: ?*timespec) c_int; extern "c" fn pipe2(fds: *[2]fd_t, flags: O) c_int; extern "c" fn readdir(dir: *DIR) ?*dirent; extern "c" fn realpath(noalias file_name: [*:0]const u8, noalias resolved_name: [*]u8) ?[*:0]u8; -- 2.54.0 From 130fc7ef751e665de14b440a3b5a3ee75d2312e0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 7 Jan 2026 20:57:18 -0800 Subject: [PATCH 2/2] std.c: use {} rather than void for absent functions --- lib/std/c.zig | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/std/c.zig b/lib/std/c.zig index da499e63328c6095ac84436e6ce216cb9b3237bd..0cf52edbb3cbb5299d16edc2db85b4eb200dfec6 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -10579,7 +10579,7 @@ pub const socket = switch (native_os) { pub const socketpair = switch (native_os) { // https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/#unsupported\unavailable: - .windows => void, + .windows => {}, else => private.socketpair, }; @@ -10766,11 +10766,10 @@ pub extern "c" fn recvfrom( ) if (native_os == .windows) c_int else isize; pub const recvmsg = switch (native_os) { - // Windows: Technically, a form of recvmsg() exists for Windows, but the - // user has to install some kind of callback for it. I'm not sure if/how - // we can map this to normal recvmsg() interface use. + // Technically, a form of recvmsg() exists for Windows, but the user has to + // install some kind of callback for it. // https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nc-mswsock-lpfn_wsarecvmsg - .windows => void, + .windows => {}, else => private.recvmsg, }; -- 2.54.0