Skip to content

feat(libc): add the std::__sce_v2 thread start, timed wait, clock and processor count calls - #9447

Open
AlxcBTW wants to merge 8 commits into
boykopovar:mainfrom
AlxcBTW:pr/libc-sce-v2-thread-time-remainder
Open

AlxcBTW wants to merge 8 commits into
boykopovar:mainfrom
AlxcBTW:pr/libc-sce-v2-thread-time-remainder

Conversation

@AlxcBTW

@AlxcBTW AlxcBTW commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

What

#8885 adds the versioned (std::__sce_v2) _Mtx, _Cnd and _Thrd calls on the libkernel scePthread* functions and lists the calls it leaves out. This adds three of them and one clock, in Threads.cpp and Time.cpp next to #8885's, each written from the console's libc.prx disassembly:

Export (NID) Behaviour
std::__sce_v2::_Thrd_start(pthread**, void*(*)(void*), void*) (2cXiHqvKFUM) scePthreadCreate with default attributes and the name Thr; returns 0, or 4 for any failure (the console returns nothing else)
std::__sce_v2::_Thrd_hardware_concurrency() (dt3C+gjXHKk) the population count of a libkernel affinity mask (scePthreadGetaffinity of the first calling thread), computed once
std::__sce_v2::_Cnd_timedwait(pthread_cond**, pthread_mutex**, const timespec*) (230scaAkbIU) the absolute realtime deadline is turned into the remaining microseconds (0 once passed, rounded up to the next microsecond) and passed to scePthreadCondTimedwait; returns 0 when signalled, 2 on ETIMEDOUT, 4 for other errors and 5 for EPERM, as the console's result mapping does
std::__sce_v2::chrono::steady_clock::now_v1_compat() (EMwrSFcyowE) gettimeofday as seconds * 1000000 + microseconds, the unversioned _Xtime_get_ticks value

What the disassembly says that the topic's first description did not: now_v1_compat does not read CLOCK_MONOTONIC and does not count nanoseconds; the console calls gettimeofday and returns microseconds of the realtime clock, so that is what it does here (and it is not monotonic if the system clock steps). _Thrd_hardware_concurrency is not the host's processor count: the module caches the population count of the main thread's affinity mask (13 with the libkernel default mask 0x1FFF). The libkernel forwards for scePthreadCreate, scePthreadCondTimedwait and scePthreadGetaffinity are three more members of #8885's PthreadSyncForwards_nid_no_patch, registered where #8885 registers the others (libkernel/Pthread/Posix/Thread.cpp, libc/include/General.hpp).

Not in this PR:

  • std::__sce_v2::_Xtime_get_ticks (XXOOIxrIKDM) is in feat(libc): add the std::__sce_v2 exception types and throwers #8901 with the same body (the unversioned call, microseconds); tools/pr_overlap.py lists it, so it is left to that PR.
  • std::__sce_v2::_Cnd_do_broadcast_at_thread_exit (2s6aLdPIA4I) is left out. The disassembled body does not register a broadcast; it walks the per-process table of registrations for the calling thread, signals and broadcasts each and clears it. That table is filled by _Cnd_register_at_thread_exit, which is not implemented in libc (the _Pad::_Launch entry in the debt file says the same), so an implementation now would be a function that never finds anything. The debt entry says so.

Known differences, in docs/dev/debt/libc.md: the remaining time saturates at 4294967295 microseconds where the console wraps its 32-bit result; the processor count is read from the first caller's mask, not the main thread's at module start.

Titles that import these: Minecraft Dungeons II (PPSA16064) imports the four calls above and the two left out below.

Tested

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: feat(libc): add the std::__sce_v2 mutex, condition and thread calls #8885 (this branch is based on its head 8e08acb; rebase onto main after it merges)
  • Fixes: none
  • Unblocks: none (PPSA16064 imports these six; no Game bring-up discussion yet)
  • GPUs tested: n/a
  • AI-assisted: yes

hypermist and others added 8 commits October 21, 2026 17:25
The versioned Dinkumware entries operate on libkernel's own mutex,
condition and thread handles: _Mtx_init(_with_name), _Mtx_destroy,
_Mtx_lock, _Mtx_trylock, _Mtx_unlock, _Cnd_init(_with_name),
_Cnd_destroy, _Cnd_wait, _Cnd_signal, _Cnd_broadcast, _Thrd_detach,
_Thrd_join, _Thrd_yield, _Thrd_id and _Throw_Cpp_error. libkernel
registers the pthread calls with libc next to the C11 forwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RbLgECLQ2bpDM7oe2urGZK
The console's std::__sce_v2::_Throw_Cpp_error raises a
std::__sce_v2::system_error, not the unversioned std::system_error this
forwarded to. It moves to the versioned exception change, which adds that
type.

Review on boykopovar#8885: the versioned unlock, wait, signal and broadcast calls
return 0 whatever the kernel returns, as the console's do (each calls the
kernel and clears eax). The test now shows the kernel failing an unowned
unlock and wait while the wrappers report success.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RbLgECLQ2bpDM7oe2urGZK
…read-sync

# Conflicts:
#	core/libs/tests/GuestLibcThreads.cpp
@github-actions

Copy link
Copy Markdown

Progress report (a6dcea9 → 2dc7b70)

📈 System libraries: 42.44% (+0.11%, +20 implemented functions)

✅ 20 implemented
Library Name
libc _ZNSt8__sce_v210_Thrd_joinEP7pthreadPi_nid_postfix
libc _ZNSt8__sce_v211_Cnd_signalEPP12pthread_cond_nid_postfix
libc _ZNSt8__sce_v211_Mtx_unlockEPP13pthread_mutex_nid_postfix
libc _ZNSt8__sce_v211_Thrd_startEPP7pthreadPFPvS3_ES3__nid_postfix
libc _ZNSt8__sce_v211_Thrd_yieldEv_nid_postfix
libc _ZNSt8__sce_v212_Cnd_destroyEPP12pthread_cond_nid_postfix
libc _ZNSt8__sce_v212_Mtx_destroyEPP13pthread_mutex_nid_postfix
libc _ZNSt8__sce_v212_Mtx_trylockEPP13pthread_mutex_nid_postfix
libc _ZNSt8__sce_v212_Thrd_detachEP7pthread_nid_postfix
libc _ZNSt8__sce_v214_Cnd_broadcastEPP12pthread_cond_nid_postfix
libc _ZNSt8__sce_v214_Cnd_timedwaitEPP12pthread_condPP13pthread_mutexPK8timespec_nid_postfix
libc _ZNSt8__sce_v219_Cnd_init_with_nameEPP12pthread_condPKc_nid_postfix
libc _ZNSt8__sce_v219_Mtx_init_with_nameEPP13pthread_mutexiPKc_nid_postfix
libc _ZNSt8__sce_v226_Thrd_hardware_concurrencyEv_nid_postfix
libc _ZNSt8__sce_v26chrono12steady_clock13now_v1_compatEv_nid_postfix
libc _ZNSt8__sce_v28_Thrd_idEv_nid_postfix
libc _ZNSt8__sce_v29_Cnd_initEPP12pthread_cond_nid_postfix
libc _ZNSt8__sce_v29_Cnd_waitEPP12pthread_condPP13pthread_mutex_nid_postfix
libc _ZNSt8__sce_v29_Mtx_initEPP13pthread_mutexi_nid_postfix
libc _ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix

@github-actions

github-actions Bot commented Oct 21, 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 1835 core/libs/prx/libc/src/Threads.cpp
PR 3965 docs/dev/debt/libc.md
PR 5021 core/libs/prx/libc/src/Threads.cpp
core/libs/prx/libc/src/Time.cpp
docs/dev/debt/libc.md
PR 5303 docs/dev/debt/libc.md
PR 6084 core/libs/prx/libc/src/Time.cpp
PR 6819 docs/dev/debt/libc.md
PR 7081 docs/dev/debt/libc.md
PR 7135 core/libs/prx/libkernel/Pthread/Posix/Thread.cpp
PR 7386 docs/dev/debt/libc.md
PR 7447 docs/dev/debt/libc.md
PR 7544 docs/dev/debt/libc.md
PR 7648 core/libs/prx/libc/src/Threads.cpp
docs/dev/debt/libc.md
PR 7715 docs/dev/debt/libc.md
PR 7851 docs/dev/debt/libc.md
PR 8150 docs/dev/debt/libc.md
PR 8417 docs/dev/debt/libc.md
PR 8965 docs/dev/debt/libc.md
PR 9087 docs/dev/debt/libc.md
PR 9340 docs/dev/debt/libc.md
PR 9371 docs/dev/debt/libc.md
PR 9677 core/libs/prx/libc/src/Time.cpp
docs/dev/debt/libc.md
PR 9761 docs/dev/debt/libc.md
PR 9863 docs/dev/debt/libc.md
PR 9873 docs/dev/debt/libc.md
PR 9929 core/libs/prx/libc/include/General.hpp
docs/dev/debt/libc.md
PR 9935 docs/dev/debt/libc.md
PR 9964 docs/dev/debt/libc.md
PR 10002 docs/dev/debt/libc.md
PR 10007 docs/dev/debt/libc.md
PR 10113 docs/dev/debt/libc.md
PR 10158 docs/dev/debt/libc.md
PR 10165 docs/dev/debt/libc.md
PR 10200 docs/dev/debt/libc.md
PR 10226 docs/dev/debt/libc.md
PR 10234 docs/dev/debt/libc.md
PR 10245 docs/dev/debt/libc.md
PR 10250 docs/dev/debt/libc.md
PR 10253 docs/dev/debt/libc.md
PR 10265 docs/dev/debt/libc.md
PR 10270 docs/dev/debt/libc.md
PR 10274 docs/dev/debt/libc.md
PR 10315 docs/dev/debt/libc.md
PR 10321 docs/dev/debt/libc.md
PR 10325 docs/dev/debt/libc.md
PR 10328 docs/dev/debt/libc.md
PR 10345 docs/dev/debt/libc.md
PR 10349 docs/dev/debt/libc.md
PR 10397 docs/dev/debt/libc.md
PR 10405 docs/dev/debt/libc.md
PR 10409 core/libs/prx/libc/src/Time.cpp
PR 10506 docs/dev/debt/libc.md
PR 10510 docs/dev/debt/libc.md
PR 10512 docs/dev/debt/libc.md
PR 10565 docs/dev/debt/libc.md
PR 10569 docs/dev/debt/libc.md
PR 10749 core/libs/prx/libc/include/General.hpp
docs/dev/debt/libc.md
PR 10780 docs/dev/debt/libc.md
PR 10987 core/libs/prx/libc/src/Time.cpp
docs/dev/debt/libc.md
PR 11109 docs/dev/debt/libc.md
PR 11172 docs/dev/debt/libc.md
PR 11260 docs/dev/debt/libc.md
PR 11262 docs/dev/debt/libc.md
PR 11266 docs/dev/debt/libc.md
PR 11332 docs/dev/debt/libc.md
PR 11446 core/libs/prx/libc/include/General.hpp
PR 11621 docs/dev/debt/libc.md
PR 11625 docs/dev/debt/libc.md
PR 11632 docs/dev/debt/libc.md
PR 11634 docs/dev/debt/libc.md
PR 11661 docs/dev/debt/libc.md
PR 11664 docs/dev/debt/libc.md
PR 11689 docs/dev/debt/libc.md
PR 11698 docs/dev/debt/libc.md
PR 11724 docs/dev/debt/libc.md
PR 11726 docs/dev/debt/libc.md
PR 11793 docs/dev/debt/libc.md
PR 11831 docs/dev/debt/libc.md
PR 11848 docs/dev/debt/libc.md
PR 11870 docs/dev/debt/libc.md
PR 11895 docs/dev/debt/libc.md
PR 11907 docs/dev/debt/libc.md
PR 11947 docs/dev/debt/libc.md
PR 12053 docs/dev/debt/libc.md
PR 12057 docs/dev/debt/libc.md
PR 12122 docs/dev/debt/libc.md
PR 12146 core/libs/prx/libc/include/General.hpp
core/libs/prx/libc/src/Threads.cpp
core/libs/prx/libkernel/Pthread/Posix/Thread.cpp
PR 12149 docs/dev/debt/libc.md
PR 12184 docs/dev/debt/libc.md
PR 12271 docs/dev/debt/libc.md
PR 12292 docs/dev/debt/libc.md
PR 12397 docs/dev/debt/libc.md
PR 12428 docs/dev/debt/libc.md
PR 12510 docs/dev/debt/libc.md
PR 12511 docs/dev/debt/libc.md
PR 12514 docs/dev/debt/libc.md
PR 12518 docs/dev/debt/libc.md
PR 12530 docs/dev/debt/libc.md
PR 12532 docs/dev/debt/libc.md
PR 12560 docs/dev/debt/libc.md
PR 12574 docs/dev/debt/libc.md
PR 12592 core/libs/prx/libc/src/Time.cpp
docs/dev/debt/libc.md
PR 12593 core/libs/prx/libc/src/Time.cpp
docs/dev/debt/libc.md
PR 12594 docs/dev/debt/libc.md
PR 12595 docs/dev/debt/libc.md
PR 12598 docs/dev/debt/libc.md
PR 12605 docs/dev/debt/libc.md
PR 12622 docs/dev/debt/libc.md
PR 12627 docs/dev/debt/libc.md
PR 12682 docs/dev/debt/libc.md
PR 12688 docs/dev/debt/libc.md
PR 12700 docs/dev/debt/libc.md
PR 12704 docs/dev/debt/libc.md
PR 12841 core/libs/prx/libc/src/Time.cpp
docs/dev/debt/libc.md
PR 12849 docs/dev/debt/libc.md
PR 12920 docs/dev/debt/libc.md
PR 12947 docs/dev/debt/libc.md
PR 12965 docs/dev/debt/libc.md
PR 13119 docs/dev/debt/libc.md
PR 13186 docs/dev/debt/libc.md
PR 13390 docs/dev/debt/libc.md
PR 13449 docs/dev/debt/libc.md
PR 13504 core/libs/prx/libkernel/Pthread/Posix/Thread.cpp
PR 13506 core/libs/prx/libkernel/Pthread/Posix/Thread.cpp
PR 13730 core/libs/prx/libc/include/General.hpp
PR 13784 docs/dev/debt/libc.md
PR 13793 docs/dev/debt/libc.md
PR 13794 docs/dev/debt/libc.md
PR 13804 docs/dev/debt/libc.md
PR 13809 docs/dev/debt/libc.md
PR 13828 docs/dev/debt/libc.md
PR 14020 docs/dev/debt/libc.md
PR 14039 core/libs/prx/libkernel/Pthread/Posix/Thread.cpp
PR 14085 docs/dev/debt/libc.md
PR 14212 docs/dev/debt/libc.md
PR 14235 core/libs/prx/libc/include/General.hpp
docs/dev/debt/libc.md
PR 14298 docs/dev/debt/libc.md
PR 14326 docs/dev/debt/libc.md
PR 14585 docs/dev/debt/libc.md
PR 14588 docs/dev/debt/libc.md
PR 14595 docs/dev/debt/libc.md
PR 14610 docs/dev/debt/libc.md
PR 14619 docs/dev/debt/libc.md
PR 14620 core/libs/prx/libc/include/General.hpp
core/libs/prx/libc/src/Time.cpp
docs/dev/debt/libc.md
PR 14623 docs/dev/debt/libc.md
PR 14828 docs/dev/debt/libc.md
PR 14864 docs/dev/debt/libc.md
PR 14878 docs/dev/debt/libc.md
PR 14885 core/libs/prx/libkernel/Pthread/Posix/Thread.cpp
PR 14915 docs/dev/debt/libc.md
PR 14955 docs/dev/debt/libc.md
PR 15004 docs/dev/debt/libc.md
PR 15095 core/libs/prx/libc/include/General.hpp
docs/dev/debt/libc.md
PR 15098 docs/dev/debt/libc.md
PR 15099 docs/dev/debt/libc.md

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The focused condition-variable cases cover signalled, expired and future deadlines, and the thread-start/current-affinity paths are backed by guest tests. I found a conversion boundary defect in MicrosecondsUntil: with a normalized deadline exactly 4,294 seconds ahead and a fractional component above 967,295 microseconds, the computed total exceeds UINT_MAX, but the guard only clamps when seconds > 4294; casting the larger total to unsigned int wraps it to a short timeout. Please clamp/check the total microseconds (including the fractional part) before conversion and add a boundary test around UINT_MAX.

The PR correctly declares its dependency on #8885 and says to rebase after that PR merges. Keep that ordering; once #8885 lands, rebase this branch onto then-current main and rerun the focused thread tests, conventions and overlap checks. The current head is tied to the older #8885 branch and its Linux tests were run on fork CI; Windows/title/console runs are explicitly not claimed. I did not run local tests.

@ycbuzi

ycbuzi commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Windows run of 2dc7b70 merged onto main a6646f8 (b60ba2cef1), the platform the description lists as not run. Windows 11 Home 10.0.26200, MinGW-w64 GCC 15.2.0 (ucrt-posix-seh r7), Release, BUILD_TESTING=ON.

The merge conflicts only in docs/dev/debt/libc.md, as GitHub shows; for this run I took this PR's side of that file. Built libc, libkernel and guest_libc_threads_tests with no errors or warnings. ctest --repeat until-fail:2 on guest_libc_threads: passes on both repeats. No negative control: the test calls functions this PR adds, so with main's sources it does not link. Not run: a title.

danielradosa added a commit to danielradosa/AnyPS5 that referenced this pull request Oct 24, 2026
…start, timed wait, clock and processor count calls

Dropped the PR's copy of boykopovar#8885 (already in our tree); took _Thrd_start, _Cnd_timedwait, now_v1_compat, the create/condTimedwait/getAffinity forwards and the PR's affinity-mask _Thrd_hardware_concurrency over ours (host count, CxxAbiSupport.cpp), so guest_hardware_concurrency (host-count test) is removed; removed two stale duplicate _Pad debt bullets.
@edubox edubox mentioned this pull request Oct 24, 2026
12 tasks done
@adriadam10 adriadam10 self-assigned this Oct 25, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

@AlxcBTW this conflicts with main now (libkernel/Pthread/Posix/Thread.cpp, tests/GuestLibcThreads.cpp, docs/dev/debt/libc.md). Since this branch was opened, main has implemented _Xtime_get_ticks and scePthreadCondTimedwait, so please keep main's versions when rebasing instead of adding a second definition. Could you also say in the description how _Thrd_hardware_concurrency relates to orezraey's console measurement (5 in a payload process)?

This branch has not been deployed

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

Labels

docs libc libkernel needs rebase Conflicts with main, rebase needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants