authorgravatar for thiago@thiagotps.xyzThiago Teodoro Pereira Silva <thiago@thiagotps.xyz> 2022-05-16 19:56:33-03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-05-17 00:56:33+02:00
log7a4758ed7868096c12fec8dacba0bfd4a37fdd13
tree28c446fd7ac027a685f726647b4ecdf1de8af2c1
parent1de7b8d26c2d283b2e494dd6b4cecfa4d44c441d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

std.os: add timerfd_create, timerfd_settime and timerfd_gettime


2 files changed, 69 insertions(+), 0 deletions(-)

lib/std/os.zig+49
......@@ -6926,3 +6926,52 @@ pub fn perf_event_open(
69266926 else => |err| return unexpectedErrno(err),
69276927 }
69286928}
6929
6930pub const TimerFdCreateError = error{
6931 AccessDenied,
6932 ProcessFdQuotaExceeded,
6933 SystemFdQuotaExceeded,
6934 NoDevice,
6935 SystemResources,
6936} || UnexpectedError;
6937
6938pub const TimerFdGetError = error{InvalidHandle} || UnexpectedError;
6939pub const TimerFdSetError = TimerFdGetError || error{Canceled};
6940
6941pub fn timerfd_create(clokid: i32, flags: u32) TimerFdCreateError!fd_t {
6942 var rc = linux.timerfd_create(clokid, flags);
6943 return switch (errno(rc)) {
6944 .SUCCESS => @intCast(fd_t, rc),
6945 .INVAL => unreachable,
6946 .MFILE => return error.ProcessFdQuotaExceeded,
6947 .NFILE => return error.SystemFdQuotaExceeded,
6948 .NODEV => return error.NoDevice,
6949 .NOMEM => return error.SystemResources,
6950 .PERM => return error.AccessDenied,
6951 else => |err| return unexpectedErrno(err),
6952 };
6953}
6954
6955pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const linux.itimerspec, old_value: ?*linux.itimerspec) TimerFdSetError!void {
6956 var rc = linux.timerfd_settime(fd, flags, new_value, old_value);
6957 return switch (errno(rc)) {
6958 .SUCCESS => {},
6959 .BADF => error.InvalidHandle,
6960 .FAULT => unreachable,
6961 .INVAL => unreachable,
6962 .CANCELED => error.Canceled,
6963 else => |err| return unexpectedErrno(err),
6964 };
6965}
6966
6967pub fn timerfd_gettime(fd: i32) TimerFdGetError!linux.itimerspec {
6968 var curr_value: linux.itimerspec = undefined;
6969 var rc = linux.timerfd_gettime(fd, &curr_value);
6970 return switch (errno(rc)) {
6971 .SUCCESS => return curr_value,
6972 .BADF => error.InvalidHandle,
6973 .FAULT => unreachable,
6974 .INVAL => unreachable,
6975 else => |err| return unexpectedErrno(err),
6976 };
6977}
lib/std/os/test.zig+20
......@@ -1000,3 +1000,23 @@ test "access smoke test" {
10001000 file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" });
10011001 try os.access(file_path, os.F_OK);
10021002}
1003
1004test "timerfd" {
1005 if (native_os != .linux)
1006 return error.SkipZigTest;
1007
1008 const linux = os.linux;
1009 var tfd = try os.timerfd_create(linux.CLOCK.MONOTONIC, linux.TFD.CLOEXEC);
1010 defer os.close(tfd);
1011
1012 var sit: linux.itimerspec = .{ .it_interval = .{ .tv_sec = 0, .tv_nsec = 0 }, .it_value = .{ .tv_sec = 0, .tv_nsec = 10 * (1000 * 1000) } };
1013 try os.timerfd_settime(tfd, 0, &sit, null);
1014
1015 var fds: [1]os.pollfd = .{.{ .fd = tfd, .events = os.linux.POLL.IN, .revents = 0 }};
1016 try expectEqual(try os.poll(&fds, -1), 1);
1017 var git = try os.timerfd_gettime(tfd);
1018 try expectEqual(git, .{ .it_interval = .{ .tv_sec = 0, .tv_nsec = 0 }, .it_value = .{ .tv_sec = 0, .tv_nsec = 0 } });
1019
1020 try os.timerfd_settime(tfd, 0, &sit, null);
1021 try expectEqual(try os.poll(&fds, 5), 0);
1022}