Skip to content

feat(libkernel): implement pthread_mutex_setname_np, pthread_rwlock_setname_np and pthread_barrier_setname_np - #10385

Merged
oneandonlydean merged 6 commits into
boykopovar:mainfrom
alvaroelpob:feat/libkernel-pthread-setname
Oct 26, 2026
Merged

oneandonlydean merged 6 commits into
boykopovar:mainfrom
alvaroelpob:feat/libkernel-pthread-setname

Conversation

@alvaroelpob

@alvaroelpob alvaroelpob commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

What

Implements pthread_mutex_setname_np, pthread_rwlock_setname_np and pthread_barrier_setname_np in libkernel, one commit each, and removes their throwing stubs from the libkernel_sys discovery exports. This follows #9962, which does the same for pthread_cond_setname_np.

BunnyFl's run of firmware 13.42's libkernel.sprx on a PC settles most of the behaviour. The module dereferences the object first, then passes name to the kernel's namedobj_create and stores the returned id; a second call on a named object returns EAGAIN (35) without a syscall. A null name goes to the kernel unchecked, so its result is unmeasured.

Export Implemented Throws
pthread_mutex_setname_np(mutex, name) initialized mutex: copies name and returns 0; once named, every later call returns EAGAIN and keeps the name. Null name (unmeasured): returns 0 and leaves the mutex unnamed null mutex pointer (faults in the module), statically initialized mutex and destroyed mutex (unmeasured)
pthread_rwlock_setname_np(rwlock, name) initialized lock: copies name and returns 0; once named, EAGAIN. Null name (unmeasured): returns EINVAL, following shadPS4 null lock pointer, statically initialized lock and destroyed lock, which fault in the module
pthread_barrier_setname_np(barrier, name) initialized barrier: copies name and returns 0; once named, EAGAIN. Null name (unmeasured): returns 0 and leaves the barrier unnamed null barrier pointer, unset barrier and destroyed barrier, which fault in the module

The console keeps the kernel's id, not the string; here the name is copied under the object's lock (the mutex initialization lock, the rwlock state mutex, or the barrier mutex) and nothing reads it back. Each function has its own debt entry with these gaps.

Tested

Ubuntu (WSL2, kernel 6.18), GCC 15.2.0, Release, full build with BUILD_TESTING=ON on main aca451e.

  • New guest_pthread_setname test. Each commit adds the block for its function, and each commit was built and its test and check_conventions.py run on its own. After cf2aa7c it checks, for each of the three objects, a first rename (read back from the object), EAGAIN with the name unchanged for a later rename (also while the mutex is locked, the rwlock read-locked, or after a barrier wait), and a throw for a null pointer and a destroyed object, plus an unset rwlock and barrier.
  • nm -D on the built libkernel.prx shows the three exports.
  • Full ctest -j16 at the last commit: 1992/1993 pass. agc_driver_multisample_retirement fails the same way on main on this machine.
  • Not tested: Windows, a title.
  • Rebased on main e7e3e9c, head 17dd582: since fix(libkernel): store only rwlock attribute types 1 and 2 #10173 merged, the branch conflicted in Rwlock.cpp. Main's refactor(libs): add full export headers for libs #10706 moved PthreadBarrierPrivate into libkernel/include/Api.hpp, so the barrier commit adds name there. 17dd582 (refactor(libkernel): declare the setname exports in the public header) declares the three exports with their real signatures in libkernel/include/Api.hpp, removes their (void) stubs from libkernel_sys/include/Api.hpp and drops the test's redeclarations, which public_headers now rejects. Full build and ctest -j16: 2202/2203 pass; agc_driver_multisample_retirement fails the same way on that main. check_conventions.py --base upstream/main passes.
  • Review fix ca27388 drops the static and adaptive-initializer cases from the mutex test. guest_pthread_setname passes; full build and ctest -j16 on main e7e3e9c: 2202/2203 pass; agc_driver_multisample_retirement fails the same way on that main. check_conventions.py --base upstream/main passes. Not tested: Windows.
  • Rebased on main 2dbe9b9, head b78878a, to resolve the conflicts from feat(libkernel): add pthread_rwlockattr_settype_np and scePthreadMutexattrSetkind #9632 and feat(libkernel): add pthread_cond_setname_np #9962 in libkernel_sys/Export.Discovery.cpp and libkernel_sys/include/Api.hpp; both sides' stub removals are kept. Review fix cf2aa7c follows the 13.42 run: a later rename of a named object returns EAGAIN, the null-name assertions are gone and the null name is marked unmeasured in the debt, and the inputs that fault in the module throw; the debt entries are rewritten. Full build and ctest -j16: 2370/2371 pass; agc_driver_multisample_retirement fails the same way on that main. check_conventions.py --base upstream/main passes. Not tested: Windows.

Checklist

Copilot AI balanced review requested due to automatic review settings October 23, 2026 20:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Progress report (b282541 → cf2aa7c)

📈 System libraries: 51.06% (+0.02%, +3 implemented, -3 removed functions)

✅ 3 implemented
Library Name
libkernel pthread_barrier_setname_np_nid_postfix
libkernel pthread_mutex_setname_np_nid_postfix
libkernel pthread_rwlock_setname_np_nid_postfix
🗑️ 3 removed
Library Name
libkernel_sys pthread_barrier_setname_np_nid_postfix
libkernel_sys pthread_mutex_setname_np_nid_postfix
libkernel_sys pthread_rwlock_setname_np_nid_postfix

Changed libraries (implemented exports)

Library Before After Change
libkernel 686/725 (94.62%) 689/728 (94.64%) +0.02 pp
libkernel_sys 85/525 (16.19%) 85/522 (16.28%) +0.09 pp

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

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.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 11230 docs/dev/debt/libkernel.md L290-291

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 4563 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/Pthread/include/Pthread.hpp
PR 4630 docs/dev/debt/libkernel.md
PR 5021 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 6149 docs/dev/debt/libkernel.md
PR 6936 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 7088 docs/dev/debt/libkernel.md
PR 7105 docs/dev/debt/libkernel.md
PR 7121 docs/dev/debt/libkernel.md
PR 7149 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 7192 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 7201 core/libs/prx/libkernel/CMakeLists.txt
PR 7447 docs/dev/debt/libkernel.md
PR 7509 docs/dev/debt/libkernel.md
PR 7804 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 8592 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
PR 8605 docs/dev/debt/libkernel.md
PR 8916 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9097 core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 9161 core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 9162 core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 9199 docs/dev/debt/libkernel.md
PR 9284 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel_sys/Export.Discovery.cpp
docs/dev/debt/libkernel.md
PR 9293 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel_sys/Export.Discovery.cpp
docs/dev/debt/libkernel.md
PR 9297 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel_sys/Export.Discovery.cpp
docs/dev/debt/libkernel.md
PR 9302 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel_sys/Export.Discovery.cpp
docs/dev/debt/libkernel.md
PR 9383 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel_sys/Export.Discovery.cpp
PR 9389 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel_sys/Export.Discovery.cpp
docs/dev/debt/libkernel.md
PR 9442 core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
docs/dev/debt/libkernel.md
PR 9557 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9566 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9575 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9713 core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 9947 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 10442 docs/dev/debt/libkernel.md
PR 10657 core/libs/prx/libkernel_sys/Export.Discovery.cpp
PR 10749 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 11002 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 11032 core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 11042 docs/dev/debt/libkernel.md
PR 11085 docs/dev/debt/libkernel.md
PR 11215 core/libs/prx/libkernel/include/Api.hpp
docs/dev/debt/libkernel.md
PR 11223 docs/dev/debt/libkernel.md
PR 11264 docs/dev/debt/libkernel.md
PR 11267 core/libs/prx/libkernel/include/Api.hpp
core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
docs/dev/debt/libkernel.md
PR 11341 docs/dev/debt/libkernel.md

@cadenasynyster

Copy link
Copy Markdown
Contributor

Ran this on Windows 11 (WinLibs GCC 15.2.0, Ninja), merging the PR head (7a05396) onto current main (dcd7e3a). The merge is clean.

Built and ran every pthread test that has a build target: 28 of 28 passed, including guest_pthread_setname and the neighbouring guest_pthread_barrier, guest_pthread_rwlock, guest_pthread_mutex_errors and guest_pthread_destroyed_objects.

tools/check_conventions.py --base origin/main passes and git diff --check is clean.

Not run: guest_pthread_cancel_recovery_coarse (no build target here), the full ctest run, a baseline without the PR (the new test needs the PR's code to build), a title, Linux and macOS.

@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.

Reviewed the full three-function diff at 7a05396, including the pthread object state, lock coverage, discovery-export removal, tests and debt entries. The invalid/static/destroyed cases are handled consistently with the source evidence described in the PR, and the behavior limits are recorded rather than guessed. The author reports the full Linux test result; the independent Windows report confirms all 28 built pthread tests pass, including the new setname test. Hosted Linux/Windows product builds are skipped by workflow policy, so I am not treating them as run. No blocking issue found.

@alvaroelpob

Copy link
Copy Markdown
Contributor Author

Depends on now also lists #9156: a local tools/pr_overlap.py run and git merge-tree show it conflicts with this PR in libkernel_sys/Export.Discovery.cpp, and it was opened first. No same exports.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 24, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

@alvaroelpob Since #10173 merged, this branch conflicts with main in Rwlock.cpp (one hunk). It still lands after #9156, so merging main once #9156 is in would save a second refresh. We'll run full CI on the resulting head.

@alvaroelpob

Copy link
Copy Markdown
Contributor Author

Agreed: I'll rebase on main once #9156 lands, which also resolves the Rwlock.cpp hunk from #10173. Depends on drops the merged #10173.

@alvaroelpob
alvaroelpob force-pushed the feat/libkernel-pthread-setname branch from 7a05396 to 17dd582 Compare October 25, 2026 05:32
@alvaroelpob

Copy link
Copy Markdown
Contributor Author

Rebased on main e7e3e9c, head 17dd582: since #10173 merged, the branch conflicted in Rwlock.cpp. Main's #10706 moved PthreadBarrierPrivate into libkernel/include/Api.hpp, so the barrier commit adds name there. 17dd582 declares the three exports in libkernel/include/Api.hpp (and drops their libkernel_sys stubs and the test's redeclarations), which public_headers now requires. Full suite 2202/2203, with the same failure on main. I rebased now rather than after #9156 because the branch conflicted; I'll rebase again when #9156 lands.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 25, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

@alvaroelpob Please drop the two new throw cases for the static and adaptive mutex initializers in GuestPthreadSetname.cpp:37 and :40. These are valid initializer forms, but naming them is intentionally unsupported, so the test should not pin that limitation. Keep supported naming and genuine null/destroyed-object validation, then rerun guest_pthread_setname and the mutex/rwlock/barrier regressions on Linux and Windows. The agreed #9156-first order still applies.

danielradosa added a commit to danielradosa/AnyPS5 that referenced this pull request Oct 25, 2026
…_setname_np, pthread_rwlock_setname_np and pthread_barrier_setname_np

Took the PR's three libkernel exports (they store the name) and its test; dropped our name-discarding mutex/rwlock copies from libkernel_sys/Pthread.cpp (libkernel_sys imports fall back to libkernel) and the barrier stub, kept our cond/sem setname and the GuestKernelSys checks, trimmed the libkernel_sys debt line to cond/sem.

(cherry picked from commit fae34fbcc2bf375603e70d3287c45b8122dabd9c)
@alvaroelpob

Copy link
Copy Markdown
Contributor Author

@oneandonlydean Dropped the static and adaptive initializer cases from the mutex test in ca27388; the supported naming, null-pointer and destroyed-mutex checks stay. On Linux (Ubuntu 26.04 WSL2, GCC 15.2.0) guest_pthread_setname passes, and the full ctest -j16 gives 2202/2203, including the mutex, rwlock and barrier tests; agc_driver_multisample_retirement fails the same way on main. I have no Windows machine for this one. The #9156-first order is unchanged.

@orezraey

Copy link
Copy Markdown
Contributor

@alvaroelpob #11230 removes the reltimed debt entries (now measured on a PS5) next to where this PR adds its entry in docs/dev/debt/libkernel.md, so git may report a conflict there. Whichever merges second keeps both; I'll rebase #11230 if this one lands first.

@wachi35676

Copy link
Copy Markdown
Contributor

Windows run, which the description doesn't cover. Head ca27388ae244 merged onto main 90f918fa7, WinLibs GCC 15.2.0, Release.

  • guest_pthread_setname passes 3/3: the mutex, rwlock and barrier rename paths, null names, the locked-mutex rename, and the throwing null/destroyed cases.

AI-assisted: yes (Claude Code); results above were run on this machine.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 26, 2026
@BunnyFl

BunnyFl commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

On "no console measurement or firmware disassembly settles these": I ran the three exports of firmware 13.42's libkernel.sprx (sha256 4be40bf838a46e1f…) in an x86-64 emulator. The objects come from the module's own pthread_mutex_init(&m, NULL), pthread_rwlock_init(&l, NULL) and pthread_barrier_init(&b, NULL, 2). Every syscall was logged. The harness answered syscall 0x22d (namedobj_create in the PS4 syscall table) with an id, or with a forced failure for one case, and 0x22e (namedobj_delete) with 0; the inits' other syscalls (getpid, sysctl, 0x24b) got 0, and allocations came from a zeroed pool. Three runs gave identical output.

All three functions work the same way, each on its own field:

field after init object type passed to the kernel
mutex +0x3c = 0xff010100 0x201
rwlock +0x28 = 0xff010300 0x203
barrier +0x40 = 0xff010400 0x204
  • First call on an initialized object: the module passes the caller's name pointer, the object and the type to syscall 0x22d (namedobj_create) and returns 0, storing id | type << 16 in the field (0x2011234 for id 0x1234). The name is not copied into the object. The mutex's name bytes at +0x50 stayed empty. A 40-character name went to the syscall unshortened.
  • A second call on the same object returns 0x23 without a syscall. That holds whenever the field is positive and not 0x5eaf00d, which is the case after a successful first call. Your test's second rename ("second"), and in the barrier block the nullptr and "second" calls after "first", would get 0x23 here wherever the kernel accepted the first call.
  • A null name is not checked in user space: it is passed to syscall 0x22d like any other pointer, so whether it is refused is up to the kernel. The rwlock's EINVAL for a null name and the mutex's "return 0, keep the name" do not come from this code.
  • When the syscall fails, the function returns the errno value (12 when the harness failed it with 12) and leaves the field at its init value.
  • The object pointer is dereferenced first, with no null check. (nullptr, …) faults reading address 0 at +0x7 in each function, including pthread_rwlock_setname_np(nullptr, nullptr) and pthread_barrier_setname_np(nullptr, "barrier"), which the test expects to return EINVAL. A handle that holds 0, 1 or 2 faults reading the field. That covers an unset or statically initialized rwlock or barrier stored as 0 (the test expects 0 for the rwlock and EINVAL for the barrier), the rwlock after pthread_rwlock_destroy (which set the handle to 1), and the barrier after pthread_barrier_destroy (which set it to 0; the test expects EINVAL).

Per the disassembly only (not reached in these runs): the mutex function has one more branch. When its field holds 0x5eaf00d, it copies at most 31 characters of name into the object at +0x50 (strncpy 0x20 bytes, terminator at +0x6f), copies a built-in default string when name is null, and returns 0 without a syscall. The rwlock and barrier functions have no copy. A field of 0x5eaf00d sends them to the syscall too.

Not covered: what the kernel's namedobj_create accepts or refuses (it was emulated here), a destroyed mutex (pthread_mutex_destroy stopped at its sceLibcHeapMutexFree import), and which code sets 0x5eaf00d.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

@BunnyFl Thanks, this is the kind of evidence these functions were missing. The second-call result (0x23 with no syscall) and the unchecked null name differ from what the current tests expect, so we're checking the PR's assertions against your results. @alvaroelpob please take a look too, particularly the repeated rename and the null-name cases.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

@alvaroelpob Thanks. BunnyFl's firmware 13.42 run (#10385 (comment)) settles part of what the debt entries call unverified, so a few changes, please:

  1. Once a mutex, rwlock or barrier has been named, the console returns 35 (EAGAIN) for every later setname call on it and changes nothing. Please make all three functions do that, and have the test expect 35 for the second and later calls (mutex "second" and "held", rwlock "read", barrier "second").
  2. A null name is passed to the kernel, so its result is unknown. Please remove the null-name assertions (GuestPthreadSetname.cpp:27, :40, :57) and mark the null name as unmeasured in the debt entries; the code can keep what it does now.
  3. A null object pointer, or an unset, statically initialised or destroyed rwlock/barrier, faults on the console. Refusing those on the host is fine, and the existing RequireThrows checks can stay, but please drop the checks that expect a return value for them (:44, :50, :60, :62, :64) and say in the debt that the console faults.
  4. The branch now conflicts with main in libkernel_sys/Export.Discovery.cpp and libkernel_sys/include/Api.hpp; please rebase.

@alvaroelpob
alvaroelpob force-pushed the feat/libkernel-pthread-setname branch from ca27388 to cf2aa7c Compare October 26, 2026 15:09
@alvaroelpob

Copy link
Copy Markdown
Contributor Author

@oneandonlydean @BunnyFl thanks. All four points are done; the head is now cf2aa7c.

  1. After a successful first call, the mutex, rwlock and barrier each return 35 (EAGAIN) for every later call and keep their name. The test expects 35 for the mutex's "second" and "held", the rwlock's "read" and the barrier's "second", and checks that the first name stays.
  2. The null-name assertions are removed, and each debt entry marks the null name as unmeasured. The code keeps its previous null-name results, with the named check first, as in the module.
  3. The return-value checks for faulting inputs are removed. A null pointer, an unset rwlock or barrier, and a destroyed object now throw in all three functions, so the barrier's and the unset rwlock's former EINVAL/0 results are gone. The RequireThrows checks cover them, and the debt entries say the module faults there. For a static or destroyed mutex the entry says the module's result is unmeasured, since the run didn't reach those cases.
  4. Rebased on main 2dbe9b9. feat(libkernel): add pthread_rwlockattr_settype_np and scePthreadMutexattrSetkind #9632 and feat(libkernel): add pthread_cond_setname_np #9962 are merged, so Depends on drops them.

The debt entries also say that the console stores the namedobj_create id, not the string. Removing the barrier's EAGAIN check makes the test fail. Full ctest -j16 is 2370/2371, with agc_driver_multisample_retirement failing the same way on main.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 26, 2026
@oneandonlydean
oneandonlydean merged commit ad1caa8 into boykopovar:main Oct 26, 2026
12 checks passed
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.

8 participants