diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2024-09-24 16:15:06 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-09-26 12:35:14 -0700 |
| commit | 04e694ad116ad2706328c13ce3643347330a861f (patch) | |
| tree | 9aa8a254e980c73733b07dabbb5c6d4d0905a546 /lib/std/Thread.zig | |
| parent | 085cc54aadb327b9910be2c72b31ea046e7e8f52 (diff) | |
| download | zig-04e694ad116ad2706328c13ce3643347330a861f.tar.gz zig-04e694ad116ad2706328c13ce3643347330a861f.zip | |
move std.time.sleep to std.Thread.sleep
Diffstat (limited to 'lib/std/Thread.zig')
| -rw-r--r-- | lib/std/Thread.zig | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 446b629cc6..a5c03138f7 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 |
