| author | |
| committer | |
| log | 58c00a829e8acf438b91e9f7e1729ce79be722fa |
| tree | 21a7941f28fe1aea30c2591d116ad09334b34c8d |
| parent | c44be99f1abff2ab67d69964efecca380b96219e |
| signature |
6 files changed, 63 insertions(+), 23 deletions(-)
lib/std/Thread/Futex.zig+1-1| ... | ... | @@ -543,7 +543,7 @@ const PosixImpl = struct { |
| 543 | 543 | // This can be changed with pthread_condattr_setclock, but it's an extension and may not be available everywhere. |
| 544 | 544 | var ts: c.timespec = undefined; |
| 545 | 545 | if (timeout) |timeout_ns| { |
| 546 | std.posix.clock_gettime(c.CLOCK.REALTIME, &ts) catch unreachable; | |
| 546 | ts = std.posix.clock_gettime(c.CLOCK.REALTIME) catch unreachable; | |
| 547 | 547 | ts.sec +|= @as(@TypeOf(ts.sec), @intCast(timeout_ns / std.time.ns_per_s)); |
| 548 | 548 | ts.nsec += @as(@TypeOf(ts.nsec), @intCast(timeout_ns % std.time.ns_per_s)); |
| 549 | 549 |
lib/std/c.zig+18-1| ... | ... | @@ -213,6 +213,23 @@ pub const ARCH = switch (native_os) { |
| 213 | 213 | .linux => linux.ARCH, |
| 214 | 214 | else => void, |
| 215 | 215 | }; |
| 216 | ||
| 217 | // For use with posix.timerfd_create() | |
| 218 | // Actually, the parameter for the timerfd_create() function is an integer, | |
| 219 | // which means that the developer has to figure out which value is appropriate. | |
| 220 | // To make this easier and, above all, safer, because an incorrect value leads | |
| 221 | // to a panic, an enum is introduced which only allows the values | |
| 222 | // that actually work. | |
| 223 | pub const TIMERFD_CLOCK = timerfd_clockid_t; | |
| 224 | pub const timerfd_clockid_t = switch (native_os) { | |
| 225 | .linux, .freebsd => enum(u32) { | |
| 226 | REALTIME = 0, | |
| 227 | MONOTONIC = 1, | |
| 228 | _, | |
| 229 | }, | |
| 230 | else => clockid_t, | |
| 231 | }; | |
| 232 | ||
| 216 | 233 | pub const CLOCK = clockid_t; |
| 217 | 234 | pub const clockid_t = switch (native_os) { |
| 218 | 235 | .linux, .emscripten => linux.clockid_t, |
| ... | ... | @@ -9256,7 +9273,7 @@ pub extern "c" fn epoll_pwait( |
| 9256 | 9273 | sigmask: *const sigset_t, |
| 9257 | 9274 | ) c_int; |
| 9258 | 9275 | |
| 9259 | pub extern "c" fn timerfd_create(clockid: clockid_t, flags: c_int) c_int; | |
| 9276 | pub extern "c" fn timerfd_create(clockid: timerfd_clockid_t, flags: c_int) c_int; | |
| 9260 | 9277 | pub extern "c" fn timerfd_settime( |
| 9261 | 9278 | fd: c_int, |
| 9262 | 9279 | flags: c_int, |
lib/std/os/linux.zig+27-3| ... | ... | @@ -2215,7 +2215,7 @@ pub fn eventfd(count: u32, flags: u32) usize { |
| 2215 | 2215 | return syscall2(.eventfd2, count, flags); |
| 2216 | 2216 | } |
| 2217 | 2217 | |
| 2218 | pub fn timerfd_create(clockid: clockid_t, flags: TFD) usize { | |
| 2218 | pub fn timerfd_create(clockid: timerfd_clockid_t, flags: TFD) usize { | |
| 2219 | 2219 | return syscall2( |
| 2220 | 2220 | .timerfd_create, |
| 2221 | 2221 | @intFromEnum(clockid), |
| ... | ... | @@ -4696,8 +4696,32 @@ pub const clockid_t = enum(u32) { |
| 4696 | 4696 | BOOTTIME = 7, |
| 4697 | 4697 | REALTIME_ALARM = 8, |
| 4698 | 4698 | BOOTTIME_ALARM = 9, |
| 4699 | SGI_CYCLE = 10, | |
| 4700 | TAI = 11, | |
| 4699 | // In the linux kernel header file (time.h) is the following note: | |
| 4700 | // * The driver implementing this got removed. The clock ID is kept as a | |
| 4701 | // * place holder. Do not reuse! | |
| 4702 | // Therefore, calling clock_gettime() with these IDs will result in an error. | |
| 4703 | // | |
| 4704 | // Some backgrond: | |
| 4705 | // - SGI_CYCLE was for Silicon Graphics (SGI) workstations, | |
| 4706 | // which are probably no longer in use, so it makes sense to disable | |
| 4707 | // - TAI_CLOCK was designed as CLOCK_REALTIME(UTC) + tai_offset, | |
| 4708 | // but tai_offset was always 0 in the kernel. | |
| 4709 | // So there is no point in using this clock. | |
| 4710 | // SGI_CYCLE = 10, | |
| 4711 | // TAI = 11, | |
| 4712 | _, | |
| 4713 | }; | |
| 4714 | ||
| 4715 | // For use with posix.timerfd_create() | |
| 4716 | // Actually, the parameter for the timerfd_create() function is in integer, | |
| 4717 | // which means that the developer has to figure out which value is appropriate. | |
| 4718 | // To make this easier and, above all, safer, because an incorrect value leads | |
| 4719 | // to a panic, an enum is introduced which only allows the values | |
| 4720 | // that actually work. | |
| 4721 | pub const TIMERFD_CLOCK = timerfd_clockid_t; | |
| 4722 | pub const timerfd_clockid_t = enum(u32) { | |
| 4723 | REALTIME = 0, | |
| 4724 | MONOTONIC = 1, | |
| 4701 | 4725 | _, |
| 4702 | 4726 | }; |
| 4703 | 4727 |
lib/std/os/linux/test.zig+1-1| ... | ... | @@ -41,7 +41,7 @@ test "timer" { |
| 41 | 41 | var err: linux.E = linux.E.init(epoll_fd); |
| 42 | 42 | try expect(err == .SUCCESS); |
| 43 | 43 | |
| 44 | const timer_fd = linux.timerfd_create(linux.CLOCK.MONOTONIC, .{}); | |
| 44 | const timer_fd = linux.timerfd_create(linux.TIMERFD_CLOCK.MONOTONIC, .{}); | |
| 45 | 45 | try expect(linux.E.init(timer_fd) == .SUCCESS); |
| 46 | 46 | |
| 47 | 47 | const time_interval = linux.timespec{ |
lib/std/posix.zig+14-13| ... | ... | @@ -121,6 +121,7 @@ pub const blkcnt_t = system.blkcnt_t; |
| 121 | 121 | pub const blksize_t = system.blksize_t; |
| 122 | 122 | pub const clock_t = system.clock_t; |
| 123 | 123 | pub const clockid_t = system.clockid_t; |
| 124 | pub const timerfd_clockid_t = system.timerfd_clockid_t; | |
| 124 | 125 | pub const cpu_set_t = system.cpu_set_t; |
| 125 | 126 | pub const dev_t = system.dev_t; |
| 126 | 127 | pub const dl_phdr_info = system.dl_phdr_info; |
| ... | ... | @@ -155,6 +156,7 @@ pub const socklen_t = system.socklen_t; |
| 155 | 156 | pub const stack_t = system.stack_t; |
| 156 | 157 | pub const time_t = system.time_t; |
| 157 | 158 | pub const timespec = system.timespec; |
| 159 | pub const timestamp_t = system.timestamp_t; | |
| 158 | 160 | pub const timeval = system.timeval; |
| 159 | 161 | pub const timezone = system.timezone; |
| 160 | 162 | pub const ucontext_t = system.ucontext_t; |
| ... | ... | @@ -5653,13 +5655,13 @@ pub fn dl_iterate_phdr( |
| 5653 | 5655 | |
| 5654 | 5656 | pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError; |
| 5655 | 5657 | |
| 5656 | /// TODO: change this to return the timespec as a return value | |
| 5657 | pub fn clock_gettime(clock_id: clockid_t, tp: *timespec) ClockGetTimeError!void { | |
| 5658 | pub fn clock_gettime(clock_id: clockid_t) ClockGetTimeError!timespec { | |
| 5659 | var tp: timespec = undefined; | |
| 5658 | 5660 | if (native_os == .wasi and !builtin.link_libc) { |
| 5659 | var ts: wasi.timestamp_t = undefined; | |
| 5661 | var ts: timestamp_t = undefined; | |
| 5660 | 5662 | switch (system.clock_time_get(clock_id, 1, &ts)) { |
| 5661 | 5663 | .SUCCESS => { |
| 5662 | tp.* = .{ | |
| 5664 | tp = .{ | |
| 5663 | 5665 | .sec = @intCast(ts / std.time.ns_per_s), |
| 5664 | 5666 | .nsec = @intCast(ts % std.time.ns_per_s), |
| 5665 | 5667 | }; |
| ... | ... | @@ -5667,7 +5669,7 @@ pub fn clock_gettime(clock_id: clockid_t, tp: *timespec) ClockGetTimeError!void |
| 5667 | 5669 | .INVAL => return error.UnsupportedClock, |
| 5668 | 5670 | else => |err| return unexpectedErrno(err), |
| 5669 | 5671 | } |
| 5670 | return; | |
| 5672 | return tp; | |
| 5671 | 5673 | } |
| 5672 | 5674 | if (native_os == .windows) { |
| 5673 | 5675 | if (clock_id == .REALTIME) { |
| ... | ... | @@ -5676,19 +5678,19 @@ pub fn clock_gettime(clock_id: clockid_t, tp: *timespec) ClockGetTimeError!void |
| 5676 | 5678 | // FileTime has a granularity of 100 nanoseconds and uses the NTFS/Windows epoch. |
| 5677 | 5679 | const ft64 = (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime; |
| 5678 | 5680 | const ft_per_s = std.time.ns_per_s / 100; |
| 5679 | tp.* = .{ | |
| 5681 | tp = .{ | |
| 5680 | 5682 | .sec = @as(i64, @intCast(ft64 / ft_per_s)) + std.time.epoch.windows, |
| 5681 | 5683 | .nsec = @as(c_long, @intCast(ft64 % ft_per_s)) * 100, |
| 5682 | 5684 | }; |
| 5683 | return; | |
| 5685 | return tp; | |
| 5684 | 5686 | } else { |
| 5685 | 5687 | // TODO POSIX implementation of CLOCK.MONOTONIC on Windows. |
| 5686 | 5688 | return error.UnsupportedClock; |
| 5687 | 5689 | } |
| 5688 | 5690 | } |
| 5689 | 5691 | |
| 5690 | switch (errno(system.clock_gettime(clock_id, tp))) { | |
| 5691 | .SUCCESS => return, | |
| 5692 | switch (errno(system.clock_gettime(clock_id, &tp))) { | |
| 5693 | .SUCCESS => return tp, | |
| 5692 | 5694 | .FAULT => unreachable, |
| 5693 | 5695 | .INVAL => return error.UnsupportedClock, |
| 5694 | 5696 | else => |err| return unexpectedErrno(err), |
| ... | ... | @@ -5697,7 +5699,7 @@ pub fn clock_gettime(clock_id: clockid_t, tp: *timespec) ClockGetTimeError!void |
| 5697 | 5699 | |
| 5698 | 5700 | pub fn clock_getres(clock_id: clockid_t, res: *timespec) ClockGetTimeError!void { |
| 5699 | 5701 | if (native_os == .wasi and !builtin.link_libc) { |
| 5700 | var ts: wasi.timestamp_t = undefined; | |
| 5702 | var ts: timestamp_t = undefined; | |
| 5701 | 5703 | switch (system.clock_res_get(@bitCast(clock_id), &ts)) { |
| 5702 | 5704 | .SUCCESS => res.* = .{ |
| 5703 | 5705 | .sec = @intCast(ts / std.time.ns_per_s), |
| ... | ... | @@ -5910,8 +5912,7 @@ pub fn res_mkquery( |
| 5910 | 5912 | q[i + 3] = class; |
| 5911 | 5913 | |
| 5912 | 5914 | // Make a reasonably unpredictable id |
| 5913 | var ts: timespec = undefined; | |
| 5914 | clock_gettime(.REALTIME, &ts) catch {}; | |
| 5915 | const ts = clock_gettime(.REALTIME) catch unreachable; | |
| 5915 | 5916 | const UInt = std.meta.Int(.unsigned, @bitSizeOf(@TypeOf(ts.nsec))); |
| 5916 | 5917 | const unsec: UInt = @bitCast(ts.nsec); |
| 5917 | 5918 | const id: u32 = @truncate(unsec + unsec / 65536); |
| ... | ... | @@ -7293,7 +7294,7 @@ pub const TimerFdCreateError = error{ |
| 7293 | 7294 | pub const TimerFdGetError = error{InvalidHandle} || UnexpectedError; |
| 7294 | 7295 | pub const TimerFdSetError = TimerFdGetError || error{Canceled}; |
| 7295 | 7296 | |
| 7296 | pub fn timerfd_create(clock_id: clockid_t, flags: system.TFD) TimerFdCreateError!fd_t { | |
| 7297 | pub fn timerfd_create(clock_id: system.timerfd_clockid_t, flags: system.TFD) TimerFdCreateError!fd_t { | |
| 7297 | 7298 | const rc = system.timerfd_create(clock_id, @bitCast(flags)); |
| 7298 | 7299 | return switch (errno(rc)) { |
| 7299 | 7300 | .SUCCESS => @intCast(rc), |
lib/std/time.zig+2-4| ... | ... | @@ -68,8 +68,7 @@ pub fn nanoTimestamp() i128 { |
| 68 | 68 | return value.toEpoch(); |
| 69 | 69 | }, |
| 70 | 70 | else => { |
| 71 | var ts: posix.timespec = undefined; | |
| 72 | posix.clock_gettime(.REALTIME, &ts) catch |err| switch (err) { | |
| 71 | const ts = posix.clock_gettime(.REALTIME) catch |err| switch (err) { | |
| 73 | 72 | error.UnsupportedClock, error.Unexpected => return 0, // "Precision of timing depends on hardware and OS". |
| 74 | 73 | }; |
| 75 | 74 | return (@as(i128, ts.sec) * ns_per_s) + ts.nsec; |
| ... | ... | @@ -171,8 +170,7 @@ pub const Instant = struct { |
| 171 | 170 | else => posix.CLOCK.MONOTONIC, |
| 172 | 171 | }; |
| 173 | 172 | |
| 174 | var ts: posix.timespec = undefined; | |
| 175 | posix.clock_gettime(clock_id, &ts) catch return error.Unsupported; | |
| 173 | const ts = posix.clock_gettime(clock_id) catch return error.Unsupported; | |
| 176 | 174 | return .{ .timestamp = ts }; |
| 177 | 175 | } |
| 178 | 176 |