authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-24 20:06:56-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-24 21:40:08-04:00
log53d011fa1a7bfb2389e3677e1f6fcbe7a678e05f
tree6dc248d8606088f7a288c00f6ccef78290229cf4
parentc6e7d0fcfdf83531c5c931433528c540eee62e56

(breaking) std.time fixups and API changes

Remove the constants that assume a base unit in favor of explicit x_per_y constants. nanosecond calendar timestamps now use i128 for the type. This affects fs.File.Stat, std.time.nanoTimestamp, and fs.File.updateTimes. calendar timestamps are now signed, because the value can be less than the epoch (the user can set their computer time to whatever they wish). implement std.os.clock_gettime for Windows when clock id is CLOCK_CALENDAR.

13 files changed, 191 insertions(+), 170 deletions(-)

lib/std/event/batch.zig+1-1
......@@ -122,7 +122,7 @@ test "std.event.Batch" {
122122}
123123
124124fn sleepALittle(count: *usize) void {
125 std.time.sleep(1 * std.time.millisecond);
125 std.time.sleep(1 * std.time.ns_per_ms);
126126 _ = @atomicRmw(usize, count, .Add, 1, .SeqCst);
127127}
128128
lib/std/event/group.zig+1-1
......@@ -145,7 +145,7 @@ fn testGroup(allocator: *Allocator) callconv(.Async) void {
145145 testing.expectError(error.ItBroke, another.wait());
146146}
147147fn sleepALittle(count: *usize) callconv(.Async) void {
148 std.time.sleep(1 * std.time.millisecond);
148 std.time.sleep(1 * std.time.ns_per_ms);
149149 _ = @atomicRmw(usize, count, .Add, 1, .SeqCst);
150150}
151151fn increaseByTen(count: *usize) callconv(.Async) void {
lib/std/event/loop.zig+1-1
......@@ -457,7 +457,7 @@ pub const Loop = struct {
457457 => {
458458 // Even poll() didn't work. The best we can do now is sleep for a
459459 // small duration and then hope that something changed.
460 std.time.sleep(1 * std.time.millisecond);
460 std.time.sleep(1 * std.time.ns_per_ms);
461461 },
462462 };
463463 resume @frame();
lib/std/fs/file.zig+11-13
......@@ -227,14 +227,12 @@ pub const File = struct {
227227 size: u64,
228228 mode: Mode,
229229
230 /// access time in nanoseconds
231 atime: i64,
232
233 /// last modification time in nanoseconds
234 mtime: i64,
235
236 /// creation time in nanoseconds
237 ctime: i64,
230 /// Access time in nanoseconds, relative to UTC 1970-01-01.
231 atime: i128,
232 /// Last modification time in nanoseconds, relative to UTC 1970-01-01.
233 mtime: i128,
234 /// Creation time in nanoseconds, relative to UTC 1970-01-01.
235 ctime: i128,
238236 };
239237
240238 pub const StatError = os.FStatError;
......@@ -270,9 +268,9 @@ pub const File = struct {
270268 .inode = st.ino,
271269 .size = @bitCast(u64, st.size),
272270 .mode = st.mode,
273 .atime = @as(i64, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec,
274 .mtime = @as(i64, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec,
275 .ctime = @as(i64, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec,
271 .atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec,
272 .mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec,
273 .ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec,
276274 };
277275 }
278276
......@@ -286,9 +284,9 @@ pub const File = struct {
286284 pub fn updateTimes(
287285 self: File,
288286 /// access timestamp in nanoseconds
289 atime: i64,
287 atime: i128,
290288 /// last modification timestamp in nanoseconds
291 mtime: i64,
289 mtime: i128,
292290 ) UpdateTimesError!void {
293291 if (builtin.os.tag == .windows) {
294292 const atime_ft = windows.nanoSecondsToFileTime(atime);
lib/std/fs/test.zig+3-3
......@@ -10,7 +10,7 @@ test "openSelfExe" {
1010 self_exe_file.close();
1111}
1212
13const FILE_LOCK_TEST_SLEEP_TIME = 5 * std.time.millisecond;
13const FILE_LOCK_TEST_SLEEP_TIME = 5 * std.time.ns_per_ms;
1414
1515test "open file with exclusive nonblocking lock twice" {
1616 if (builtin.os.tag == .wasi) return error.SkipZigTest;
......@@ -142,8 +142,8 @@ const FileLockTestContext = struct {
142142
143143 // Output variables
144144 err: ?(File.OpenError || std.os.ReadError) = null,
145 start_time: u64 = 0,
146 end_time: u64 = 0,
145 start_time: i64 = 0,
146 end_time: i64 = 0,
147147 bytes_read: ?usize = null,
148148
149149 fn overlaps(self: *const @This(), other: *const @This()) bool {
lib/std/net.zig+2-2
......@@ -1135,13 +1135,13 @@ fn resMSendRc(
11351135 }};
11361136 const retry_interval = timeout / attempts;
11371137 var next: u32 = 0;
1138 var t2: u64 = std.time.milliTimestamp();
1138 var t2: u64 = @bitCast(u64, std.time.milliTimestamp());
11391139 var t0 = t2;
11401140 var t1 = t2 - retry_interval;
11411141
11421142 var servfail_retry: usize = undefined;
11431143
1144 outer: while (t2 - t0 < timeout) : (t2 = std.time.milliTimestamp()) {
1144 outer: while (t2 - t0 < timeout) : (t2 = @bitCast(u64, std.time.milliTimestamp())) {
11451145 if (t2 - t1 >= retry_interval) {
11461146 // Query all configured nameservers in parallel
11471147 var i: usize = 0;
lib/std/os.zig+19
......@@ -3880,6 +3880,8 @@ pub fn dl_iterate_phdr(
38803880
38813881pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError;
38823882
3883/// TODO: change this to return the timespec as a return value
3884/// TODO: look into making clk_id an enum
38833885pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {
38843886 if (std.Target.current.os.tag == .wasi) {
38853887 var ts: timestamp_t = undefined;
......@@ -3895,6 +3897,23 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {
38953897 }
38963898 return;
38973899 }
3900 if (std.Target.current.os.tag == .windows) {
3901 if (clk_id == CLOCK_REALTIME) {
3902 var ft: windows.FILETIME = undefined;
3903 windows.kernel32.GetSystemTimeAsFileTime(&ft);
3904 // FileTime has a granularity of 100 nanoseconds and uses the NTFS/Windows epoch.
3905 const ft64 = (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
3906 const ft_per_s = std.time.ns_per_s / 100;
3907 tp.* = .{
3908 .tv_sec = @intCast(i64, ft64 / ft_per_s) + std.time.epoch.windows,
3909 .tv_nsec = @intCast(c_long, ft64 % ft_per_s) * 100,
3910 };
3911 return;
3912 } else {
3913 // TODO POSIX implementation of CLOCK_MONOTONIC on Windows.
3914 return error.UnsupportedClock;
3915 }
3916 }
38983917
38993918 switch (errno(system.clock_gettime(clk_id, tp))) {
39003919 0 => return,
lib/std/os/bits/darwin.zig+9
......@@ -1456,3 +1456,12 @@ pub const POLLHUP = 0x010;
14561456pub const POLLNVAL = 0x020;
14571457
14581458pub const POLLSTANDARD = POLLIN | POLLPRI | POLLOUT | POLLRDNORM | POLLRDBAND | POLLWRBAND | POLLERR | POLLHUP | POLLNVAL;
1459
1460pub const CLOCK_REALTIME = 0;
1461pub const CLOCK_MONOTONIC = 6;
1462pub const CLOCK_MONOTONIC_RAW = 4;
1463pub const CLOCK_MONOTONIC_RAW_APPROX = 5;
1464pub const CLOCK_UPTIME_RAW = 8;
1465pub const CLOCK_UPTIME_RAW_APPROX = 9;
1466pub const CLOCK_PROCESS_CPUTIME_ID = 12;
1467pub const CLOCK_THREAD_CPUTIME_ID = 16;
lib/std/os/windows.zig+7-7
......@@ -1193,23 +1193,23 @@ pub fn peb() *PEB {
11931193/// Universal Time (UTC).
11941194/// This function returns the number of nanoseconds since the canonical epoch,
11951195/// which is the POSIX one (Jan 01, 1970 AD).
1196pub fn fromSysTime(hns: i64) i64 {
1197 const adjusted_epoch = hns + std.time.epoch.windows * (std.time.ns_per_s / 100);
1196pub fn fromSysTime(hns: i64) i128 {
1197 const adjusted_epoch = @as(i128, hns + std.time.epoch.windows) * (std.time.ns_per_s / 100);
11981198 return adjusted_epoch * 100;
11991199}
12001200
1201pub fn toSysTime(ns: i64) i64 {
1201pub fn toSysTime(ns: i128) i64 {
12021202 const hns = @divFloor(ns, 100);
1203 return hns - std.time.epoch.windows * (std.time.ns_per_s / 100);
1203 return @intCast(i64, hns) - std.time.epoch.windows * (std.time.ns_per_s / 100);
12041204}
12051205
1206pub fn fileTimeToNanoSeconds(ft: FILETIME) i64 {
1207 const hns = @bitCast(i64, (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime);
1206pub fn fileTimeToNanoSeconds(ft: FILETIME) i128 {
1207 const hns = (@as(i64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
12081208 return fromSysTime(hns);
12091209}
12101210
12111211/// Converts a number of nanoseconds since the POSIX epoch to a Windows FILETIME.
1212pub fn nanoSecondsToFileTime(ns: i64) FILETIME {
1212pub fn nanoSecondsToFileTime(ns: i128) FILETIME {
12131213 const adjusted = @bitCast(u64, toSysTime(ns));
12141214 return FILETIME{
12151215 .dwHighDateTime = @truncate(u32, adjusted >> 32),
lib/std/progress.zig+8-8
......@@ -31,10 +31,10 @@ pub const Progress = struct {
3131 output_buffer: [100]u8 = undefined,
3232
3333 /// How many nanoseconds between writing updates to the terminal.
34 refresh_rate_ns: u64 = 50 * std.time.millisecond,
34 refresh_rate_ns: u64 = 50 * std.time.ns_per_ms,
3535
3636 /// How many nanoseconds to keep the output hidden
37 initial_delay_ns: u64 = 500 * std.time.millisecond,
37 initial_delay_ns: u64 = 500 * std.time.ns_per_ms,
3838
3939 done: bool = true,
4040
......@@ -282,24 +282,24 @@ test "basic functionality" {
282282 next_sub_task = (next_sub_task + 1) % sub_task_names.len;
283283
284284 node.completeOne();
285 std.time.sleep(5 * std.time.millisecond);
285 std.time.sleep(5 * std.time.ns_per_ms);
286286 node.completeOne();
287287 node.completeOne();
288 std.time.sleep(5 * std.time.millisecond);
288 std.time.sleep(5 * std.time.ns_per_ms);
289289 node.completeOne();
290290 node.completeOne();
291 std.time.sleep(5 * std.time.millisecond);
291 std.time.sleep(5 * std.time.ns_per_ms);
292292
293293 node.end();
294294
295 std.time.sleep(5 * std.time.millisecond);
295 std.time.sleep(5 * std.time.ns_per_ms);
296296 }
297297 {
298298 var node = root_node.start("this is a really long name designed to activate the truncation code. let's find out if it works", null);
299299 node.activate();
300 std.time.sleep(10 * std.time.millisecond);
300 std.time.sleep(10 * std.time.ns_per_ms);
301301 progress.refresh();
302 std.time.sleep(10 * std.time.millisecond);
302 std.time.sleep(10 * std.time.ns_per_ms);
303303 node.end();
304304 }
305305}
lib/std/reset_event.zig+5-5
......@@ -152,15 +152,15 @@ const PosixEvent = struct {
152152 if (comptime std.Target.current.isDarwin()) {
153153 var tv: os.darwin.timeval = undefined;
154154 assert(os.darwin.gettimeofday(&tv, null) == 0);
155 timeout_abs += @intCast(u64, tv.tv_sec) * time.second;
156 timeout_abs += @intCast(u64, tv.tv_usec) * time.microsecond;
155 timeout_abs += @intCast(u64, tv.tv_sec) * time.ns_per_s;
156 timeout_abs += @intCast(u64, tv.tv_usec) * time.us_per_s;
157157 } else {
158158 os.clock_gettime(os.CLOCK_REALTIME, &ts) catch unreachable;
159 timeout_abs += @intCast(u64, ts.tv_sec) * time.second;
159 timeout_abs += @intCast(u64, ts.tv_sec) * time.ns_per_s;
160160 timeout_abs += @intCast(u64, ts.tv_nsec);
161161 }
162 ts.tv_sec = @intCast(@TypeOf(ts.tv_sec), @divFloor(timeout_abs, time.second));
163 ts.tv_nsec = @intCast(@TypeOf(ts.tv_nsec), @mod(timeout_abs, time.second));
162 ts.tv_sec = @intCast(@TypeOf(ts.tv_sec), @divFloor(timeout_abs, time.ns_per_s));
163 ts.tv_nsec = @intCast(@TypeOf(ts.tv_nsec), @mod(timeout_abs, time.ns_per_s));
164164 }
165165
166166 while (!self.is_set) {
lib/std/time.zig+101-117
......@@ -4,16 +4,14 @@ const assert = std.debug.assert;
44const testing = std.testing;
55const os = std.os;
66const math = std.math;
7const is_windows = std.Target.current.os.tag == .windows;
78
89pub const epoch = @import("time/epoch.zig");
910
10const is_windows = std.Target.current.os.tag == .windows;
11
1211/// Spurious wakeups are possible and no precision of timing is guaranteed.
1312/// TODO integrate with evented I/O
1413pub fn sleep(nanoseconds: u64) void {
1514 if (is_windows) {
16 const ns_per_ms = ns_per_s / ms_per_s;
1715 const big_ms_from_ns = nanoseconds / ns_per_ms;
1816 const ms = math.cast(os.windows.DWORD, big_ms_from_ns) catch math.maxInt(os.windows.DWORD);
1917 os.windows.kernel32.Sleep(ms);
......@@ -49,105 +47,78 @@ pub fn sleep(nanoseconds: u64) void {
4947 std.os.nanosleep(s, ns);
5048}
5149
52/// Get the posix timestamp, UTC, in seconds
53/// TODO audit this function. is it possible to return an error?
54pub fn timestamp() u64 {
55 return @divFloor(milliTimestamp(), ms_per_s);
50/// Get a calendar timestamp, in seconds, relative to UTC 1970-01-01.
51/// Precision of timing depends on the hardware and operating system.
52/// The return value is signed because it is possible to have a date that is
53/// before the epoch.
54/// See `std.os.clock_gettime` for a POSIX timestamp.
55pub fn timestamp() i64 {
56 return @divFloor(milliTimestamp(), ns_per_s);
5657}
5758
58/// Get the posix timestamp, UTC, in milliseconds
59/// TODO audit this function. is it possible to return an error?
60pub fn milliTimestamp() u64 {
61 return @divFloor(nanoTimestamp(), millisecond);
59/// Get a calendar timestamp, in milliseconds, relative to UTC 1970-01-01.
60/// Precision of timing depends on the hardware and operating system.
61/// The return value is signed because it is possible to have a date that is
62/// before the epoch.
63/// See `std.os.clock_gettime` for a POSIX timestamp.
64pub fn milliTimestamp() i64 {
65 return @intCast(i64, @divFloor(nanoTimestamp(), ns_per_ms));
6266}
6367
64const DarwinTimeStart = struct {
65 timebase: os.darwin.mach_timebase_info_data,
66 inittime: os.darwin.timespec,
67 initclock: u64,
68};
69
70var global_timestart: DarwinTimeStart = undefined;
71var init_global_timestart_once = std.once(init_global_timestart);
72
73pub fn init_global_timestart() void {
74 var micro: os.darwin.timeval = undefined;
75 var timestart: DarwinTimeStart = undefined;
76
77 os.darwin.mach_timebase_info(&timestart.timebase);
78
79 const err = os.darwin.gettimeofday(&micro, null);
80 assert(err == 0);
81
82 timestart.initclock = os.darwin.mach_absolute_time();
83 timestart.inittime.tv_sec = micro.tv_sec;
84 timestart.inittime.tv_nsec = micro.tv_usec * 1000;
85
86 global_timestart = timestart;
87}
88
89/// Get the posix timestamp, UTC, in nanoseconds
90///
91/// On windows this only has a granularity of 100 nanoseconds.
92///
93/// TODO audit this function. is it possible to return an error?
94pub fn nanoTimestamp() u64 {
68/// Get a calendar timestamp, in nanoseconds, relative to UTC 1970-01-01.
69/// Precision of timing depends on the hardware and operating system.
70/// On Windows this has a maximum granularity of 100 nanoseconds.
71/// The return value is signed because it is possible to have a date that is
72/// before the epoch.
73/// See `std.os.clock_gettime` for a POSIX timestamp.
74pub fn nanoTimestamp() i128 {
9575 if (is_windows) {
96 //FileTime has a granularity of 100 nanoseconds
97 // and uses the NTFS/Windows epoch
76 // FileTime has a granularity of 100 nanoseconds and uses the NTFS/Windows epoch,
77 // which is 1601-01-01.
78 const epoch_adj = epoch.windows * (ns_per_s / 100);
9879 var ft: os.windows.FILETIME = undefined;
9980 os.windows.kernel32.GetSystemTimeAsFileTime(&ft);
100 const ns_per_hns = 100;
101 const epoch_adj = epoch.windows * ns_per_s;
102
10381 const ft64 = (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
104 return (ft64 * ns_per_hns) - -epoch_adj;
82 return @as(i128, @bitCast(i64, ft64) + epoch_adj) * 100;
10583 }
10684 if (builtin.os.tag == .wasi and !builtin.link_libc) {
10785 var ns: os.wasi.timestamp_t = undefined;
108
109 // TODO: Verify that precision is ignored
11086 const err = os.wasi.clock_time_get(os.wasi.CLOCK_REALTIME, 1, &ns);
11187 assert(err == os.wasi.ESUCCESS);
112
11388 return ns;
11489 }
115 if (comptime std.Target.current.isDarwin()) {
116 // https://stackoverflow.com/a/21352348
117 init_global_timestart_once.call();
118
119 const clock: u64 = os.darwin.mach_absolute_time() - global_timestart.initclock;
120 const nano = @divFloor(clock * @as(u64, global_timestart.timebase.numer), @as(u64, global_timestart.timebase.denom));
121
122 const tv_sec_nsec = @intCast(u64, global_timestart.inittime.tv_sec) * ns_per_s;
123 const tv_nsec = @intCast(u64, global_timestart.inittime.tv_nsec);
124
125 return tv_sec_nsec + tv_nsec + nano;
126 }
12790 var ts: os.timespec = undefined;
128 //From what I can tell there's no reason clock_gettime
129 // should ever fail for us with CLOCK_REALTIME,
130 // seccomp aside.
131 os.clock_gettime(os.CLOCK_REALTIME, &ts) catch unreachable;
132 const sec_ns = @intCast(u64, ts.tv_sec) * ns_per_s;
133 return sec_ns + @intCast(u64, ts.tv_nsec);
91 os.clock_gettime(os.CLOCK_REALTIME, &ts) catch |err| switch (err) {
92 error.UnsupportedClock, error.Unexpected => return 0, // "Precision of timing depends on hardware and OS".
93 };
94 return (@as(i128, ts.tv_sec) * ns_per_s) + ts.tv_nsec;
13495}
13596
136/// Multiples of a base unit (nanoseconds)
137pub const nanosecond = 1;
138pub const microsecond = 1000 * nanosecond;
139pub const millisecond = 1000 * microsecond;
140pub const second = 1000 * millisecond;
141pub const minute = 60 * second;
142pub const hour = 60 * minute;
143
144/// Divisions of a second
145pub const ns_per_s = 1000000000;
146pub const us_per_s = 1000000;
97// Divisions of a nanosecond.
98pub const ns_per_us = 1000;
99pub const ns_per_ms = 1000 * ns_per_us;
100pub const ns_per_s = 1000 * ns_per_ms;
101pub const ns_per_min = 60 * ns_per_s;
102pub const ns_per_hour = 60 * ns_per_min;
103pub const ns_per_day = 24 * ns_per_hour;
104pub const ns_per_week = 7 * ns_per_day;
105
106// Divisions of a microsecond.
107pub const us_per_ms = 1000;
108pub const us_per_s = 1000 * us_per_ms;
109pub const us_per_min = 60 * us_per_s;
110pub const us_per_hour = 60 * us_per_min;
111pub const us_per_day = 24 * us_per_hour;
112pub const us_per_week = 7 * us_per_day;
113
114// Divisions of a millisecond.
147115pub const ms_per_s = 1000;
148pub const cs_per_s = 100;
116pub const ms_per_min = 60 * ms_per_s;
117pub const ms_per_hour = 60 * ms_per_min;
118pub const ms_per_day = 24 * ms_per_hour;
119pub const ms_per_week = 7 * ms_per_day;
149120
150/// Common time divisions
121// Divisions of a second.
151122pub const s_per_min = 60;
152123pub const s_per_hour = s_per_min * 60;
153124pub const s_per_day = s_per_hour * 24;
......@@ -155,12 +126,12 @@ pub const s_per_week = s_per_day * 7;
155126
156127/// A monotonic high-performance timer.
157128/// Timer.start() must be called to initialize the struct, which captures
158/// the counter frequency on windows and darwin, records the resolution,
159/// and gives the user an opportunity to check for the existnece of
160/// monotonic clocks without forcing them to check for error on each read.
129/// the counter frequency on windows and darwin, records the resolution,
130/// and gives the user an opportunity to check for the existnece of
131/// monotonic clocks without forcing them to check for error on each read.
161132/// .resolution is in nanoseconds on all platforms but .start_time's meaning
162/// depends on the OS. On Windows and Darwin it is a hardware counter
163/// value that requires calculation to convert to a meaninful unit.
133/// depends on the OS. On Windows and Darwin it is a hardware counter
134/// value that requires calculation to convert to a meaninful unit.
164135pub const Timer = struct {
165136 ///if we used resolution's value when performing the
166137 /// performance counter calc on windows/darwin, it would
......@@ -173,43 +144,58 @@ pub const Timer = struct {
173144 resolution: u64,
174145 start_time: u64,
175146
176 const Error = error{TimerUnsupported};
147 pub const Error = error{TimerUnsupported};
177148
178 ///At some point we may change our minds on RAW, but for now we're
179 /// sticking with posix standard MONOTONIC. For more information, see:
180 /// https://github.com/ziglang/zig/pull/933
149 /// At some point we may change our minds on RAW, but for now we're
150 /// sticking with posix standard MONOTONIC. For more information, see:
151 /// https://github.com/ziglang/zig/pull/933
181152 const monotonic_clock_id = os.CLOCK_MONOTONIC;
153
182154 /// Initialize the timer structure.
183 //This gives us an opportunity to grab the counter frequency in windows.
184 //On Windows: QueryPerformanceCounter will succeed on anything >= XP/2000.
185 //On Posix: CLOCK_MONOTONIC will only fail if the monotonic counter is not
186 // supported, or if the timespec pointer is out of bounds, which should be
187 // impossible here barring cosmic rays or other such occurrences of
188 // incredibly bad luck.
189 //On Darwin: This cannot fail, as far as I am able to tell.
155 /// Can only fail when running in a hostile environment that intentionally injects
156 /// error values into syscalls, such as using seccomp on Linux to intercept
157 /// `clock_gettime`.
190158 pub fn start() Error!Timer {
191 var self: Timer = undefined;
192
159 // This gives us an opportunity to grab the counter frequency in windows.
160 // On Windows: QueryPerformanceCounter will succeed on anything >= XP/2000.
161 // On Posix: CLOCK_MONOTONIC will only fail if the monotonic counter is not
162 // supported, or if the timespec pointer is out of bounds, which should be
163 // impossible here barring cosmic rays or other such occurrences of
164 // incredibly bad luck.
165 // On Darwin: This cannot fail, as far as I am able to tell.
193166 if (is_windows) {
194 self.frequency = os.windows.QueryPerformanceFrequency();
195 self.resolution = @divFloor(ns_per_s, self.frequency);
196 self.start_time = os.windows.QueryPerformanceCounter();
167 const freq = os.windows.QueryPerformanceFrequency();
168 return Timer{
169 .frequency = freq,
170 .resolution = @divFloor(ns_per_s, freq),
171 .start_time = os.windows.QueryPerformanceCounter(),
172 };
197173 } else if (comptime std.Target.current.isDarwin()) {
198 os.darwin.mach_timebase_info(&self.frequency);
199 self.resolution = @divFloor(self.frequency.numer, self.frequency.denom);
200 self.start_time = os.darwin.mach_absolute_time();
174 var freq: os.darwin.mach_timebase_info_data = undefined;
175 os.darwin.mach_timebase_info(&freq);
176
177 return Timer{
178 .frequency = freq,
179 .resolution = @divFloor(freq.numer, freq.denom),
180 .start_time = os.darwin.mach_absolute_time(),
181 };
201182 } else {
202 //On Linux, seccomp can do arbitrary things to our ability to call
203 // syscalls, including return any errno value it wants and
204 // inconsistently throwing errors. Since we can't account for
205 // abuses of seccomp in a reasonable way, we'll assume that if
206 // seccomp is going to block us it will at least do so consistently
207 var ts: os.timespec = undefined;
208 os.clock_getres(monotonic_clock_id, &ts) catch return error.TimerUnsupported;
209 self.resolution = @intCast(u64, ts.tv_sec) * @as(u64, ns_per_s) + @intCast(u64, ts.tv_nsec);
183 // On Linux, seccomp can do arbitrary things to our ability to call
184 // syscalls, including return any errno value it wants and
185 // inconsistently throwing errors. Since we can't account for
186 // abuses of seccomp in a reasonable way, we'll assume that if
187 // seccomp is going to block us it will at least do so consistently
188 var res: os.timespec = undefined;
189 os.clock_getres(monotonic_clock_id, &res) catch return error.TimerUnsupported;
210190
191 var ts: os.timespec = undefined;
211192 os.clock_gettime(monotonic_clock_id, &ts) catch return error.TimerUnsupported;
212 self.start_time = @intCast(u64, ts.tv_sec) * @as(u64, ns_per_s) + @intCast(u64, ts.tv_nsec);
193
194 return Timer{
195 .resolution = @intCast(u64, res.tv_sec) * ns_per_s + @intCast(u64, res.tv_nsec),
196 .start_time = @intCast(u64, ts.tv_sec) * ns_per_s + @intCast(u64, ts.tv_nsec),
197 .frequency = {},
198 };
213199 }
214200
215201 return self;
......@@ -262,7 +248,6 @@ test "sleep" {
262248}
263249
264250test "timestamp" {
265 const ns_per_ms = (ns_per_s / ms_per_s);
266251 const margin = ns_per_ms * 50;
267252
268253 const time_0 = milliTimestamp();
......@@ -273,7 +258,6 @@ test "timestamp" {
273258}
274259
275260test "Timer" {
276 const ns_per_ms = (ns_per_s / ms_per_s);
277261 const margin = ns_per_ms * 150;
278262
279263 var timer = try Timer.start();
lib/std/time/epoch.zig+23-12
......@@ -1,15 +1,26 @@
1/// Epoch reference times in terms of their difference from
2/// posix epoch in seconds.
3pub const posix = 0; //Jan 01, 1970 AD
4pub const dos = 315532800; //Jan 01, 1980 AD
5pub const ios = 978307200; //Jan 01, 2001 AD
6pub const openvms = -3506716800; //Nov 17, 1858 AD
7pub const zos = -2208988800; //Jan 01, 1900 AD
8pub const windows = -11644473600; //Jan 01, 1601 AD
9pub const amiga = 252460800; //Jan 01, 1978 AD
10pub const pickos = -63244800; //Dec 31, 1967 AD
11pub const gps = 315964800; //Jan 06, 1980 AD
12pub const clr = -62135769600; //Jan 01, 0001 AD
1//! Epoch reference times in terms of their difference from
2//! UTC 1970-01-01 in seconds.
3
4/// Jan 01, 1970 AD
5pub const posix = 0;
6/// Jan 01, 1980 AD
7pub const dos = 315532800;
8/// Jan 01, 2001 AD
9pub const ios = 978307200;
10/// Nov 17, 1858 AD
11pub const openvms = -3506716800;
12/// Jan 01, 1900 AD
13pub const zos = -2208988800;
14/// Jan 01, 1601 AD
15pub const windows = -11644473600;
16/// Jan 01, 1978 AD
17pub const amiga = 252460800;
18/// Dec 31, 1967 AD
19pub const pickos = -63244800;
20/// Jan 06, 1980 AD
21pub const gps = 315964800;
22/// Jan 01, 0001 AD
23pub const clr = -62135769600;
1324
1425pub const unix = posix;
1526pub const android = posix;