Skip to content

fix(libkernel): report a level-triggered equeue event once per wait - #2703

Closed
husseinkad wants to merge 2 commits into
boykopovar:mainfrom
husseinkad:fix/kernel-equeue-level-event-once
Closed

husseinkad wants to merge 2 commits into
boykopovar:mainfrom
husseinkad:fix/kernel-equeue-level-event-once

Conversation

@husseinkad

@husseinkad husseinkad commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

What

An event added with sceKernelAddUserEvent has no EV_CLEAR, so it stays triggered until it is deleted. The collection loop in Equeue.cpp kept re-emitting it until the caller's buffer was full: a sceKernelWaitEqueue call with num = 4 on one level event returned count 4, all the same event. kqueue examines a knote once per scan and re-queues a reported level knote behind the scan marker for the next call (kqueue_scan in sys/kern/kern_event.c; kevent(2): "multiple events which trigger the filter do not result in multiple kevents being placed on the kqueue"), so a level event is reported at most once per call and again on the next one.

The two copies of the collection loop (GetTriggeredEvents and WaitForEvents) are now one CollectTriggered. It only stays on the same event when a distinct queued completion follows, which the AMPR and VideoOut events rely on. Timers, HR timers and EV_CLEAR events behave as before. The Orbis behaviour was not measured on a console; that, the remaining starvation of later events when num is smaller than the number of ready level events (FreeBSD rotates them), and AMPR/VideoOut completions being returned as separate entries are recorded in TechnicalDebt.

Tested

Windows 11 (10.0.26200), WinLibs GCC 15.2.0 r7, Release:

  • guest_equeue_events gains: a level event reported once per call with num = 4 on the poll path and on a blocking wait with a 1 s timeout (also when a helper thread triggers it after about 10 ms), an edge event reported once and again after a new trigger, and two AMPR completions of one event delivered in order with num = 4 and across num = 1 calls. It fails without the change (exit 0xc0000409) and passes with it; ctest -R "ampr|equeue" passes.
  • Outside the repo, a probe of 8 scenarios against main's and this branch's Equeue.cpp (N level/edge/mixed events with num below, equal to and above N, one event triggered 50 times between waits, a blocked waiter triggered later, periodic and one-shot timers, 20 AMPR completions on one ident and 3 idents interleaved, deleting an event and the equeue while 4 threads wait, poll/infinite/huge timeouts and bad arguments, and a 4-waiter/4-trigger stress of 3 s): all pass on the branch with no event dropped or duplicated within a call, while main fails five of the eight.
  • tools/check_conventions.py --base origin/main passes; tools/pr_overlap.py --branch reports no overlap. Open PR feat(libkernel): implement read and write events for guest sockets #1091 (guest socket events) also edits Equeue.cpp and Equeue.hpp and conflicts textually; it needs a rebase anyway, and its PollEvents() call has to stay in the callers before CollectTriggered.
  • Linux not run.

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 in TechnicalDebt
  • No notes, investigation .md files or images added to the repository
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • AI-assisted: yes

A user event added with sceKernelAddUserEvent stays triggered until it is
deleted. The collection loop kept re-emitting it until the caller's event
buffer was full, so a wait with num > 1 returned the same event num times.
Like kevent, each event is now reported at most once per call; distinct
queued completions of one event are still delivered in order.
…vents

Document the level-triggered user event semantics of sceKernelWaitEqueue in TechnicalDebt.
@github-actions github-actions Bot added the intake paused Closed while PR intake is limited to authors with at least 10 PRs merged into main label Oct 10, 2026
@github-actions

Copy link
Copy Markdown

Thank you for your interest in the project! We are sorry, but we cannot accept more PRs while we work through the existing backlog. This PR has been automatically closed and labeled "intake paused". This is not a judgment of the quality of your changes.

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

Labels

intake paused Closed while PR intake is limited to authors with at least 10 PRs merged into main

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant