Skip to content

fix(libkernel): use precise sleep for sub-millisecond host waits - #1576

Closed
neuralsin wants to merge 1 commit into
boykopovar:mainfrom
neuralsin:fix/windows-wait-precision
Closed

neuralsin wants to merge 1 commit into
boykopovar:mainfrom
neuralsin:fix/windows-wait-precision

Conversation

@neuralsin

Copy link
Copy Markdown
Contributor

What

Addresses the sub-millisecond sleep busy-spin issue documented in #1471:
On Windows, std::this_thread::sleep_for goes through winpthreads' nanosleep, which truncates sub-millisecond durations (tv_nsec / 1'000'000) to 0 ms and returns immediately without sleeping or yielding. As a result, polling loops requesting sub-millisecond pauses spin at 100% CPU.

This PR switches the sub-millisecond host waits in four areas to use PreciseSleepUs() (which uses a Windows high-resolution waitable timer CREATE_WAITABLE_TIMER_HIGH_RESOLUTION on Windows and standard microsecond sleep on POSIX):

  • core/libs/prx/libSceAgcDriver/Execution/src/Pm4.cpp: WAIT_REG_MEM polling loop (50 µs)
  • core/libs/prx/libkernel/Apr/src/Apr.cpp: _execute counter and address wait loop (50 µs)
  • core/libs/prx/libkernel/Aio/src/Aio.cpp: sceKernelAioWaitRequests and sceKernelAioWaitRequest polling loops (10 µs)
  • core/libs/prx/libSceFont/src/State.cpp: Font::Backoff spinlock backoff (30 µs)

Tested

  • Linux / WSL 2 Ubuntu 24.04 (x86_64), GCC 15.2.0, Ninja 1.13.2
  • ctest -R 'guest_aio|guest_ampr|guest_font': 4/4 passed (100% tests passed: guest_ampr_markers, guest_font, guest_font_writing_line, guest_aio)
  • python tools/check_conventions.py --base origin/main: 100% passed

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

@MarcZX10

MarcZX10 commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

I found that the previous head of #1551 duplicated the same four production substitutions as this PR. I have re-scoped #1551 to add and register only a focused PreciseSleepUs CTest; it no longer changes those production files. The focused test passes locally on Linux, and fork CI is running on the updated head.

@MarcZX10

MarcZX10 commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

The updated test-only head of #1551 has now passed its fork Build: 495/495 Linux tests, 486/486 Windows tests, and all three relinker jobs. Its diff contains only PreciseWait.cpp and CTest registration; no production files overlap this PR.

@popcoder565

Copy link
Copy Markdown
Contributor

Windows numbers for this, since it's only been run on Linux so far. Setup: Windows 10 (19045), MinGW-w64 GCC 15.2.0 (WinLibs r7), with the 0.5 ms timer resolution libkernel sets.

wait takes
std::this_thread::sleep_for for 10, 50 or 200 µs 0 ms (returns at once)
high-resolution waitable timer (PreciseSleepUs) for 10, 50 or 200 µs about 0.50 ms each

So on Windows each of these polls goes from a busy spin to a 0.5 ms wait, 10–50 times the requested pause. On Linux they sleep roughly 60 µs.

  • AIO: neither loop runs in practice. SubmitCommands performs the reads and sets the final state before it returns. On main, 2000 back-to-back 4 KB sceKernelAioSubmitReadCommands + sceKernelAioWaitRequest pairs take 3.2 ms in total, and every wait returns on its first check. The AIO hunk doesn't change anything measurable.
  • Font backoff and APR waits: these do loop, so each contended backoff or unmet wait now costs about 0.5 ms instead of spinning. I haven't run a workload that hits them.

🤖 Addressed by Claude Code

@MarcZX10

MarcZX10 commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

I have integrated the four production call-site changes from #1576 into my #1551, alongside its focused PreciseSleepUs regression test and Windows test setup; the commit credits you as co-author. The combined current head passes the seven focused Linux Release tests and Conventions. #1551 is now the more complete canonical PR for this change; I have asked an upstream collaborator to run its required full Build under #2113. Please close #1576 as superseded once that current-head Build is confirmed, so the same call-site fix is reviewed and merged once.

@MarcZX10

MarcZX10 commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Update on the overlapping wait changes

I have rebased #1551 onto current main at 8b393b6e (head 46a77cca) and rerun its seven focused Linux tests; all pass. It contains the same four production call-site changes as #1576, credits you as co-author, and also carries the focused PreciseSleepUs regression test. For that reason #1551 is the more complete canonical PR for this behavior.

#1576 currently has no checks reported, while #1551 still needs the repository-required upstream Build/relinker run. Please close #1576 as superseded once that required validation is recorded on #1551, so reviewers only have to land one copy of the call-site changes.

@MarcZX10

MarcZX10 commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Consolidation status

I refreshed Marc's existing PR #1551 onto upstream main 0df342c6 (head e777d26b) and reran focused Linux validation. It still carries the four precise-wait call-site changes from this PR, credits Shaan as co-author, and also includes the dedicated helper regression test.

PR Scope Current status
#1551 Four production call sites plus helper regression test Canonical carrier; Linux focused tests pass on the current head; upstream Build/relinker matrix still needs a collaborator dispatch
#1576 Same four production call sites Duplicate behavior already integrated into #1551 with attribution retained

Could you close #1576 so the same production change is not reviewed twice? Please keep this PR open if you have additional behavior or evidence that is not covered by #1551; we can review that separately.

@adriadam10

Copy link
Copy Markdown
Collaborator

Closing as a duplicate: #1551 now carries the same four call-site changes (Pm4.cpp, Apr.cpp, Aio.cpp, State.cpp), credits you as co-author, and adds a regression test for PreciseSleepUs, so the change should be reviewed and merged once, there.

Two points from @popcoder565's Windows measurements that are worth addressing in #1551: each wait becomes ~0.5 ms instead of 10-50 µs, and the AIO loops don't run in practice, so that hunk changes nothing measurable.

Thanks for the patch; feel free to reopen if #1551 doesn't move forward.

@adriadam10 adriadam10 closed this Oct 10, 2026
@MarcZX10

Copy link
Copy Markdown
Contributor

Coordination requested after the #1551 review

The reviewer on #1551 confirmed that both open PRs currently contain the same four production call-site changes and asked us to choose one carrier. I have preserved your call-site work in #1551 with you credited as co-author; #1551 also contains the focused helper regression test. I prefer #1551 as the single carrier.

Could you confirm whether you agree to close #1576 as superseded once its changes are retained in #1551? If you prefer #1576 to carry the production changes, please say so and I will remove those call-site edits from #1551. I will not ask for both PRs to merge.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants