Skip to content

feat(libkernel): implement kevent EV_DISABLE, EV_DISPATCH and EV_FORCEONESHOT - #5847

Merged
adriadam10 merged 2 commits into
boykopovar:mainfrom
akkadbakkad89:feat/kevent-ev-flags
Oct 15, 2026
Merged

adriadam10 merged 2 commits into
boykopovar:mainfrom
akkadbakkad89:feat/kevent-ev-flags

Conversation

@akkadbakkad89

@akkadbakkad89 akkadbakkad89 commented Oct 14, 2026 •

Copy link
Copy Markdown

What

kevent no longer throws on EV_DISABLE, EV_DISPATCH, EV_FORCEONESHOT or a negative nevents, following kqueue_register/kqueue_scan in FreeBSD 11's kern_event.c:

  • KernelEqueueEvent gains an enabled flag (FreeBSD's KN_DISABLED). PollEvents, TriggerExpiredTimers, TriggerEvent, WaitForDescriptors interest registration and NextTimerWaitMicros all skip disabled knotes, so a disabled knote never fires.
  • EV_DISABLE on EV_ADD registers the knote disabled; on an existing knote EV_DISABLE/EV_ENABLE toggles it. EV_ENABLE | EV_DISABLE still returns EINVAL.
  • EV_DISPATCH reports the event once, then disables the knote until re-enabled - both collect paths (CollectTriggered, CollectOncePerWait).
  • EV_FORCEONESHOT is ignored on a new knote; on an existing knote it sets EV_ONESHOT and fires it, as kqueue_register does at l.1339-1341.
  • A modify updates only udata, the filter's touch/fflags and enable/disable - no flag adoption, matching kqueue_register.
  • Negative nevents returns EINVAL.

Known deviation documented in docs/dev/debt/libkernel.md: a NOTE_TRIGGER raised while a user knote is disabled is kept and reported after EV_ENABLE, where FreeBSD's knote drops it.

File-level overlap note: Kqueue.cpp/Equeue.cpp are also touched by open PRs #5749 (EVFILT_VNODE on macOS) and #5493 (vnode error naming) - different code paths, line-adjacent only.

Tested

WSL Ubuntu 24.04, gcc, host CPU only:

  • guest_kqueue: all pass, including DisableAndDispatch cases - register-disabled socket knote stays silent until EV_ENABLE; EV_DISPATCH fires once, suppresses further data, re-arms on EV_ENABLE, disables again; EV_FORCEONESHOT on add stays a normal level knote (delivers twice), on modify sets oneshot and fires (EV_DELETE then ENOENT); disabled user knote keeps its NOTE_TRIGGER until re-enable; Errors gains the nevents < 0 -> EINVAL check and the old EV_DISABLE throw expectation is removed
  • guest_equeue_events, guest_ult_queue_* (8 tests): pass
  • Rebuilt neighbors guest_socket_pair, guest_dup, guest_fstatfs, guest_getrlimit, guest_signals: pass
  • tools/check_conventions.py --base upstream/main: clean

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

@adriadam10 adriadam10 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the enabled flag and the EV_DISPATCH collect paths look right and guest_kqueue passes here. Two points differ from kern_event.c (the commit the debt entry cites):

  • EV_FORCEONESHOT on a new knote: kqueue_register only clears it from kn_kevent.flags on the attach path (l.1303-1304). It sets EV_ONESHOT and activates the knote only when the knote already exists (l.1339-1341). Kqueue.cpp:252 applies it on add, and GuestKqueue.cpp:250-253 pins that. Please follow the source: no oneshot on add; on an existing knote set EV_ONESHOT and trigger it.
  • ModifyKnote (Kqueue.cpp:232) ORs EV_ONESHOT | EV_CLEAR | EV_DISPATCH into an existing knote. kqueue_register does not do that for an existing knote (only udata, the filter's touch/fflags, and enable/disable). It also lets EV_CLEAR through on a socket knote, which AddDescriptorKnote throws on at add time. Drop the line (or, if you have a source for it, cite it and keep the throw for EV_CLEAR on sockets), and fix the PR body and the debt entry accordingly.

@akkadbakkad89

Copy link
Copy Markdown
Author

Both points fixed in 637cb1ed4, thanks for the line references:

  • EV_FORCEONESHOT on add now does nothing beyond KNOTE_CLEARED_FLAGS stripping it; on an existing knote ModifyKnote sets EV_ONESHOT and marks the knote triggered. The test now pins both halves: EV_ADD | EV_FORCEONESHOT delivers as a normal level knote twice, then the same change on the existing knote fires once and the knote is gone (EV_DELETE -> ENOENT).
  • The EV_ONESHOT | EV_CLEAR | EV_DISPATCH OR on modify is dropped; a modify now touches only udata, enable/disable, EV_FORCEONESHOT and the filter's touch/fflags, matching kqueue_register. No EV_CLEAR can reach a socket knote through modify any more.

PR body and the libkernel.md debt entry updated to describe the new behaviour. guest_kqueue green locally (WSL).

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 14, 2026
akkadbakkad89 and others added 2 commits October 15, 2026 06:00
…EONESHOT

A knote registered or modified with EV_DISABLE stays registered but is
not polled, fired or reported until an EV_ENABLE change re-arms it, as
kern_event.c does with KN_DISABLED. EV_DISPATCH reports an event once
and then disables the knote, and EV_FORCEONESHOT registers as oneshot.
A negative nevents fails with EINVAL instead of throwing.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… flags

On a new knote EV_FORCEONESHOT is dropped from the flags; on an
existing one it sets EV_ONESHOT and fires the knote, as
kqueue_register does at l.1339-1341. A modify no longer ORs
EV_ONESHOT, EV_CLEAR or EV_DISPATCH into the knote.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 15, 2026
@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 5973 docs/dev/debt/libkernel.md L111-112
PR 6343 docs/dev/debt/libkernel.md L111-112
PR 6510 core/libs/prx/libkernel/Equeue/Equeue.cpp L52-53, L68-69, L84-85, L101-102, L123, L130, L155, L167-168
core/libs/prx/libkernel/Equeue/src/Kqueue.cpp L225, L244-252
core/libs/tests/GuestKqueue.cpp L59, L252, L534-535
docs/dev/debt/libkernel.md L111-112
PR 6542 docs/dev/debt/libkernel.md L110-112

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 3891 docs/dev/debt/libkernel.md
PR 4156 docs/dev/debt/libkernel.md
PR 4396 docs/dev/debt/libkernel.md
PR 4397 docs/dev/debt/libkernel.md
PR 4422 docs/dev/debt/libkernel.md
PR 4423 docs/dev/debt/libkernel.md
PR 4424 docs/dev/debt/libkernel.md
PR 4520 docs/dev/debt/libkernel.md
PR 4521 docs/dev/debt/libkernel.md
PR 4522 docs/dev/debt/libkernel.md
PR 4523 docs/dev/debt/libkernel.md
PR 4566 docs/dev/debt/libkernel.md
PR 4599 docs/dev/debt/libkernel.md
PR 4718 docs/dev/debt/libkernel.md
PR 4740 docs/dev/debt/libkernel.md
PR 4749 docs/dev/debt/libkernel.md
PR 4760 docs/dev/debt/libkernel.md
PR 4813 docs/dev/debt/libkernel.md
PR 5021 docs/dev/debt/libkernel.md
PR 5835 docs/dev/debt/libkernel.md
PR 6044 core/libs/tests/GuestKqueue.cpp
PR 6222 docs/dev/debt/libkernel.md
PR 6447 core/libs/prx/libkernel/Equeue/Equeue.cpp

@adriadam10 adriadam10 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both points are fixed: EV_FORCEONESHOT is a no-op on add and sets EV_ONESHOT and triggers on an existing knote, as in kqueue_register, and a modify no longer adopts flags. Checked the build and ctest on the PR merged onto main, guest_kqueue passes and fails without the change; merging once the full Build is green.

@adriadam10
adriadam10 merged commit f27697f into boykopovar:main Oct 15, 2026
8 checks passed
blawesom pushed a commit to blawesom/AnyPS5 that referenced this pull request Oct 17, 2026
… and follow Windows $Deleted paths

Carries the additive pieces of boykopovar#6510 onto main after its feature was
superseded by boykopovar#5847: the deleteEventFunc invocation when an EV_ONESHOT
note retires in CollectTriggered, the Windows $Deleted path detection
in FileEvent (IsDeleted transitions), the relaxed timer-modify and
SetVnodeNotes guards, and the compatible kevent tests.
blawesom pushed a commit to blawesom/AnyPS5 that referenced this pull request Oct 17, 2026
… and follow Windows $Deleted paths

Carries the additive pieces of boykopovar#6510 onto main after its feature was
superseded by boykopovar#5847: the deleteEventFunc invocation when an EV_ONESHOT
note retires in CollectTriggered, the Windows $Deleted path detection
in FileEvent (IsDeleted transitions), the relaxed timer-modify and
SetVnodeNotes guards, and the compatible kevent tests.
blawesom pushed a commit to blawesom/AnyPS5 that referenced this pull request Oct 18, 2026
… and follow Windows $Deleted paths

Carries the additive pieces of boykopovar#6510 onto main after its feature was
superseded by boykopovar#5847: the deleteEventFunc invocation when an EV_ONESHOT
note retires in CollectTriggered, the Windows $Deleted path detection
in FileEvent (IsDeleted transitions), the relaxed timer-modify and
SetVnodeNotes guards, and the compatible kevent tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants