aboutsummaryrefslogtreecommitdiff
path: root/lib/std/Thread.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2024-09-24 16:15:06 -0700
committerAndrew Kelley <andrew@ziglang.org>2024-09-26 12:35:14 -0700
commit04e694ad116ad2706328c13ce3643347330a861f (patch)
tree9aa8a254e980c73733b07dabbb5c6d4d0905a546 /lib/std/Thread.zig
parent085cc54aadb327b9910be2c72b31ea046e7e8f52 (diff)
downloadzig-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.zig77
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