mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
commit
c693c3ae50
@ -122,7 +122,7 @@ test "std.event.Batch" {
|
||||
}
|
||||
|
||||
fn sleepALittle(count: *usize) void {
|
||||
std.time.sleep(1 * std.time.millisecond);
|
||||
std.time.sleep(1 * std.time.ns_per_ms);
|
||||
_ = @atomicRmw(usize, count, .Add, 1, .SeqCst);
|
||||
}
|
||||
|
||||
|
||||
@ -145,7 +145,7 @@ fn testGroup(allocator: *Allocator) callconv(.Async) void {
|
||||
testing.expectError(error.ItBroke, another.wait());
|
||||
}
|
||||
fn sleepALittle(count: *usize) callconv(.Async) void {
|
||||
std.time.sleep(1 * std.time.millisecond);
|
||||
std.time.sleep(1 * std.time.ns_per_ms);
|
||||
_ = @atomicRmw(usize, count, .Add, 1, .SeqCst);
|
||||
}
|
||||
fn increaseByTen(count: *usize) callconv(.Async) void {
|
||||
|
||||
@ -457,7 +457,7 @@ pub const Loop = struct {
|
||||
=> {
|
||||
// Even poll() didn't work. The best we can do now is sleep for a
|
||||
// small duration and then hope that something changed.
|
||||
std.time.sleep(1 * std.time.millisecond);
|
||||
std.time.sleep(1 * std.time.ns_per_ms);
|
||||
},
|
||||
};
|
||||
resume @frame();
|
||||
|
||||
@ -227,14 +227,12 @@ pub const File = struct {
|
||||
size: u64,
|
||||
mode: Mode,
|
||||
|
||||
/// access time in nanoseconds
|
||||
atime: i64,
|
||||
|
||||
/// last modification time in nanoseconds
|
||||
mtime: i64,
|
||||
|
||||
/// creation time in nanoseconds
|
||||
ctime: i64,
|
||||
/// Access time in nanoseconds, relative to UTC 1970-01-01.
|
||||
atime: i128,
|
||||
/// Last modification time in nanoseconds, relative to UTC 1970-01-01.
|
||||
mtime: i128,
|
||||
/// Creation time in nanoseconds, relative to UTC 1970-01-01.
|
||||
ctime: i128,
|
||||
};
|
||||
|
||||
pub const StatError = os.FStatError;
|
||||
@ -270,9 +268,9 @@ pub const File = struct {
|
||||
.inode = st.ino,
|
||||
.size = @bitCast(u64, st.size),
|
||||
.mode = st.mode,
|
||||
.atime = @as(i64, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec,
|
||||
.mtime = @as(i64, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec,
|
||||
.ctime = @as(i64, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec,
|
||||
.atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec,
|
||||
.mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec,
|
||||
.ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec,
|
||||
};
|
||||
}
|
||||
|
||||
@ -286,9 +284,9 @@ pub const File = struct {
|
||||
pub fn updateTimes(
|
||||
self: File,
|
||||
/// access timestamp in nanoseconds
|
||||
atime: i64,
|
||||
atime: i128,
|
||||
/// last modification timestamp in nanoseconds
|
||||
mtime: i64,
|
||||
mtime: i128,
|
||||
) UpdateTimesError!void {
|
||||
if (builtin.os.tag == .windows) {
|
||||
const atime_ft = windows.nanoSecondsToFileTime(atime);
|
||||
|
||||
@ -10,7 +10,7 @@ test "openSelfExe" {
|
||||
self_exe_file.close();
|
||||
}
|
||||
|
||||
const FILE_LOCK_TEST_SLEEP_TIME = 5 * std.time.millisecond;
|
||||
const FILE_LOCK_TEST_SLEEP_TIME = 5 * std.time.ns_per_ms;
|
||||
|
||||
test "open file with exclusive nonblocking lock twice" {
|
||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
||||
@ -142,8 +142,8 @@ const FileLockTestContext = struct {
|
||||
|
||||
// Output variables
|
||||
err: ?(File.OpenError || std.os.ReadError) = null,
|
||||
start_time: u64 = 0,
|
||||
end_time: u64 = 0,
|
||||
start_time: i64 = 0,
|
||||
end_time: i64 = 0,
|
||||
bytes_read: ?usize = null,
|
||||
|
||||
fn overlaps(self: *const @This(), other: *const @This()) bool {
|
||||
|
||||
@ -1135,13 +1135,13 @@ fn resMSendRc(
|
||||
}};
|
||||
const retry_interval = timeout / attempts;
|
||||
var next: u32 = 0;
|
||||
var t2: u64 = std.time.milliTimestamp();
|
||||
var t2: u64 = @bitCast(u64, std.time.milliTimestamp());
|
||||
var t0 = t2;
|
||||
var t1 = t2 - retry_interval;
|
||||
|
||||
var servfail_retry: usize = undefined;
|
||||
|
||||
outer: while (t2 - t0 < timeout) : (t2 = std.time.milliTimestamp()) {
|
||||
outer: while (t2 - t0 < timeout) : (t2 = @bitCast(u64, std.time.milliTimestamp())) {
|
||||
if (t2 - t1 >= retry_interval) {
|
||||
// Query all configured nameservers in parallel
|
||||
var i: usize = 0;
|
||||
|
||||
@ -3880,6 +3880,8 @@ pub fn dl_iterate_phdr(
|
||||
|
||||
pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError;
|
||||
|
||||
/// TODO: change this to return the timespec as a return value
|
||||
/// TODO: look into making clk_id an enum
|
||||
pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {
|
||||
if (std.Target.current.os.tag == .wasi) {
|
||||
var ts: timestamp_t = undefined;
|
||||
@ -3895,6 +3897,23 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (std.Target.current.os.tag == .windows) {
|
||||
if (clk_id == CLOCK_REALTIME) {
|
||||
var ft: windows.FILETIME = undefined;
|
||||
windows.kernel32.GetSystemTimeAsFileTime(&ft);
|
||||
// FileTime has a granularity of 100 nanoseconds and uses the NTFS/Windows epoch.
|
||||
const ft64 = (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
||||
const ft_per_s = std.time.ns_per_s / 100;
|
||||
tp.* = .{
|
||||
.tv_sec = @intCast(i64, ft64 / ft_per_s) + std.time.epoch.windows,
|
||||
.tv_nsec = @intCast(c_long, ft64 % ft_per_s) * 100,
|
||||
};
|
||||
return;
|
||||
} else {
|
||||
// TODO POSIX implementation of CLOCK_MONOTONIC on Windows.
|
||||
return error.UnsupportedClock;
|
||||
}
|
||||
}
|
||||
|
||||
switch (errno(system.clock_gettime(clk_id, tp))) {
|
||||
0 => return,
|
||||
|
||||
@ -1456,3 +1456,12 @@ pub const POLLHUP = 0x010;
|
||||
pub const POLLNVAL = 0x020;
|
||||
|
||||
pub const POLLSTANDARD = POLLIN | POLLPRI | POLLOUT | POLLRDNORM | POLLRDBAND | POLLWRBAND | POLLERR | POLLHUP | POLLNVAL;
|
||||
|
||||
pub const CLOCK_REALTIME = 0;
|
||||
pub const CLOCK_MONOTONIC = 6;
|
||||
pub const CLOCK_MONOTONIC_RAW = 4;
|
||||
pub const CLOCK_MONOTONIC_RAW_APPROX = 5;
|
||||
pub const CLOCK_UPTIME_RAW = 8;
|
||||
pub const CLOCK_UPTIME_RAW_APPROX = 9;
|
||||
pub const CLOCK_PROCESS_CPUTIME_ID = 12;
|
||||
pub const CLOCK_THREAD_CPUTIME_ID = 16;
|
||||
|
||||
@ -1193,23 +1193,23 @@ pub fn peb() *PEB {
|
||||
/// Universal Time (UTC).
|
||||
/// This function returns the number of nanoseconds since the canonical epoch,
|
||||
/// which is the POSIX one (Jan 01, 1970 AD).
|
||||
pub fn fromSysTime(hns: i64) i64 {
|
||||
const adjusted_epoch = hns + std.time.epoch.windows * (std.time.ns_per_s / 100);
|
||||
pub fn fromSysTime(hns: i64) i128 {
|
||||
const adjusted_epoch = @as(i128, hns + std.time.epoch.windows) * (std.time.ns_per_s / 100);
|
||||
return adjusted_epoch * 100;
|
||||
}
|
||||
|
||||
pub fn toSysTime(ns: i64) i64 {
|
||||
pub fn toSysTime(ns: i128) i64 {
|
||||
const hns = @divFloor(ns, 100);
|
||||
return hns - std.time.epoch.windows * (std.time.ns_per_s / 100);
|
||||
return @intCast(i64, hns) - std.time.epoch.windows * (std.time.ns_per_s / 100);
|
||||
}
|
||||
|
||||
pub fn fileTimeToNanoSeconds(ft: FILETIME) i64 {
|
||||
const hns = @bitCast(i64, (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime);
|
||||
pub fn fileTimeToNanoSeconds(ft: FILETIME) i128 {
|
||||
const hns = (@as(i64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
||||
return fromSysTime(hns);
|
||||
}
|
||||
|
||||
/// Converts a number of nanoseconds since the POSIX epoch to a Windows FILETIME.
|
||||
pub fn nanoSecondsToFileTime(ns: i64) FILETIME {
|
||||
pub fn nanoSecondsToFileTime(ns: i128) FILETIME {
|
||||
const adjusted = @bitCast(u64, toSysTime(ns));
|
||||
return FILETIME{
|
||||
.dwHighDateTime = @truncate(u32, adjusted >> 32),
|
||||
|
||||
@ -31,10 +31,10 @@ pub const Progress = struct {
|
||||
output_buffer: [100]u8 = undefined,
|
||||
|
||||
/// How many nanoseconds between writing updates to the terminal.
|
||||
refresh_rate_ns: u64 = 50 * std.time.millisecond,
|
||||
refresh_rate_ns: u64 = 50 * std.time.ns_per_ms,
|
||||
|
||||
/// How many nanoseconds to keep the output hidden
|
||||
initial_delay_ns: u64 = 500 * std.time.millisecond,
|
||||
initial_delay_ns: u64 = 500 * std.time.ns_per_ms,
|
||||
|
||||
done: bool = true,
|
||||
|
||||
@ -282,24 +282,24 @@ test "basic functionality" {
|
||||
next_sub_task = (next_sub_task + 1) % sub_task_names.len;
|
||||
|
||||
node.completeOne();
|
||||
std.time.sleep(5 * std.time.millisecond);
|
||||
std.time.sleep(5 * std.time.ns_per_ms);
|
||||
node.completeOne();
|
||||
node.completeOne();
|
||||
std.time.sleep(5 * std.time.millisecond);
|
||||
std.time.sleep(5 * std.time.ns_per_ms);
|
||||
node.completeOne();
|
||||
node.completeOne();
|
||||
std.time.sleep(5 * std.time.millisecond);
|
||||
std.time.sleep(5 * std.time.ns_per_ms);
|
||||
|
||||
node.end();
|
||||
|
||||
std.time.sleep(5 * std.time.millisecond);
|
||||
std.time.sleep(5 * std.time.ns_per_ms);
|
||||
}
|
||||
{
|
||||
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);
|
||||
node.activate();
|
||||
std.time.sleep(10 * std.time.millisecond);
|
||||
std.time.sleep(10 * std.time.ns_per_ms);
|
||||
progress.refresh();
|
||||
std.time.sleep(10 * std.time.millisecond);
|
||||
std.time.sleep(10 * std.time.ns_per_ms);
|
||||
node.end();
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,15 +152,15 @@ const PosixEvent = struct {
|
||||
if (comptime std.Target.current.isDarwin()) {
|
||||
var tv: os.darwin.timeval = undefined;
|
||||
assert(os.darwin.gettimeofday(&tv, null) == 0);
|
||||
timeout_abs += @intCast(u64, tv.tv_sec) * time.second;
|
||||
timeout_abs += @intCast(u64, tv.tv_usec) * time.microsecond;
|
||||
timeout_abs += @intCast(u64, tv.tv_sec) * time.ns_per_s;
|
||||
timeout_abs += @intCast(u64, tv.tv_usec) * time.us_per_s;
|
||||
} else {
|
||||
os.clock_gettime(os.CLOCK_REALTIME, &ts) catch unreachable;
|
||||
timeout_abs += @intCast(u64, ts.tv_sec) * time.second;
|
||||
timeout_abs += @intCast(u64, ts.tv_sec) * time.ns_per_s;
|
||||
timeout_abs += @intCast(u64, ts.tv_nsec);
|
||||
}
|
||||
ts.tv_sec = @intCast(@TypeOf(ts.tv_sec), @divFloor(timeout_abs, time.second));
|
||||
ts.tv_nsec = @intCast(@TypeOf(ts.tv_nsec), @mod(timeout_abs, time.second));
|
||||
ts.tv_sec = @intCast(@TypeOf(ts.tv_sec), @divFloor(timeout_abs, time.ns_per_s));
|
||||
ts.tv_nsec = @intCast(@TypeOf(ts.tv_nsec), @mod(timeout_abs, time.ns_per_s));
|
||||
}
|
||||
|
||||
while (!self.is_set) {
|
||||
|
||||
188
lib/std/time.zig
188
lib/std/time.zig
@ -4,16 +4,14 @@ const assert = std.debug.assert;
|
||||
const testing = std.testing;
|
||||
const os = std.os;
|
||||
const math = std.math;
|
||||
const is_windows = std.Target.current.os.tag == .windows;
|
||||
|
||||
pub const epoch = @import("time/epoch.zig");
|
||||
|
||||
const is_windows = std.Target.current.os.tag == .windows;
|
||||
|
||||
/// Spurious wakeups are possible and no precision of timing is guaranteed.
|
||||
/// TODO integrate with evented I/O
|
||||
pub fn sleep(nanoseconds: u64) void {
|
||||
if (is_windows) {
|
||||
const ns_per_ms = ns_per_s / ms_per_s;
|
||||
const big_ms_from_ns = nanoseconds / ns_per_ms;
|
||||
const ms = math.cast(os.windows.DWORD, big_ms_from_ns) catch math.maxInt(os.windows.DWORD);
|
||||
os.windows.kernel32.Sleep(ms);
|
||||
@ -49,69 +47,78 @@ pub fn sleep(nanoseconds: u64) void {
|
||||
std.os.nanosleep(s, ns);
|
||||
}
|
||||
|
||||
/// Get the posix timestamp, UTC, in seconds
|
||||
/// TODO audit this function. is it possible to return an error?
|
||||
pub fn timestamp() u64 {
|
||||
return @divFloor(milliTimestamp(), ms_per_s);
|
||||
/// Get a calendar timestamp, in seconds, relative to UTC 1970-01-01.
|
||||
/// Precision of timing depends on the hardware and operating system.
|
||||
/// The return value is signed because it is possible to have a date that is
|
||||
/// before the epoch.
|
||||
/// See `std.os.clock_gettime` for a POSIX timestamp.
|
||||
pub fn timestamp() i64 {
|
||||
return @divFloor(milliTimestamp(), ns_per_s);
|
||||
}
|
||||
|
||||
/// Get the posix timestamp, UTC, in milliseconds
|
||||
/// TODO audit this function. is it possible to return an error?
|
||||
pub fn milliTimestamp() u64 {
|
||||
/// Get a calendar timestamp, in milliseconds, relative to UTC 1970-01-01.
|
||||
/// Precision of timing depends on the hardware and operating system.
|
||||
/// The return value is signed because it is possible to have a date that is
|
||||
/// before the epoch.
|
||||
/// See `std.os.clock_gettime` for a POSIX timestamp.
|
||||
pub fn milliTimestamp() i64 {
|
||||
return @intCast(i64, @divFloor(nanoTimestamp(), ns_per_ms));
|
||||
}
|
||||
|
||||
/// Get a calendar timestamp, in nanoseconds, relative to UTC 1970-01-01.
|
||||
/// Precision of timing depends on the hardware and operating system.
|
||||
/// On Windows this has a maximum granularity of 100 nanoseconds.
|
||||
/// The return value is signed because it is possible to have a date that is
|
||||
/// before the epoch.
|
||||
/// See `std.os.clock_gettime` for a POSIX timestamp.
|
||||
pub fn nanoTimestamp() i128 {
|
||||
if (is_windows) {
|
||||
//FileTime has a granularity of 100 nanoseconds
|
||||
// and uses the NTFS/Windows epoch
|
||||
// FileTime has a granularity of 100 nanoseconds and uses the NTFS/Windows epoch,
|
||||
// which is 1601-01-01.
|
||||
const epoch_adj = epoch.windows * (ns_per_s / 100);
|
||||
var ft: os.windows.FILETIME = undefined;
|
||||
os.windows.kernel32.GetSystemTimeAsFileTime(&ft);
|
||||
const hns_per_ms = (ns_per_s / 100) / ms_per_s;
|
||||
const epoch_adj = epoch.windows * ms_per_s;
|
||||
|
||||
const ft64 = (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
||||
return @divFloor(ft64, hns_per_ms) - -epoch_adj;
|
||||
return @as(i128, @bitCast(i64, ft64) + epoch_adj) * 100;
|
||||
}
|
||||
if (builtin.os.tag == .wasi and !builtin.link_libc) {
|
||||
var ns: os.wasi.timestamp_t = undefined;
|
||||
|
||||
// TODO: Verify that precision is ignored
|
||||
const err = os.wasi.clock_time_get(os.wasi.CLOCK_REALTIME, 1, &ns);
|
||||
assert(err == os.wasi.ESUCCESS);
|
||||
|
||||
const ns_per_ms = 1000;
|
||||
return @divFloor(ns, ns_per_ms);
|
||||
}
|
||||
if (comptime std.Target.current.isDarwin()) {
|
||||
var tv: os.darwin.timeval = undefined;
|
||||
var err = os.darwin.gettimeofday(&tv, null);
|
||||
assert(err == 0);
|
||||
const sec_ms = tv.tv_sec * ms_per_s;
|
||||
const usec_ms = @divFloor(tv.tv_usec, us_per_s / ms_per_s);
|
||||
return @intCast(u64, sec_ms + usec_ms);
|
||||
return ns;
|
||||
}
|
||||
var ts: os.timespec = undefined;
|
||||
//From what I can tell there's no reason clock_gettime
|
||||
// should ever fail for us with CLOCK_REALTIME,
|
||||
// seccomp aside.
|
||||
os.clock_gettime(os.CLOCK_REALTIME, &ts) catch unreachable;
|
||||
const sec_ms = @intCast(u64, ts.tv_sec) * ms_per_s;
|
||||
const nsec_ms = @divFloor(@intCast(u64, ts.tv_nsec), ns_per_s / ms_per_s);
|
||||
return sec_ms + nsec_ms;
|
||||
os.clock_gettime(os.CLOCK_REALTIME, &ts) catch |err| switch (err) {
|
||||
error.UnsupportedClock, error.Unexpected => return 0, // "Precision of timing depends on hardware and OS".
|
||||
};
|
||||
return (@as(i128, ts.tv_sec) * ns_per_s) + ts.tv_nsec;
|
||||
}
|
||||
|
||||
/// Multiples of a base unit (nanoseconds)
|
||||
pub const nanosecond = 1;
|
||||
pub const microsecond = 1000 * nanosecond;
|
||||
pub const millisecond = 1000 * microsecond;
|
||||
pub const second = 1000 * millisecond;
|
||||
pub const minute = 60 * second;
|
||||
pub const hour = 60 * minute;
|
||||
// Divisions of a nanosecond.
|
||||
pub const ns_per_us = 1000;
|
||||
pub const ns_per_ms = 1000 * ns_per_us;
|
||||
pub const ns_per_s = 1000 * ns_per_ms;
|
||||
pub const ns_per_min = 60 * ns_per_s;
|
||||
pub const ns_per_hour = 60 * ns_per_min;
|
||||
pub const ns_per_day = 24 * ns_per_hour;
|
||||
pub const ns_per_week = 7 * ns_per_day;
|
||||
|
||||
/// Divisions of a second
|
||||
pub const ns_per_s = 1000000000;
|
||||
pub const us_per_s = 1000000;
|
||||
// Divisions of a microsecond.
|
||||
pub const us_per_ms = 1000;
|
||||
pub const us_per_s = 1000 * us_per_ms;
|
||||
pub const us_per_min = 60 * us_per_s;
|
||||
pub const us_per_hour = 60 * us_per_min;
|
||||
pub const us_per_day = 24 * us_per_hour;
|
||||
pub const us_per_week = 7 * us_per_day;
|
||||
|
||||
// Divisions of a millisecond.
|
||||
pub const ms_per_s = 1000;
|
||||
pub const cs_per_s = 100;
|
||||
pub const ms_per_min = 60 * ms_per_s;
|
||||
pub const ms_per_hour = 60 * ms_per_min;
|
||||
pub const ms_per_day = 24 * ms_per_hour;
|
||||
pub const ms_per_week = 7 * ms_per_day;
|
||||
|
||||
/// Common time divisions
|
||||
// Divisions of a second.
|
||||
pub const s_per_min = 60;
|
||||
pub const s_per_hour = s_per_min * 60;
|
||||
pub const s_per_day = s_per_hour * 24;
|
||||
@ -119,12 +126,12 @@ pub const s_per_week = s_per_day * 7;
|
||||
|
||||
/// A monotonic high-performance timer.
|
||||
/// Timer.start() must be called to initialize the struct, which captures
|
||||
/// the counter frequency on windows and darwin, records the resolution,
|
||||
/// and gives the user an opportunity to check for the existnece of
|
||||
/// monotonic clocks without forcing them to check for error on each read.
|
||||
/// the counter frequency on windows and darwin, records the resolution,
|
||||
/// and gives the user an opportunity to check for the existnece of
|
||||
/// monotonic clocks without forcing them to check for error on each read.
|
||||
/// .resolution is in nanoseconds on all platforms but .start_time's meaning
|
||||
/// depends on the OS. On Windows and Darwin it is a hardware counter
|
||||
/// value that requires calculation to convert to a meaninful unit.
|
||||
/// depends on the OS. On Windows and Darwin it is a hardware counter
|
||||
/// value that requires calculation to convert to a meaninful unit.
|
||||
pub const Timer = struct {
|
||||
///if we used resolution's value when performing the
|
||||
/// performance counter calc on windows/darwin, it would
|
||||
@ -137,43 +144,58 @@ pub const Timer = struct {
|
||||
resolution: u64,
|
||||
start_time: u64,
|
||||
|
||||
const Error = error{TimerUnsupported};
|
||||
pub const Error = error{TimerUnsupported};
|
||||
|
||||
///At some point we may change our minds on RAW, but for now we're
|
||||
/// sticking with posix standard MONOTONIC. For more information, see:
|
||||
/// https://github.com/ziglang/zig/pull/933
|
||||
/// At some point we may change our minds on RAW, but for now we're
|
||||
/// sticking with posix standard MONOTONIC. For more information, see:
|
||||
/// https://github.com/ziglang/zig/pull/933
|
||||
const monotonic_clock_id = os.CLOCK_MONOTONIC;
|
||||
|
||||
/// Initialize the timer structure.
|
||||
//This gives us an opportunity to grab the counter frequency in windows.
|
||||
//On Windows: QueryPerformanceCounter will succeed on anything >= XP/2000.
|
||||
//On Posix: CLOCK_MONOTONIC will only fail if the monotonic counter is not
|
||||
// supported, or if the timespec pointer is out of bounds, which should be
|
||||
// impossible here barring cosmic rays or other such occurrences of
|
||||
// incredibly bad luck.
|
||||
//On Darwin: This cannot fail, as far as I am able to tell.
|
||||
/// Can only fail when running in a hostile environment that intentionally injects
|
||||
/// error values into syscalls, such as using seccomp on Linux to intercept
|
||||
/// `clock_gettime`.
|
||||
pub fn start() Error!Timer {
|
||||
var self: Timer = undefined;
|
||||
|
||||
// This gives us an opportunity to grab the counter frequency in windows.
|
||||
// On Windows: QueryPerformanceCounter will succeed on anything >= XP/2000.
|
||||
// On Posix: CLOCK_MONOTONIC will only fail if the monotonic counter is not
|
||||
// supported, or if the timespec pointer is out of bounds, which should be
|
||||
// impossible here barring cosmic rays or other such occurrences of
|
||||
// incredibly bad luck.
|
||||
// On Darwin: This cannot fail, as far as I am able to tell.
|
||||
if (is_windows) {
|
||||
self.frequency = os.windows.QueryPerformanceFrequency();
|
||||
self.resolution = @divFloor(ns_per_s, self.frequency);
|
||||
self.start_time = os.windows.QueryPerformanceCounter();
|
||||
const freq = os.windows.QueryPerformanceFrequency();
|
||||
return Timer{
|
||||
.frequency = freq,
|
||||
.resolution = @divFloor(ns_per_s, freq),
|
||||
.start_time = os.windows.QueryPerformanceCounter(),
|
||||
};
|
||||
} else if (comptime std.Target.current.isDarwin()) {
|
||||
os.darwin.mach_timebase_info(&self.frequency);
|
||||
self.resolution = @divFloor(self.frequency.numer, self.frequency.denom);
|
||||
self.start_time = os.darwin.mach_absolute_time();
|
||||
} else {
|
||||
//On Linux, seccomp can do arbitrary things to our ability to call
|
||||
// syscalls, including return any errno value it wants and
|
||||
// inconsistently throwing errors. Since we can't account for
|
||||
// abuses of seccomp in a reasonable way, we'll assume that if
|
||||
// seccomp is going to block us it will at least do so consistently
|
||||
var ts: os.timespec = undefined;
|
||||
os.clock_getres(monotonic_clock_id, &ts) catch return error.TimerUnsupported;
|
||||
self.resolution = @intCast(u64, ts.tv_sec) * @as(u64, ns_per_s) + @intCast(u64, ts.tv_nsec);
|
||||
var freq: os.darwin.mach_timebase_info_data = undefined;
|
||||
os.darwin.mach_timebase_info(&freq);
|
||||
|
||||
return Timer{
|
||||
.frequency = freq,
|
||||
.resolution = @divFloor(freq.numer, freq.denom),
|
||||
.start_time = os.darwin.mach_absolute_time(),
|
||||
};
|
||||
} else {
|
||||
// On Linux, seccomp can do arbitrary things to our ability to call
|
||||
// syscalls, including return any errno value it wants and
|
||||
// inconsistently throwing errors. Since we can't account for
|
||||
// abuses of seccomp in a reasonable way, we'll assume that if
|
||||
// seccomp is going to block us it will at least do so consistently
|
||||
var res: os.timespec = undefined;
|
||||
os.clock_getres(monotonic_clock_id, &res) catch return error.TimerUnsupported;
|
||||
|
||||
var ts: os.timespec = undefined;
|
||||
os.clock_gettime(monotonic_clock_id, &ts) catch return error.TimerUnsupported;
|
||||
self.start_time = @intCast(u64, ts.tv_sec) * @as(u64, ns_per_s) + @intCast(u64, ts.tv_nsec);
|
||||
|
||||
return Timer{
|
||||
.resolution = @intCast(u64, res.tv_sec) * ns_per_s + @intCast(u64, res.tv_nsec),
|
||||
.start_time = @intCast(u64, ts.tv_sec) * ns_per_s + @intCast(u64, ts.tv_nsec),
|
||||
.frequency = {},
|
||||
};
|
||||
}
|
||||
|
||||
return self;
|
||||
@ -226,7 +248,6 @@ test "sleep" {
|
||||
}
|
||||
|
||||
test "timestamp" {
|
||||
const ns_per_ms = (ns_per_s / ms_per_s);
|
||||
const margin = ns_per_ms * 50;
|
||||
|
||||
const time_0 = milliTimestamp();
|
||||
@ -237,7 +258,6 @@ test "timestamp" {
|
||||
}
|
||||
|
||||
test "Timer" {
|
||||
const ns_per_ms = (ns_per_s / ms_per_s);
|
||||
const margin = ns_per_ms * 150;
|
||||
|
||||
var timer = try Timer.start();
|
||||
|
||||
@ -1,15 +1,26 @@
|
||||
/// Epoch reference times in terms of their difference from
|
||||
/// posix epoch in seconds.
|
||||
pub const posix = 0; //Jan 01, 1970 AD
|
||||
pub const dos = 315532800; //Jan 01, 1980 AD
|
||||
pub const ios = 978307200; //Jan 01, 2001 AD
|
||||
pub const openvms = -3506716800; //Nov 17, 1858 AD
|
||||
pub const zos = -2208988800; //Jan 01, 1900 AD
|
||||
pub const windows = -11644473600; //Jan 01, 1601 AD
|
||||
pub const amiga = 252460800; //Jan 01, 1978 AD
|
||||
pub const pickos = -63244800; //Dec 31, 1967 AD
|
||||
pub const gps = 315964800; //Jan 06, 1980 AD
|
||||
pub const clr = -62135769600; //Jan 01, 0001 AD
|
||||
//! Epoch reference times in terms of their difference from
|
||||
//! UTC 1970-01-01 in seconds.
|
||||
|
||||
/// Jan 01, 1970 AD
|
||||
pub const posix = 0;
|
||||
/// Jan 01, 1980 AD
|
||||
pub const dos = 315532800;
|
||||
/// Jan 01, 2001 AD
|
||||
pub const ios = 978307200;
|
||||
/// Nov 17, 1858 AD
|
||||
pub const openvms = -3506716800;
|
||||
/// Jan 01, 1900 AD
|
||||
pub const zos = -2208988800;
|
||||
/// Jan 01, 1601 AD
|
||||
pub const windows = -11644473600;
|
||||
/// Jan 01, 1978 AD
|
||||
pub const amiga = 252460800;
|
||||
/// Dec 31, 1967 AD
|
||||
pub const pickos = -63244800;
|
||||
/// Jan 06, 1980 AD
|
||||
pub const gps = 315964800;
|
||||
/// Jan 01, 0001 AD
|
||||
pub const clr = -62135769600;
|
||||
|
||||
pub const unix = posix;
|
||||
pub const android = posix;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user