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) {...@@ -699,7 +699,7 @@ const Os = switch (builtin.os.tag) {
699 .data = 0,699 .data = 0,
700 .udata = gop.index,700 .udata = gop.index,
701 }};701 }};
702 _ = try posix.kevent(w.os.kq_fd, &changes, &.{}, null);702 _ = try Io.Kqueue.kevent(w.os.kq_fd, &changes, &.{}, null);
703 assert(handles.len == gop.index);703 assert(handles.len == gop.index);
704 try handles.append(gpa, .{704 try handles.append(gpa, .{
705 .rs = .{},705 .rs = .{},
...@@ -789,7 +789,7 @@ const Os = switch (builtin.os.tag) {...@@ -789,7 +789,7 @@ const Os = switch (builtin.os.tag) {
789 },789 },
790 };790 };
791 const filtered_changes = if (i == handles.len - 1) changes[0..1] else &changes;791 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);
793 if (path.sub_path.len != 0) posix.close(dir_fd);793 if (path.sub_path.len != 0) posix.close(dir_fd);
794794
795 w.dir_table.swapRemoveAt(i);795 w.dir_table.swapRemoveAt(i);
...@@ -803,13 +803,13 @@ const Os = switch (builtin.os.tag) {...@@ -803,13 +803,13 @@ const Os = switch (builtin.os.tag) {
803 fn wait(w: *Watch, gpa: Allocator, timeout: Timeout) !WaitResult {803 fn wait(w: *Watch, gpa: Allocator, timeout: Timeout) !WaitResult {
804 var timespec_buffer: posix.timespec = undefined;804 var timespec_buffer: posix.timespec = undefined;
805 var event_buffer: [100]posix.Kevent = undefined;805 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));
807 if (n == 0) return .timeout;807 if (n == 0) return .timeout;
808 const reaction_sets = w.os.handles.items(.rs);808 const reaction_sets = w.os.handles.items(.rs);
809 var any_dirty = markDirtySteps(gpa, reaction_sets, event_buffer[0..n], false);809 var any_dirty = markDirtySteps(gpa, reaction_sets, event_buffer[0..n], false);
810 timespec_buffer = .{ .sec = 0, .nsec = 0 };810 timespec_buffer = .{ .sec = 0, .nsec = 0 };
811 while (n == event_buffer.len) {811 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);
813 if (n == 0) break;813 if (n == 0) break;
814 any_dirty = markDirtySteps(gpa, reaction_sets, event_buffer[0..n], any_dirty);814 any_dirty = markDirtySteps(gpa, reaction_sets, event_buffer[0..n], any_dirty);
815 }815 }
lib/std/Io/Kqueue.zig+55-6
...@@ -334,7 +334,10 @@ fn schedule(k: *Kqueue, thread: *Thread, ready_queue: Fiber.Queue) void {...@@ -334,7 +334,10 @@ fn schedule(k: *Kqueue, thread: *Thread, ready_queue: Fiber.Queue) void {
334 },334 },
335 };335 };
336 // If an error occurs it only pessimises scheduling.336 // 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 };
338 return;341 return;
339 }342 }
340 spawn_thread: {343 spawn_thread: {
...@@ -429,9 +432,9 @@ fn idle(k: *Kqueue, thread: *Thread) void {...@@ -429,9 +432,9 @@ fn idle(k: *Kqueue, thread: *Thread) void {
429 k.yield(ready_fiber, .nothing);432 k.yield(ready_fiber, .nothing);
430 maybe_ready_fiber = null;433 maybe_ready_fiber = null;
431 }434 }
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| {
433 // TODO handle EINTR for cancellation purposes436 // TODO handle EINTR for cancellation purposes
434 @panic(@errorName(err));437 @panic(@errorName(err)); // TODO
435 };438 };
436 var maybe_ready_queue: ?Fiber.Queue = null;439 var maybe_ready_queue: ?Fiber.Queue = null;
437 for (events_buffer[0..n]) |event| switch (@as(Completion.UserData, @enumFromInt(event.udata))) {440 for (events_buffer[0..n]) |event| switch (@as(Completion.UserData, @enumFromInt(event.udata))) {
...@@ -598,8 +601,9 @@ const SwitchMessage = struct {...@@ -598,8 +601,9 @@ const SwitchMessage = struct {
598 .udata = @intFromEnum(Completion.UserData.exit),601 .udata = @intFromEnum(Completion.UserData.exit),
599 },602 },
600 };603 };
601 _ = posix.kevent(each_thread.kq_fd, &changes, &.{}, null) catch |err| {604 _ = kevent(each_thread.kq_fd, &changes, &.{}, null) catch |err| {
602 @panic(@errorName(err));605 // TODO handle EINTR for cancellation purposes
606 @panic(@errorName(err)); // TODO
603 };607 };
604 },608 },
605 }609 }
...@@ -1538,7 +1542,8 @@ fn netRead(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Strea...@@ -1538,7 +1542,8 @@ fn netRead(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Strea
1538 .udata = @intFromPtr(fiber),1542 .udata = @intFromPtr(fiber),
1539 },1543 },
1540 };1544 };
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
1542 @panic(@errorName(err)); // TODO1547 @panic(@errorName(err)); // TODO
1543 }));1548 }));
1544 }1549 }
...@@ -1774,3 +1779,47 @@ const Condition = struct {...@@ -1774,3 +1779,47 @@ const Condition = struct {
1774 wake: Io.Condition.Wake,1779 wake: Io.Condition.Wake,
1775 },1780 },
1776};1781};
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 {...@@ -792,54 +792,6 @@ pub fn fstat(fd: fd_t) FStatError!Stat {
792 }792 }
793}793}
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
843pub const INotifyInitError = error{795pub const INotifyInitError = error{
844 ProcessFdQuotaExceeded,796 ProcessFdQuotaExceeded,
845 SystemFdQuotaExceeded,797 SystemFdQuotaExceeded,