Skip to content

feat(libkernel): support EV_DISABLE and EV_ENABLE in kevent - #5440

Closed
Sevthered wants to merge 1 commit into
boykopovar:mainfrom
Sevthered:feat/libkernel-kevent-disable
Closed

Sevthered wants to merge 1 commit into
boykopovar:mainfrom
Sevthered:feat/libkernel-kevent-disable

Conversation

@Sevthered

@Sevthered Sevthered commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What

kevent accepts EV_DISABLE and EV_ENABLE instead of throwing on EV_DISABLE.

Semantics follow FreeBSD 11 kern_event.c, the revision the libkernel technical debt entry already pins:

  • kqueue_register (done_ev_add): EV_ENABLE clears KN_DISABLED, otherwise EV_DISABLE sets it, after the other changes of the same kevent. It applies to a knote added by the same change and to an existing one. EV_DELETE is handled first, so EV_DELETE | EV_DISABLE deletes.
  • kqueue_scan: a disabled knote is not reported and stays registered.
  • KNOTE_ACTIVATE: activity that arrives while a knote is disabled is kept, so it is reported after EV_ENABLE.

Implementation:

  • KernelEqueueEvent gets a disabled flag, set when the knote is added (AddVnodeEvent takes it as a parameter so the knote is never visible enabled) and changed in ModifyKnote.
  • CollectOncePerWait skips disabled knotes. PollEvents and WaitForDescriptors skip them too, so a disabled socket that is readable does not wake the wait.
  • A user trigger or vnode hint that arrives while disabled is kept in the knote; a socket is polled again at the first scan after EV_ENABLE.

EV_DISABLE on EVFILT_TIMER still throws: enabling it again is a change to an existing timer, which throws on main. EV_DISPATCH and EV_FORCEONESHOT are unchanged. Not measured on a console.

Tested

Windows 11, MinGW-w64 GCC 15.2.0 (WinLibs r7), full build with BUILD_TESTING=ON.

  • guest_kqueue: new DisabledEvents covers EV_ENABLE/EV_DISABLE on a missing knote (ENOENT), a user event added disabled then triggered and enabled, disabling and enabling an existing level event, EV_DELETE | EV_DISABLE, an EV_CLEAR user event touched while disabled, an EV_ONESHOT event enabled from another thread while kevent waits, a readable socket added disabled (a 30 ms kevent does not return early) then enabled, and a file watch added disabled whose write is reported after EV_ENABLE. The assertion in Errors that EV_ADD | EV_DISABLE throws now uses a timer.
  • Full suite: ctest -j 8, 1097 tests, 1090 passed, 0 failed, 7 skipped. The same 7 are skipped on main on this machine (five video_out_flip_*, agc_driver_stencil_ref_export, guest_video_out_wqhd_detection_no_vulkan).
  • python tools/check_conventions.py --base origin/main passes.

Linux: WSL2 Ubuntu 24.04 (kernel 6.6.87.2), GCC 13.3.0, lavapipe (Mesa 25.2.8), this branch merged into main 0aa4cb1c2 as the CI linux job does. guest_kqueue passes. Full suite with the CI environment, ctest --parallel 8: 1080 tests, 2 failed, 48 skipped. Both failures also occur on main alone in this environment, three runs out of three: agc_driver_depth_compare_copy needs the write watch, which the WSL kernel lacks (no asynchronous userfaultfd write protection), and guest_socket_read_write gets EAGAIN where it expects EPIPE at line 154. tools/check_skips.py reports five of the skips as unexpected: four write-watch tests and guest_video_out_high_frame_rate (no 120 Hz display). No title or homebrew was run.

Checklist

A disabled knote stays registered and is not reported. A user trigger or
vnode hint that arrives while it is disabled is kept and reported after
EV_ENABLE, and a socket is polled again at the first scan after it. The
state changes after the other changes of the same kevent, and EV_DELETE
with EV_DISABLE deletes, as kqueue_register does with KN_DISABLED in
FreeBSD 11.

EV_DISABLE on EVFILT_TIMER still throws: enabling it again is a change
to an existing timer, which is not supported.
@johnohhh1

Copy link
Copy Markdown
Contributor

Independent Linux validation of 691616e38d0f0c283c5da1c4817f7388759404c6, cleanly cherry-picked onto main a0f5916a293067ca840e835e58a8a55a0b764b4b. Original author and stable patch ID retained; no implementation changes.

Ubuntu 26.04.1 x86-64, GCC 15.2.0, Release, bundled dependencies, BUILD_TESTING=ON.

  • Full Linux build passes. Eight selected CTests pass without skips: guest_kqueue, guest_equeue_events, guest_socket_events, guest_socket_pair, guest_socket_read_write, guest_poll, guest_select, patched_libraries. Serial run, 30-second per-test limit, 2.88 seconds total; guest_kqueue takes 1.73 seconds. This includes the new disabled socket and file-watch cases and existing Linux-specific file/directory tests.
  • The identical rebuilt guest_kqueue_tests executable, run against frozen baseline libraries, aborts with kevent: EV_DISABLE not implemented; it passes with the PR libraries. The baseline's existing regression also passes when local IPC is permitted.
  • A separate guest-ABI probe passes 64 simultaneous-enable/disable rejection cases, including receipts and preservation of existing event state; four level/clear/oneshot delivery modes with pending notifications, timed waits and cross-thread enabling; and 800 enable/disable cycles across four concurrent queues. All 4,474 assertions pass, approximately 0.067 seconds. The same probe reports the unsupported EV_DISABLE exception against baseline libraries.
  • Conventions and whitespace checks pass.

Initial socket sends returned EPERM under the Codex sandbox on both versions. The results above use host execution with local IPC permitted; no external service was contacted. Initial failure logs are retained as environment evidence.

Expectations use the PR's pinned FreeBSD source. No console, title, extra Windows or complete CTest-suite run is claimed. Timer enable/disable remains outside the supported scope described in this PR.

AI-assisted validation/report: Codex. Your existing patch is unchanged.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 14, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

Closing: no title is known to reach this. With the queue at 700+ open PRs, please hold off on new PRs that don't name a title needing the change until it's down. If a title stops on this on current main, reopen with the title ID and the log line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs libkernel needs rebase Conflicts with main, rebase needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants