Repository navigation
feat(libkernel): watch a kqueue with EVFILT_READ - #8523
Conversation
…-kqueue # Conflicts: # docs/dev/debt/libkernel.md
|
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.
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.
|
|
The
The socket case in
This also affects If the live count is meant to stay, I think widening the entry is enough, for example:
The other option is a per-note queued flag so the count follows |
|
@MarrasFederico Thanks, this is a careful piece of work. Two things before the full review:
Once that's in, I'll review the waiter registration (lock order across nested queues) and check the Windows build, which hasn't been compiled yet. |
|
Windows run of 5f6c305 merged onto The merge conflicts only in |
…-kqueue # Conflicts: # docs/dev/debt/libkernel.md
|
@oneandonlydean @nikowolf123 thanks. Merged current
The code and the test are unchanged. @ycbuzi thanks for the Windows run. |
|
Checked the nested wait registration (lock order is always outer to inner, cycles are refused at registration), the |
What
keventthrewnot implementedforEVFILT_READon a kqueue descriptor. FreeBSD 11 lets a kqueue watch another one (kqueue_kqfilterandfilt_kqueue): the watched queue is readable while it has pending events, anddatais their count. This is now supported:datais that count. It is evaluated on every poll or wait, after the watched queue's timers and descriptors are refreshed.keventon the outer queue wakes when the inner one gets an event. The waiter registers with every watched queue, recursively, and rechecks after registering so no wake is lost. It also takes on their nearest timer and their descriptor interests, so an inner timer or socket wakes it too.EV_DISABLE/EV_ENABLE,EV_DISPATCH,EV_ONESHOT,EV_DELETE, and closing the watched queue, which drops the note.EINVAL, askqueue_kqfilterdoes. A note on the queue itself staysEINVAL(L1300-L1303).EV_CLEARon such a note, since FreeBSD re-arms it only when the watched queue queues a note, which is not tracked here. Also a note that would close a cycle (A watches B, B watches A), which no source defines and which would otherwise deadlock.The debt file drops this case from the kqueue entry's throw list and gets a
kevent on a kqueueentry with the throwing cases and how the count differs from FreeBSD. Heredatais the watched queue's enabled notes that are ready when the note is evaluated; FreeBSD'skq_countkeeps counting a queued note until that kqueue is scanned, even once it is disabled or no longer ready, and reports a queuedEV_ONESHOTnote with its last count before deleting it, where here it is evaluated again and, if the watched queue is empty by then, neither reported nor deleted.Tested
Ubuntu 26.04.1, kernel 7.0.0-38, GCC 15.2.0, Release, full build with
BUILD_TESTING=ON. Windows was not compiled. No title was run.guest_kqueue, newWatchKqueuecases:data1 and 2, level-triggered, and partial consumption lowers the count.keventis woken by an inner user trigger (about 50 ms), an inner timer, an inner socket send, and a three-level chain.EV_DISPATCH,EV_ONESHOTandEV_DELETE(thenENOENT) work.EVFILT_WRITEandEVFILT_VNODEon a kqueue returnEINVAL, andEV_CLEARand a cycle throw.EBADFon delete.The test passed five runs in a row. It fails on
main, where the registration throws. Reportingdata1 instead of the count, not registering the waiter with the watched queue, or ignoring the inner queue's timers makes it fail.All 79 tests matching
equeue|kqueue|kevent|pipe|aio|socket|select|pollpass.tools/check_conventions.py --base origin/mainpasses, with one warning: the existingkqueue and keventdebt entry was already over 1000 characters before this edit.tools/pr_overlap.pyfinds no shared function. It reports textual conflicts:Kqueue.cppline 193, next to itsAddDescriptorKnotechange;main()list.Whichever is merged second needs a small rebase, and I will rebase this one if they go first. feat(libkernel): sceKernelRaiseException on macOS hosts #4630 could not be compared, as it conflicts with
main; it does not touch kqueue.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)