Commit 7a4758ed78
lib/std/os/test.zig
@@ -1000,3 +1000,23 @@ test "access smoke test" {
file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" });
try os.access(file_path, os.F_OK);
}
+
+test "timerfd" {
+ if (native_os != .linux)
+ return error.SkipZigTest;
+
+ const linux = os.linux;
+ var tfd = try os.timerfd_create(linux.CLOCK.MONOTONIC, linux.TFD.CLOEXEC);
+ defer os.close(tfd);
+
+ var sit: linux.itimerspec = .{ .it_interval = .{ .tv_sec = 0, .tv_nsec = 0 }, .it_value = .{ .tv_sec = 0, .tv_nsec = 10 * (1000 * 1000) } };
+ try os.timerfd_settime(tfd, 0, &sit, null);
+
+ var fds: [1]os.pollfd = .{.{ .fd = tfd, .events = os.linux.POLL.IN, .revents = 0 }};
+ try expectEqual(try os.poll(&fds, -1), 1);
+ var git = try os.timerfd_gettime(tfd);
+ try expectEqual(git, .{ .it_interval = .{ .tv_sec = 0, .tv_nsec = 0 }, .it_value = .{ .tv_sec = 0, .tv_nsec = 0 } });
+
+ try os.timerfd_settime(tfd, 0, &sit, null);
+ try expectEqual(try os.poll(&fds, 5), 0);
+}
lib/std/os.zig
@@ -6926,3 +6926,52 @@ pub fn perf_event_open(
else => |err| return unexpectedErrno(err),
}
}
+
+pub const TimerFdCreateError = error{
+ AccessDenied,
+ ProcessFdQuotaExceeded,
+ SystemFdQuotaExceeded,
+ NoDevice,
+ SystemResources,
+} || UnexpectedError;
+
+pub const TimerFdGetError = error{InvalidHandle} || UnexpectedError;
+pub const TimerFdSetError = TimerFdGetError || error{Canceled};
+
+pub fn timerfd_create(clokid: i32, flags: u32) TimerFdCreateError!fd_t {
+ var rc = linux.timerfd_create(clokid, flags);
+ return switch (errno(rc)) {
+ .SUCCESS => @intCast(fd_t, rc),
+ .INVAL => unreachable,
+ .MFILE => return error.ProcessFdQuotaExceeded,
+ .NFILE => return error.SystemFdQuotaExceeded,
+ .NODEV => return error.NoDevice,
+ .NOMEM => return error.SystemResources,
+ .PERM => return error.AccessDenied,
+ else => |err| return unexpectedErrno(err),
+ };
+}
+
+pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const linux.itimerspec, old_value: ?*linux.itimerspec) TimerFdSetError!void {
+ var rc = linux.timerfd_settime(fd, flags, new_value, old_value);
+ return switch (errno(rc)) {
+ .SUCCESS => {},
+ .BADF => error.InvalidHandle,
+ .FAULT => unreachable,
+ .INVAL => unreachable,
+ .CANCELED => error.Canceled,
+ else => |err| return unexpectedErrno(err),
+ };
+}
+
+pub fn timerfd_gettime(fd: i32) TimerFdGetError!linux.itimerspec {
+ var curr_value: linux.itimerspec = undefined;
+ var rc = linux.timerfd_gettime(fd, &curr_value);
+ return switch (errno(rc)) {
+ .SUCCESS => return curr_value,
+ .BADF => error.InvalidHandle,
+ .FAULT => unreachable,
+ .INVAL => unreachable,
+ else => |err| return unexpectedErrno(err),
+ };
+}