lib/sys/src/time.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const builtin = @import("builtin");
3 const capabilities = @import("capabilities.zig");
4
5 pub const required_capabilities = capabilities.noLibc(&.{.time});
6 pub const ClockError = error{
7 UnsupportedPlatform,
8 ClockUnavailable,
9 ClockRegressed,
10 ClockOverflow,
11 };
12
13 pub const ExternalClockId = enum(u32) {
14 _,
15
16 pub fn fromNative(value: u32) ExternalClockId {
17 return @fromBackingInt(@intCast(value));
18 }
19
20 pub fn toNative(self: ExternalClockId) u32 {
21 return @backingInt(self);
22 }
23 };
24
25 pub const real_clock_id = ExternalClockId.fromNative(
26 @intCast(@backingInt(std.os.linux.clockid_t.REALTIME)),
27 );
28 pub const awake_clock_id = ExternalClockId.fromNative(
29 @intCast(@backingInt(std.os.linux.clockid_t.MONOTONIC)),
30 );
31 pub const boot_clock_id = ExternalClockId.fromNative(
32 @intCast(@backingInt(std.os.linux.clockid_t.BOOTTIME)),
33 );
34
35 pub const Duration = enum(u64) {
36 _,
37
38 pub const zero: Duration = @fromBackingInt(@intCast(0));
39
40 pub fn fromNanoseconds(value: u64) Duration {
41 return @fromBackingInt(@intCast(value));
42 }
43
44 pub fn fromMilliseconds(value: u64) Duration {
45 return @fromBackingInt(@intCast(value *| std.time.ns_per_ms));
46 }
47
48 pub fn asNanoseconds(self: Duration) u64 {
49 return @backingInt(self);
50 }
51
52 pub fn asMillisecondsFloor(self: Duration) u64 {
53 return self.asNanoseconds() / std.time.ns_per_ms;
54 }
55
56 pub fn asMillisecondsCeil(self: Duration) u64 {
57 const nanoseconds = self.asNanoseconds();
58 if (nanoseconds == 0) return 0;
59 return 1 + (nanoseconds - 1) / std.time.ns_per_ms;
60 }
61
62 pub fn isZero(self: Duration) bool {
63 return self == zero;
64 }
65
66 pub fn min(self: Duration, other: Duration) Duration {
67 return if (self.asNanoseconds() <= other.asNanoseconds()) self else other;
68 }
69
70 pub fn saturatingMultiply(self: Duration, factor: u64) Duration {
71 return .fromNanoseconds(self.asNanoseconds() *| factor);
72 }
73 };
74
75 pub const AwakeInstant = enum(u64) {
76 _,
77
78 pub const zero: AwakeInstant = @fromBackingInt(@intCast(0));
79
80 pub fn fromNanoseconds(value: u64) AwakeInstant {
81 return @fromBackingInt(@intCast(value));
82 }
83
84 pub fn asNanoseconds(self: AwakeInstant) u64 {
85 return @backingInt(self);
86 }
87
88 pub fn elapsedSince(self: AwakeInstant, earlier: AwakeInstant) ClockError!Duration {
89 const current = self.asNanoseconds();
90 const start = earlier.asNanoseconds();
91 if (current < start) return error.ClockRegressed;
92 return Duration.fromNanoseconds(current - start);
93 }
94
95 pub fn deadlineAfter(self: AwakeInstant, duration: Duration) AwakeInstant {
96 return @fromBackingInt(@intCast(self.asNanoseconds() +| duration.asNanoseconds()));
97 }
98
99 pub fn reached(self: AwakeInstant, deadline: AwakeInstant) bool {
100 return self.asNanoseconds() >= deadline.asNanoseconds();
101 }
102
103 pub fn isBefore(self: AwakeInstant, other: AwakeInstant) bool {
104 return self.asNanoseconds() < other.asNanoseconds();
105 }
106
107 pub fn remainingUntil(self: AwakeInstant, deadline: AwakeInstant) Duration {
108 if (self.reached(deadline)) return .zero;
109 return .fromNanoseconds(deadline.asNanoseconds() - self.asNanoseconds());
110 }
111 };
112
113 pub const BootInstant = enum(u64) {
114 _,
115
116 pub const zero: BootInstant = @fromBackingInt(@intCast(0));
117
118 pub fn fromNanoseconds(value: u64) BootInstant {
119 return @fromBackingInt(@intCast(value));
120 }
121
122 pub fn asNanoseconds(self: BootInstant) u64 {
123 return @backingInt(self);
124 }
125
126 pub fn elapsedSince(self: BootInstant, earlier: BootInstant) ClockError!Duration {
127 const current = self.asNanoseconds();
128 const start = earlier.asNanoseconds();
129 if (current < start) return error.ClockRegressed;
130 return Duration.fromNanoseconds(current - start);
131 }
132
133 pub fn deadlineAfter(self: BootInstant, duration: Duration) BootInstant {
134 return @fromBackingInt(@intCast(self.asNanoseconds() +| duration.asNanoseconds()));
135 }
136
137 pub fn reached(self: BootInstant, deadline: BootInstant) bool {
138 return self.asNanoseconds() >= deadline.asNanoseconds();
139 }
140
141 pub fn isBefore(self: BootInstant, other: BootInstant) bool {
142 return self.asNanoseconds() < other.asNanoseconds();
143 }
144
145 pub fn remainingUntil(self: BootInstant, deadline: BootInstant) Duration {
146 if (self.reached(deadline)) return .zero;
147 return .fromNanoseconds(deadline.asNanoseconds() - self.asNanoseconds());
148 }
149 };
150
151 pub const WallTimestamp = enum(u64) {
152 _,
153
154 pub const epoch: WallTimestamp = @fromBackingInt(@intCast(0));
155
156 pub fn fromNanoseconds(value: u64) WallTimestamp {
157 return @fromBackingInt(@intCast(value));
158 }
159
160 pub fn asNanoseconds(self: WallTimestamp) u64 {
161 return @backingInt(self);
162 }
163
164 pub fn asMilliseconds(self: WallTimestamp) u64 {
165 return self.asNanoseconds() / std.time.ns_per_ms;
166 }
167 };
168
169 pub const AwakeClock = struct {
170 context: ?*anyopaque = null,
171 read_fn: *const fn (?*anyopaque) ClockError!AwakeInstant = readSystemAwake,
172
173 pub fn system() AwakeClock {
174 return .{};
175 }
176
177 pub fn now(self: AwakeClock) ClockError!AwakeInstant {
178 return self.read_fn(self.context);
179 }
180 };
181
182 pub const BootClock = struct {
183 context: ?*anyopaque = null,
184 read_fn: *const fn (?*anyopaque) ClockError!BootInstant = readSystemBoot,
185
186 pub fn system() BootClock {
187 return .{};
188 }
189
190 pub fn now(self: BootClock) ClockError!BootInstant {
191 return self.read_fn(self.context);
192 }
193 };
194
195 pub const FakeClock = struct {
196 awake: AwakeInstant,
197 boot: BootInstant,
198 wall: WallTimestamp,
199 reads_unavailable: bool = false,
200
201 pub fn init(
202 awake: AwakeInstant,
203 boot: BootInstant,
204 wall: WallTimestamp,
205 ) FakeClock {
206 return .{ .awake = awake, .boot = boot, .wall = wall };
207 }
208
209 pub fn zero() FakeClock {
210 return init(.zero, .zero, .epoch);
211 }
212
213 pub fn awakeClock(self: *FakeClock) AwakeClock {
214 return .{ .context = self, .read_fn = readFakeAwake };
215 }
216
217 pub fn bootClock(self: *FakeClock) BootClock {
218 return .{ .context = self, .read_fn = readFakeBoot };
219 }
220
221 pub fn advance(self: *FakeClock, duration: Duration) void {
222 const delta = duration.asNanoseconds();
223 self.awake = .fromNanoseconds(self.awake.asNanoseconds() +| delta);
224 self.boot = .fromNanoseconds(self.boot.asNanoseconds() +| delta);
225 self.wall = .fromNanoseconds(self.wall.asNanoseconds() +| delta);
226 }
227
228 pub fn regress(self: *FakeClock, duration: Duration) void {
229 const delta = duration.asNanoseconds();
230 self.awake = .fromNanoseconds(self.awake.asNanoseconds() -| delta);
231 self.boot = .fromNanoseconds(self.boot.asNanoseconds() -| delta);
232 self.wall = .fromNanoseconds(self.wall.asNanoseconds() -| delta);
233 }
234
235 pub fn suspendGap(self: *FakeClock, duration: Duration) void {
236 const delta = duration.asNanoseconds();
237 self.boot = .fromNanoseconds(self.boot.asNanoseconds() +| delta);
238 self.wall = .fromNanoseconds(self.wall.asNanoseconds() +| delta);
239 }
240
241 pub fn overflow(self: *FakeClock) void {
242 self.awake = .fromNanoseconds(std.math.maxInt(u64));
243 self.boot = .fromNanoseconds(std.math.maxInt(u64));
244 self.wall = .fromNanoseconds(std.math.maxInt(u64));
245 }
246
247 pub fn setWall(self: *FakeClock, wall: WallTimestamp) void {
248 self.wall = wall;
249 }
250
251 pub fn setReadsUnavailable(self: *FakeClock, unavailable: bool) void {
252 self.reads_unavailable = unavailable;
253 }
254 };
255
256 pub fn supportsAwakeClock() bool {
257 return switch (builtin.os.tag) {
258 .freestanding, .wasi => false,
259 else => true,
260 };
261 }
262
263 pub fn supportsBootClock() bool {
264 return switch (builtin.os.tag) {
265 .freestanding, .wasi => false,
266 else => true,
267 };
268 }
269
270 pub fn supportsRealClock() bool {
271 return switch (builtin.os.tag) {
272 .freestanding, .wasi => false,
273 else => true,
274 };
275 }
276
277 pub fn awakeNow() ClockError!AwakeInstant {
278 const value = awakeNanoseconds() orelse return error.ClockUnavailable;
279 return .fromNanoseconds(try nonnegativeNanoseconds(value));
280 }
281
282 pub fn bootNow() ClockError!BootInstant {
283 const value = bootNanoseconds() orelse return error.ClockUnavailable;
284 return .fromNanoseconds(try nonnegativeNanoseconds(value));
285 }
286
287 pub fn wallNow() ClockError!WallTimestamp {
288 const value = realNanoseconds() orelse return error.ClockUnavailable;
289 return .fromNanoseconds(try nonnegativeNanoseconds(value));
290 }
291
292 pub fn awakeNanoseconds() ?i128 {
293 if (comptime !supportsAwakeClock()) return null;
294 return switch (builtin.os.tag) {
295 .linux => linuxClockNanoseconds(.MONOTONIC),
296 else => std.Io.Timestamp.now(std.Options.debug_io, .awake).toNanoseconds(),
297 };
298 }
299
300 /// CPU time spent by every thread of the process, or null where the host keeps no such clock.
301 pub fn processCpuNanoseconds() ?i128 {
302 return switch (builtin.os.tag) {
303 .linux => linuxClockNanoseconds(.PROCESS_CPUTIME_ID),
304 else => null,
305 };
306 }
307
308 pub fn bootNanoseconds() ?i128 {
309 if (comptime !supportsBootClock()) return null;
310 return switch (builtin.os.tag) {
311 .linux => linuxClockNanoseconds(.BOOTTIME),
312 else => std.Io.Timestamp.now(std.Options.debug_io, .boot).toNanoseconds(),
313 };
314 }
315
316 pub fn realNanoseconds() ?i128 {
317 if (comptime !supportsRealClock()) return null;
318 return switch (builtin.os.tag) {
319 .linux => linuxClockNanoseconds(.REALTIME),
320 else => std.Io.Timestamp.now(std.Options.debug_io, .real).toNanoseconds(),
321 };
322 }
323
324 pub fn externalClockNanoseconds(clock_id: ExternalClockId) ClockError!i128 {
325 if (comptime builtin.os.tag != .linux) return error.UnsupportedPlatform;
326 const clock: std.os.linux.clockid_t = @fromBackingInt(@intCast(clock_id.toNative()));
327 return linuxClockNanoseconds(clock) orelse error.ClockUnavailable;
328 }
329
330 pub fn nanoTimestamp() i128 {
331 return @intCast((awakeNow() catch @panic("awake clock unavailable")).asNanoseconds());
332 }
333
334 pub fn realNanoTimestamp() i128 {
335 return @intCast((wallNow() catch @panic("wall clock unavailable")).asNanoseconds());
336 }
337
338 pub fn realMilliTimestamp() i64 {
339 return @intCast(@divTrunc(realNanoTimestamp(), std.time.ns_per_ms));
340 }
341
342 pub fn ioTimestampNanoseconds(timestamp_value: std.Io.Timestamp) u64 {
343 return @intCast(timestamp_value.nanoseconds);
344 }
345
346 pub fn seconds() f64 {
347 return @as(f64, @floatFromInt(nanoTimestamp())) / @as(f64, @floatFromInt(std.time.ns_per_s));
348 }
349
350 pub fn realSeconds() f64 {
351 return @as(f64, @floatFromInt(realNanoTimestamp())) /
352 @as(f64, @floatFromInt(std.time.ns_per_s));
353 }
354
355 pub fn microTimestamp() i64 {
356 return @intCast(@divTrunc(nanoTimestamp(), std.time.ns_per_us));
357 }
358
359 pub fn milliTimestamp() i64 {
360 return @intCast(@divTrunc(nanoTimestamp(), std.time.ns_per_ms));
361 }
362
363 pub fn timestamp() i64 {
364 return @intCast(@divTrunc(nanoTimestamp(), std.time.ns_per_s));
365 }
366
367 pub fn sleepNanoseconds(duration_ns: u64) void {
368 if (duration_ns == 0) return;
369 if (comptime builtin.os.tag == .freestanding or builtin.os.tag == .wasi) return;
370 switch (builtin.os.tag) {
371 .linux => linuxSleepNanoseconds(duration_ns),
372 else => std.Io.sleep(std.Options.debug_io, .fromNanoseconds(duration_ns), .awake) catch {},
373 }
374 }
375
376 pub fn sleepMilliseconds(duration_ms: u64) void {
377 sleepNanoseconds(sleepNanosecondsForMilliseconds(duration_ms));
378 }
379
380 pub fn sleepSeconds(duration_seconds: f64) void {
381 sleepNanoseconds(sleepNanosecondsForSeconds(duration_seconds));
382 }
383
384 fn sleepNanosecondsForMilliseconds(duration_ms: u64) u64 {
385 if (duration_ms > std.math.maxInt(u64) / std.time.ns_per_ms) return std.math.maxInt(u64);
386 return duration_ms * std.time.ns_per_ms;
387 }
388
389 fn sleepNanosecondsForSeconds(duration_seconds: f64) u64 {
390 if (!std.math.isFinite(duration_seconds) or duration_seconds <= 0) return 0;
391 const ns_per_s: f64 = @floatFromInt(std.time.ns_per_s);
392 const max_seconds = @as(f64, @floatFromInt(std.math.maxInt(u64))) / ns_per_s;
393 if (duration_seconds >= max_seconds) return std.math.maxInt(u64);
394 return @intFromFloat(@round(duration_seconds * ns_per_s));
395 }
396
397 fn readSystemAwake(_: ?*anyopaque) ClockError!AwakeInstant {
398 return awakeNow();
399 }
400
401 fn readSystemBoot(_: ?*anyopaque) ClockError!BootInstant {
402 return bootNow();
403 }
404
405 fn readFakeAwake(context: ?*anyopaque) ClockError!AwakeInstant {
406 const clock: *FakeClock = @ptrCast(@alignCast(context orelse unreachable));
407 if (clock.reads_unavailable) return error.ClockUnavailable;
408 return clock.awake;
409 }
410
411 fn readFakeBoot(context: ?*anyopaque) ClockError!BootInstant {
412 const clock: *FakeClock = @ptrCast(@alignCast(context orelse unreachable));
413 if (clock.reads_unavailable) return error.ClockUnavailable;
414 return clock.boot;
415 }
416
417 fn nonnegativeNanoseconds(value: i128) ClockError!u64 {
418 if (value < 0 or value > std.math.maxInt(u64)) return error.ClockUnavailable;
419 return @intCast(value);
420 }
421
422 fn linuxClockNanoseconds(clock: std.os.linux.clockid_t) ?i128 {
423 const linux = std.os.linux;
424 var ts: linux.timespec = undefined;
425 const rc = linux.clock_gettime(clock, &ts);
426 if (linux.errno(rc) != .SUCCESS) return null;
427 if (ts.sec < 0 or ts.nsec < 0) return null;
428 return @as(i128, @intCast(ts.sec)) * std.time.ns_per_s + @as(i128, @intCast(ts.nsec));
429 }
430
431 fn linuxSleepNanoseconds(duration_ns: u64) void {
432 const linux = std.os.linux;
433 var remaining = linux.timespec{
434 .sec = @intCast(duration_ns / std.time.ns_per_s),
435 .nsec = @intCast(duration_ns % std.time.ns_per_s),
436 };
437 while (true) {
438 var next: linux.timespec = undefined;
439 const rc = linux.syscall2(.nanosleep, @intFromPtr(&remaining), @intFromPtr(&next));
440 switch (linux.errno(rc)) {
441 .SUCCESS => return,
442 .INTR => remaining = next,
443 else => return,
444 }
445 }
446 }
447
448 test "timestamp helpers are callable on every target" {
449 if (supportsAwakeClock()) {
450 try std.testing.expect((try awakeNow()).asNanoseconds() > 0);
451 try std.testing.expect(nanoTimestamp() >= 0);
452 try std.testing.expect(seconds() >= 0);
453 try std.testing.expect(microTimestamp() >= 0);
454 try std.testing.expect(milliTimestamp() >= 0);
455 try std.testing.expect(timestamp() >= 0);
456 } else {
457 try std.testing.expectError(error.ClockUnavailable, awakeNow());
458 }
459 if (supportsBootClock()) {
460 try std.testing.expect((try bootNow()).asNanoseconds() > 0);
461 } else {
462 try std.testing.expectError(error.ClockUnavailable, bootNow());
463 }
464 if (supportsRealClock()) {
465 try std.testing.expect((try wallNow()).asNanoseconds() > 0);
466 try std.testing.expect(realNanoTimestamp() >= 0);
467 try std.testing.expect(realSeconds() >= 0);
468 try std.testing.expect(realMilliTimestamp() >= 0);
469 } else {
470 try std.testing.expectError(error.ClockUnavailable, wallNow());
471 }
472 }
473
474 test "Linux awake clock read is monotone within the vDSO budget" {
475 if (comptime builtin.os.tag != .linux) return error.SkipZigTest;
476 const sample_count: usize = 64;
477 const median_budget_ns: u64 = 250;
478 var samples: [sample_count]u64 = undefined;
479 for (&samples) |*sample| {
480 const before = try awakeNow();
481 const after = try awakeNow();
482 try std.testing.expect(after.asNanoseconds() >= before.asNanoseconds());
483 sample.* = (try after.elapsedSince(before)).asNanoseconds();
484 }
485 std.mem.sort(u64, &samples, {}, std.sort.asc(u64));
486 try std.testing.expect(samples[samples.len / 2] <= median_budget_ns);
487 }
488
489 test "instant subtraction accepts one clock type" {
490 comptime {
491 const awake_subtract: *const fn (
492 AwakeInstant,
493 AwakeInstant,
494 ) ClockError!Duration = AwakeInstant.elapsedSince;
495 const boot_subtract: *const fn (
496 BootInstant,
497 BootInstant,
498 ) ClockError!Duration = BootInstant.elapsedSince;
499 _ = awake_subtract;
500 _ = boot_subtract;
501 std.debug.assert(AwakeInstant != BootInstant);
502 std.debug.assert(AwakeInstant != WallTimestamp);
503 }
504 }
505
506 test "instant subtraction reports regression" {
507 const earlier = AwakeInstant.fromNanoseconds(8);
508 const current = AwakeInstant.fromNanoseconds(5);
509 try std.testing.expectError(error.ClockRegressed, current.elapsedSince(earlier));
510 }
511
512 test "deadline and duration arithmetic saturate" {
513 const duration = Duration.fromMilliseconds(std.math.maxInt(u64));
514 try std.testing.expectEqual(std.math.maxInt(u64), duration.asNanoseconds());
515 const start = AwakeInstant.fromNanoseconds(std.math.maxInt(u64) - 1);
516 const deadline = start.deadlineAfter(.fromNanoseconds(2));
517 try std.testing.expectEqual(std.math.maxInt(u64), deadline.asNanoseconds());
518 try std.testing.expectEqual(
519 @as(u64, 2),
520 Duration.fromNanoseconds(1_001_000).asMillisecondsCeil(),
521 );
522 try std.testing.expectEqual(
523 Duration.fromNanoseconds(5),
524 Duration.fromNanoseconds(8).min(.fromNanoseconds(5)),
525 );
526 try std.testing.expectEqual(
527 std.math.maxInt(u64),
528 Duration.fromNanoseconds(std.math.maxInt(u64)).saturatingMultiply(2).asNanoseconds(),
529 );
530 }
531
532 test "fake clock separates awake suspension and wall jumps" {
533 var clock = FakeClock.zero();
534 clock.advance(.fromMilliseconds(2));
535 try std.testing.expectEqual(@as(u64, 2_000_000), clock.awake.asNanoseconds());
536 clock.suspendGap(.fromMilliseconds(3));
537 try std.testing.expectEqual(@as(u64, 2_000_000), clock.awake.asNanoseconds());
538 try std.testing.expectEqual(@as(u64, 5_000_000), clock.boot.asNanoseconds());
539 clock.setWall(.fromNanoseconds(9));
540 try std.testing.expectEqual(@as(u64, 9), clock.wall.asNanoseconds());
541 clock.regress(.fromNanoseconds(1));
542 try std.testing.expectEqual(@as(u64, 1_999_999), clock.awake.asNanoseconds());
543 clock.overflow();
544 try std.testing.expectEqual(std.math.maxInt(u64), clock.awake.asNanoseconds());
545 }
546
547 test "fake typed clocks report unavailability" {
548 var fake = FakeClock.zero();
549 const awake_clock = fake.awakeClock();
550 const boot_clock = fake.bootClock();
551 try std.testing.expectEqual(AwakeInstant.zero, try awake_clock.now());
552 try std.testing.expectEqual(BootInstant.zero, try boot_clock.now());
553 fake.setReadsUnavailable(true);
554 try std.testing.expectError(error.ClockUnavailable, awake_clock.now());
555 try std.testing.expectError(error.ClockUnavailable, boot_clock.now());
556 }
557
558 test "external clock ids route through the opaque sampled clock boundary" {
559 if (builtin.os.tag != .linux) {
560 try std.testing.expectError(
561 error.UnsupportedPlatform,
562 externalClockNanoseconds(awake_clock_id),
563 );
564 return;
565 }
566 try std.testing.expectEqual(
567 @as(u32, @intCast(@backingInt(std.os.linux.clockid_t.REALTIME))),
568 real_clock_id.toNative(),
569 );
570 try std.testing.expect(try externalClockNanoseconds(real_clock_id) > 0);
571 try std.testing.expect(try externalClockNanoseconds(awake_clock_id) > 0);
572 try std.testing.expect(try externalClockNanoseconds(boot_clock_id) > 0);
573 try std.testing.expectError(
574 error.ClockUnavailable,
575 externalClockNanoseconds(.fromNative(std.math.maxInt(u32))),
576 );
577 }
578
579 test "io timestamp conversion preserves nanoseconds" {
580 try std.testing.expectEqual(@as(u64, 1234), ioTimestampNanoseconds(.{ .nanoseconds = 1234 }));
581 }
582
583 test "sleep second conversion rejects invalid durations" {
584 try std.testing.expectEqual(@as(u64, 0), sleepNanosecondsForSeconds(-1));
585 try std.testing.expectEqual(@as(u64, 0), sleepNanosecondsForSeconds(0));
586 try std.testing.expectEqual(@as(u64, 0), sleepNanosecondsForSeconds(std.math.inf(f64)));
587 }
588
589 test "sleep millisecond conversion saturates" {
590 try std.testing.expectEqual(@as(u64, 0), sleepNanosecondsForMilliseconds(0));
591 try std.testing.expectEqual(@as(u64, std.time.ns_per_ms), sleepNanosecondsForMilliseconds(1));
592 try std.testing.expectEqual(
593 std.math.maxInt(u64),
594 sleepNanosecondsForMilliseconds(std.math.maxInt(u64)),
595 );
596 }
597
598 test "sleep second conversion rounds and saturates" {
599 try std.testing.expectEqual(@as(u64, 1), sleepNanosecondsForSeconds(0.000000001));
600 try std.testing.expectEqual(@as(u64, 1_500_000_000), sleepNanosecondsForSeconds(1.5));
601 try std.testing.expectEqual(
602 std.math.maxInt(u64),
603 sleepNanosecondsForSeconds(@as(f64, @floatFromInt(std.math.maxInt(u64)))),
604 );
605 }