Skip to content

fix(libkernel): wait for alarm and setitimer expiries with the precise timed wait on Windows - #11851

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
LeandroLP23:fix/alarm-precise-timed-wait
Nov 2, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
LeandroLP23:fix/alarm-precise-timed-wait

Conversation

@LeandroLP23

Copy link
Copy Markdown
Contributor

What

On Windows, setitimer and alarm expiries land on the host's coarse tick. A 2 ms one-shot ITIMER_REAL timer delivers SIGALRM after 15.9 ms (median of 31). The alarm thread (RunAlarms in core/libs/prx/libkernel/System/src/Signals.cpp) waits on a std::condition_variable, and MinGW's wait_until goes through winpthreads and its GetTickCount64-based timeout. This is another call site of #1471. #11167 left it out of the sigtimedwait change as a separate site, and this PR does it the same way.

The change:

  • AlarmState::changed is a TimedWait::Condition, the waiter sigtimedwait, event flags, equeues and semaphores already use. alarm and setitimer wake it with NotifyAll.
  • RunAlarms keeps the steady_clock deadline that alarm, setitimer and getitimer share. When the deadline is still ahead, it waits with WaitUntil for the remaining time, converted to a TimedWait::NowNanos() deadline, then loops. It expires the timer only once steady_clock has reached the deadline, so a wake from a re-arm, or the two clocks disagreeing by a few microseconds, never fires it early.
  • A periodic timer still re-arms by whole intervals past the deadline it missed. The now < deadline branch of the old period count can no longer be reached, so it is gone.

Tested

Windows 11, Intel Core i5-10600K, WinLibs GCC 15.2.0 r7, Release, full build:

  • New guest_itimer_short_expiry (guest_itimer_tests short-expiry): with SIGALRM blocked, it arms a 2 ms one-shot ITIMER_REAL timer 31 times and takes each expiry with sigtimedwait. No expiry may come earlier than 2 ms after arming, and the median must stay under 12 ms, as in fix(libkernel): wait for sigtimedwait timeouts with the precise timed wait on Windows #11167's sigtimedwait test.
  • With main's Signals.cpp it fails: median 15858000 ns.
  • With the change it passes 10 of 10 (--repeat until-fail:10), with medians between 2008700 and 2017400 ns.
  • The 53 tests matching sig|signal|pause|alarm|itimer|pselect|exception|raise pass with --repeat until-fail:3.

Linux and macOS: not run. There TimedWait::Condition uses its condition_variable_any path, which waits the same way the old code did.

Tested on main 5bc84038c4, then rebased onto 801d5b9bc1, which doesn't touch these files. Overlaps are textual only: #9389, #10749 and #11002 edit other parts of Signals.cpp, and none touches the alarm code.

The other guest-visible waits #1471 still lists are AIO (#11416) and libSceUsbd (#9339), both in their own PRs.

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
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

Refs #1471

…e timed wait on Windows

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

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 3986 core/libs/prx/libkernel/System/src/Signals.cpp
PR 4563 core/libs/prx/libkernel/CMakeLists.txt
PR 5021 core/libs/prx/libkernel/CMakeLists.txt
PR 6936 core/libs/prx/libkernel/CMakeLists.txt
PR 7192 core/libs/prx/libkernel/CMakeLists.txt
PR 9019 core/libs/prx/libkernel/CMakeLists.txt
PR 9156 core/libs/prx/libkernel/CMakeLists.txt
PR 9293 core/libs/prx/libkernel/CMakeLists.txt
PR 9297 core/libs/prx/libkernel/CMakeLists.txt
PR 9302 core/libs/prx/libkernel/CMakeLists.txt
PR 9383 core/libs/prx/libkernel/CMakeLists.txt
PR 9389 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/System/src/Signals.cpp
PR 9557 core/libs/prx/libkernel/CMakeLists.txt
PR 9566 core/libs/prx/libkernel/CMakeLists.txt
PR 9938 core/libs/prx/libkernel/CMakeLists.txt
PR 11831 core/libs/prx/libkernel/CMakeLists.txt
PR 11896 core/libs/prx/libkernel/CMakeLists.txt
PR 11939 core/libs/prx/libkernel/CMakeLists.txt
PR 12544 core/libs/prx/libkernel/CMakeLists.txt
PR 12970 core/libs/prx/libkernel/CMakeLists.txt
PR 14264 core/libs/prx/libkernel/CMakeLists.txt
PR 14299 core/libs/prx/libkernel/CMakeLists.txt

@B-Howell

Copy link
Copy Markdown
Contributor

Linux run: Ubuntu 22.04 on WSL2 (kernel 6.18), GCC 11.4, Release, AMD Ryzen 7 7800X3D (16 threads). I built head b81185dd merged onto main f759e165d9; it merged without conflicts.

  • With the change: guest_itimer, guest_itimer_pending_default and guest_itimer_short_expiry pass 10 of 10 runs each (--repeat until-fail:10).
  • Control: with Signals.cpp from main and this PR's test, all three also pass 10 of 10.

So the slow expiry you measured on Windows (median about 15.9 ms) doesn't happen on this Linux host, and guest_itimer_short_expiry only separates the two versions on Windows. On Linux the change causes no regression in these three tests. I didn't record the per-run medians here.

AI-assisted (Claude Code).

@oneandonlydean oneandonlydean self-assigned this Oct 28, 2026
@oneandonlydean
oneandonlydean merged commit a645efe into boykopovar:main Nov 2, 2026
11 checks passed
@LeandroLP23
LeandroLP23 deleted the fix/alarm-precise-timed-wait branch November 3, 2026 08:47
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.

3 participants