From 04e694ad116ad2706328c13ce3643347330a861f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 24 Sep 2024 16:15:06 -0700 Subject: [PATCH] move std.time.sleep to std.Thread.sleep --- lib/std/Thread.zig | 77 +++++++++++++++++++++++++++++++++++++++++++ lib/std/time.zig | 82 +++------------------------------------------- 2 files changed, 81 insertions(+), 78 deletions(-) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 446b629cc6ec6a9dcfc5cb3cd22ab546161f5a96..a5c03138f79a99e302bacca48782744164801072 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -22,6 +22,83 @@ pub const WaitGroup = @import("Thread/WaitGroup.zig"); pub const use_pthreads = native_os != .windows and native_os != .wasi and builtin.link_libc; +/// Spurious wakeups are possible and no precision of timing is guaranteed. +pub fn sleep(nanoseconds: u64) void { + if (builtin.os.tag == .windows) { + const big_ms_from_ns = nanoseconds / std.time.ns_per_ms; + const ms = math.cast(windows.DWORD, big_ms_from_ns) orelse math.maxInt(windows.DWORD); + windows.kernel32.Sleep(ms); + return; + } + + if (builtin.os.tag == .wasi) { + const w = std.os.wasi; + const userdata: w.userdata_t = 0x0123_45678; + const clock: w.subscription_clock_t = .{ + .id = .MONOTONIC, + .timeout = nanoseconds, + .precision = 0, + .flags = 0, + }; + const in: w.subscription_t = .{ + .userdata = userdata, + .u = .{ + .tag = .CLOCK, + .u = .{ .clock = clock }, + }, + }; + + var event: w.event_t = undefined; + var nevents: usize = undefined; + _ = w.poll_oneoff(&in, &event, 1, &nevents); + return; + } + + if (builtin.os.tag == .uefi) { + const boot_services = std.os.uefi.system_table.boot_services.?; + const us_from_ns = nanoseconds / std.time.ns_per_us; + const us = math.cast(usize, us_from_ns) orelse math.maxInt(usize); + _ = boot_services.stall(us); + return; + } + + const s = nanoseconds / std.time.ns_per_s; + const ns = nanoseconds % std.time.ns_per_s; + + // Newer kernel ports don't have old `nanosleep()` and `clock_nanosleep()` has been around + // since Linux 2.6 and glibc 2.1 anyway. + if (builtin.os.tag == .linux) { + const linux = std.os.linux; + + var req: linux.timespec = .{ + .sec = std.math.cast(linux.time_t, s) orelse std.math.maxInt(linux.time_t), + .nsec = std.math.cast(linux.time_t, ns) orelse std.math.maxInt(linux.time_t), + }; + var rem: linux.timespec = undefined; + + while (true) { + switch (linux.E.init(linux.clock_nanosleep(.MONOTONIC, .{ .ABSTIME = false }, &req, &rem))) { + .SUCCESS => return, + .INTR => { + req = rem; + continue; + }, + .FAULT, + .INVAL, + .OPNOTSUPP, + => unreachable, + else => return, + } + } + } + + posix.nanosleep(s, ns); +} + +test sleep { + sleep(1); +} + const Thread = @This(); const Impl = if (native_os == .windows) WindowsThreadImpl diff --git a/lib/std/time.zig b/lib/std/time.zig index a80a2477acc791df49fae7b0cfe42d9bb0d6a209..d253b6351270bb3d0363dfcf54ad83d5c90d3919 100644 --- a/lib/std/time.zig +++ b/lib/std/time.zig @@ -8,82 +8,8 @@ const posix = std.posix; pub const epoch = @import("time/epoch.zig"); -/// Spurious wakeups are possible and no precision of timing is guaranteed. -pub fn sleep(nanoseconds: u64) void { - if (builtin.os.tag == .windows) { - const big_ms_from_ns = nanoseconds / ns_per_ms; - const ms = math.cast(windows.DWORD, big_ms_from_ns) orelse math.maxInt(windows.DWORD); - windows.kernel32.Sleep(ms); - return; - } - - if (builtin.os.tag == .wasi) { - const w = std.os.wasi; - const userdata: w.userdata_t = 0x0123_45678; - const clock: w.subscription_clock_t = .{ - .id = .MONOTONIC, - .timeout = nanoseconds, - .precision = 0, - .flags = 0, - }; - const in: w.subscription_t = .{ - .userdata = userdata, - .u = .{ - .tag = .CLOCK, - .u = .{ .clock = clock }, - }, - }; - - var event: w.event_t = undefined; - var nevents: usize = undefined; - _ = w.poll_oneoff(&in, &event, 1, &nevents); - return; - } - - if (builtin.os.tag == .uefi) { - const boot_services = std.os.uefi.system_table.boot_services.?; - const us_from_ns = nanoseconds / ns_per_us; - const us = math.cast(usize, us_from_ns) orelse math.maxInt(usize); - _ = boot_services.stall(us); - return; - } - - const s = nanoseconds / ns_per_s; - const ns = nanoseconds % ns_per_s; - - // Newer kernel ports don't have old `nanosleep()` and `clock_nanosleep()` has been around - // since Linux 2.6 and glibc 2.1 anyway. - if (builtin.os.tag == .linux) { - const linux = std.os.linux; - - var req: linux.timespec = .{ - .sec = std.math.cast(linux.time_t, s) orelse std.math.maxInt(linux.time_t), - .nsec = std.math.cast(linux.time_t, ns) orelse std.math.maxInt(linux.time_t), - }; - var rem: linux.timespec = undefined; - - while (true) { - switch (linux.E.init(linux.clock_nanosleep(.MONOTONIC, .{ .ABSTIME = false }, &req, &rem))) { - .SUCCESS => return, - .INTR => { - req = rem; - continue; - }, - .FAULT, - .INVAL, - .OPNOTSUPP, - => unreachable, - else => return, - } - } - } - - posix.nanosleep(s, ns); -} - -test sleep { - sleep(1); -} +/// Deprecated: moved to std.Thread.sleep +pub const sleep = std.Thread.sleep; /// Get a calendar timestamp, in seconds, relative to UTC 1970-01-01. /// Precision of timing depends on the hardware and operating system. @@ -155,7 +81,7 @@ test milliTimestamp { const margin = ns_per_ms * 50; const time_0 = milliTimestamp(); - sleep(ns_per_ms); + std.Thread.sleep(ns_per_ms); const time_1 = milliTimestamp(); const interval = time_1 - time_0; try testing.expect(interval > 0); @@ -359,7 +285,7 @@ test Timer { const margin = ns_per_ms * 150; var timer = try Timer.start(); - sleep(10 * ns_per_ms); + std.Thread.sleep(10 * ns_per_ms); const time_0 = timer.read(); try testing.expect(time_0 > 0); // Tests should not depend on timings: skip test if outside margin. -- 2.54.0