authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-07 15:00:01-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-07 17:33:07-08:00
log3961fe3de9713e3e618551cd96873a7b3948a2b2
treee070dcf7f04352f3068497e5ea7e804738f9c9e2
parent2c6304efc798d8a3773ae126661902b3a3214854

std: move posix.kevent to Io.Kqueue


3 files changed, 59 insertions(+), 58 deletions(-)

lib/std/Build/Watch.zig+4-4
......@@ -699,7 +699,7 @@ const Os = switch (builtin.os.tag) {
699699 .data = 0,
700700 .udata = gop.index,
701701 }};
702 _ = try posix.kevent(w.os.kq_fd, &changes, &.{}, null);
702 _ = try Io.Kqueue.kevent(w.os.kq_fd, &changes, &.{}, null);
703703 assert(handles.len == gop.index);
704704 try handles.append(gpa, .{
705705 .rs = .{},
......@@ -789,7 +789,7 @@ const Os = switch (builtin.os.tag) {
789789 },
790790 };
791791 const filtered_changes = if (i == handles.len - 1) changes[0..1] else &changes;
792 _ = try posix.kevent(w.os.kq_fd, filtered_changes, &.{}, null);
792 _ = try Io.Kqueue.kevent(w.os.kq_fd, filtered_changes, &.{}, null);
793793 if (path.sub_path.len != 0) posix.close(dir_fd);
794794
795795 w.dir_table.swapRemoveAt(i);
......@@ -803,13 +803,13 @@ const Os = switch (builtin.os.tag) {
803803 fn wait(w: *Watch, gpa: Allocator, timeout: Timeout) !WaitResult {
804804 var timespec_buffer: posix.timespec = undefined;
805805 var event_buffer: [100]posix.Kevent = undefined;
806 var n = try posix.kevent(w.os.kq_fd, &.{}, &event_buffer, timeout.toTimespec(&timespec_buffer));
806 var n = try Io.Kqueue.kevent(w.os.kq_fd, &.{}, &event_buffer, timeout.toTimespec(&timespec_buffer));
807807 if (n == 0) return .timeout;
808808 const reaction_sets = w.os.handles.items(.rs);
809809 var any_dirty = markDirtySteps(gpa, reaction_sets, event_buffer[0..n], false);
810810 timespec_buffer = .{ .sec = 0, .nsec = 0 };
811811 while (n == event_buffer.len) {
812 n = try posix.kevent(w.os.kq_fd, &.{}, &event_buffer, &timespec_buffer);
812 n = try Io.Kqueue.kevent(w.os.kq_fd, &.{}, &event_buffer, &timespec_buffer);
813813 if (n == 0) break;
814814 any_dirty = markDirtySteps(gpa, reaction_sets, event_buffer[0..n], any_dirty);
815815 }
lib/std/Io/Kqueue.zig+55-6
......@@ -334,7 +334,10 @@ fn schedule(k: *Kqueue, thread: *Thread, ready_queue: Fiber.Queue) void {
334334 },
335335 };
336336 // If an error occurs it only pessimises scheduling.
337 _ = posix.kevent(idle_search_thread.kq_fd, &changes, &.{}, null) catch {};
337 _ = kevent(idle_search_thread.kq_fd, &changes, &.{}, null) catch |err| {
338 // TODO handle EINTR for cancellation purposes
339 @panic(@errorName(err)); // TODO
340 };
338341 return;
339342 }
340343 spawn_thread: {
......@@ -429,9 +432,9 @@ fn idle(k: *Kqueue, thread: *Thread) void {
429432 k.yield(ready_fiber, .nothing);
430433 maybe_ready_fiber = null;
431434 }
432 const n = posix.kevent(thread.kq_fd, &.{}, &events_buffer, null) catch |err| {
435 const n = kevent(thread.kq_fd, &.{}, &events_buffer, null) catch |err| {
433436 // TODO handle EINTR for cancellation purposes
434 @panic(@errorName(err));
437 @panic(@errorName(err)); // TODO
435438 };
436439 var maybe_ready_queue: ?Fiber.Queue = null;
437440 for (events_buffer[0..n]) |event| switch (@as(Completion.UserData, @enumFromInt(event.udata))) {
......@@ -598,8 +601,9 @@ const SwitchMessage = struct {
598601 .udata = @intFromEnum(Completion.UserData.exit),
599602 },
600603 };
601 _ = posix.kevent(each_thread.kq_fd, &changes, &.{}, null) catch |err| {
602 @panic(@errorName(err));
604 _ = kevent(each_thread.kq_fd, &changes, &.{}, null) catch |err| {
605 // TODO handle EINTR for cancellation purposes
606 @panic(@errorName(err)); // TODO
603607 };
604608 },
605609 }
......@@ -1538,7 +1542,8 @@ fn netRead(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Strea
15381542 .udata = @intFromPtr(fiber),
15391543 },
15401544 };
1541 assert(0 == (posix.kevent(thread.kq_fd, &changes, &.{}, null) catch |err| {
1545 assert(0 == (kevent(thread.kq_fd, &changes, &.{}, null) catch |err| {
1546 // TODO handle EINTR for cancellation purposes
15421547 @panic(@errorName(err)); // TODO
15431548 }));
15441549 }
......@@ -1774,3 +1779,47 @@ const Condition = struct {
17741779 wake: Io.Condition.Wake,
17751780 },
17761781};
1782
1783pub const KEventError = error{
1784 /// The process does not have permission to register a filter.
1785 AccessDenied,
1786 /// The event could not be found to be modified or deleted.
1787 EventNotFound,
1788 /// No memory was available to register the event.
1789 SystemResources,
1790 /// The specified process to attach to does not exist.
1791 ProcessNotFound,
1792 /// changelist or eventlist had too many items on it.
1793 /// TODO remove this possibility
1794 Overflow,
1795};
1796
1797pub fn kevent(
1798 kq: i32,
1799 changelist: []const posix.Kevent,
1800 eventlist: []posix.Kevent,
1801 timeout: ?*const posix.timespec,
1802) KEventError!usize {
1803 while (true) {
1804 const rc = posix.system.kevent(
1805 kq,
1806 changelist.ptr,
1807 std.math.cast(c_int, changelist.len) orelse return error.Overflow,
1808 eventlist.ptr,
1809 std.math.cast(c_int, eventlist.len) orelse return error.Overflow,
1810 timeout,
1811 );
1812 switch (posix.errno(rc)) {
1813 .SUCCESS => return @intCast(rc),
1814 .ACCES => return error.AccessDenied,
1815 .FAULT => unreachable, // TODO use error.Unexpected for these
1816 .BADF => unreachable, // Always a race condition.
1817 .INTR => continue, // TODO handle cancelation
1818 .INVAL => unreachable,
1819 .NOENT => return error.EventNotFound,
1820 .NOMEM => return error.SystemResources,
1821 .SRCH => return error.ProcessNotFound,
1822 else => unreachable,
1823 }
1824 }
1825}
lib/std/posix.zig-48
......@@ -792,54 +792,6 @@ pub fn fstat(fd: fd_t) FStatError!Stat {
792792 }
793793}
794794
795pub const KEventError = error{
796 /// The process does not have permission to register a filter.
797 AccessDenied,
798
799 /// The event could not be found to be modified or deleted.
800 EventNotFound,
801
802 /// No memory was available to register the event.
803 SystemResources,
804
805 /// The specified process to attach to does not exist.
806 ProcessNotFound,
807
808 /// changelist or eventlist had too many items on it.
809 /// TODO remove this possibility
810 Overflow,
811};
812
813pub fn kevent(
814 kq: i32,
815 changelist: []const Kevent,
816 eventlist: []Kevent,
817 timeout: ?*const timespec,
818) KEventError!usize {
819 while (true) {
820 const rc = system.kevent(
821 kq,
822 changelist.ptr,
823 cast(c_int, changelist.len) orelse return error.Overflow,
824 eventlist.ptr,
825 cast(c_int, eventlist.len) orelse return error.Overflow,
826 timeout,
827 );
828 switch (errno(rc)) {
829 .SUCCESS => return @intCast(rc),
830 .ACCES => return error.AccessDenied,
831 .FAULT => unreachable,
832 .BADF => unreachable, // Always a race condition.
833 .INTR => continue,
834 .INVAL => unreachable,
835 .NOENT => return error.EventNotFound,
836 .NOMEM => return error.SystemResources,
837 .SRCH => return error.ProcessNotFound,
838 else => unreachable,
839 }
840 }
841}
842
843795pub const INotifyInitError = error{
844796 ProcessFdQuotaExceeded,
845797 SystemFdQuotaExceeded,