From 7a4758ed7868096c12fec8dacba0bfd4a37fdd13 Mon Sep 17 00:00:00 2001 From: Thiago Teodoro Pereira Silva Date: Mon, 16 May 2022 19:56:33 -0300 Subject: [PATCH] std.os: add timerfd_create, timerfd_settime and timerfd_gettime --- lib/std/os.zig | 49 +++++++++++++++++++++++++++++++++++++++++++++ lib/std/os/test.zig | 20 ++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/lib/std/os.zig b/lib/std/os.zig index cd4500d60f..27c8bd099a 100644 --- a/lib/std/os.zig +++ b/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), + }; +} diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index dfe65f008d..975d5a64eb 100644 --- a/lib/std/os/test.zig +++ b/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); +}