Skip to content

feat(libkernel): implement pthread_mutex_getprioceiling and setprioceiling - #9326

Open
erickerxhalli wants to merge 5 commits into
boykopovar:mainfrom
erickerxhalli:feat/libkernel-mutex-prioceiling
Open

erickerxhalli wants to merge 5 commits into
boykopovar:mainfrom
erickerxhalli:feat/libkernel-mutex-prioceiling

Conversation

@erickerxhalli

@erickerxhalli erickerxhalli commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What

Implements pthread_mutex_getprioceiling, pthread_mutex_setprioceiling and their SCE twins scePthreadMutexGetprioceiling and scePthreadMutexSetprioceiling in libkernel; all four threw NotImplemented_nid_no_patch from libkernel_sys. They are declared once in libkernel/include/Api.hpp with their real signatures, and the four (void) discovery declarations are removed from libkernel_sys/include/Api.hpp.

scePthreadMutexInit now copies the attribute's protocol and ceiling into the mutex, so a mutex made through the SCE calls or through pthread_mutex_init (which calls it) gets them; scePthreadMutexattrSetprotocol stores the protocol since #8373. The getters return EINVAL (0x80020016 from the SCE twin) for a static, adaptive or destroyed handle or a mutex without PTHREAD_PRIO_PROTECT, before the output pointer is used. This, and the SCE path passing the protocol and ceiling on, follow firmware 13.42's libkernel_sys as BunnyFl reported in this PR; the checks match FreeBSD 11.4's _pthread_mutex_getprioceiling. A null mutex, or a null output for a priority-protected mutex, throws: the console dereferences it.

The set does the same checks, then, as FreeBSD's do_set_ceiling does in the kernel, takes the mutex unless the caller holds it, so it waits for another holder, and writes the previous ceiling when old_ceiling is given. On the console that part runs in the kernel (_umtx_op UMTX_OP_SET_CEILING), which the 13.42 dump does not contain, so it is recorded as unverified. FreeBSD rejects a ceiling above RTP_PRIO_MAX (31), a bound that does not fit the console's 256-767 SCHED_RR priorities, so a ceiling outside sched_get_priority_min(SCHED_RR) to sched_get_priority_max(SCHED_RR) throws. The SCE twins' signatures follow Orbital's db_types.json. Priority protection itself is still not applied. The gaps are under Functional in docs/dev/debt/libkernel.md.

The new guest_pthread_mutex_prioceiling test checks EINVAL and 0x80020016, with and without an output pointer, for a static, adaptive, default and destroyed mutex; the ceiling taken from a POSIX attribute; the set with and without the old-ceiling output; that 255 and 768 throw and leave the ceiling; the set while the caller holds the mutex and while another thread does. It also covers a mutex made entirely through the SCE calls (protocol 2 with ceiling 300, and protocols 0 and 1, which give EINVAL), a POSIX attribute passed to scePthreadMutexInit, and an SCE attribute passed to pthread_mutex_init, each read and written through the other API.

Tested

  • Linux (Ubuntu 24.04 container, GCC 13.3, Release, full build of the head commit addd914): ctest ran 2287 tests; 2275 passed, including guest_pthread_mutex_prioceiling, guest_pthread_mutexattr, guest_pthread_mutex_errors, guest_pthread_timed_locks, guest_pthread_destroyed_objects, guest_kernel_sys, patched_libraries and public_headers. The 12 failures come from the container, not this change: guest_net_protocol, guest_net_buffer_validation, guest_net_nodelay_readback, guest_sce_net_keepalive, guest_socket_options, guest_socket_stream_options, guest_socket_address_length and guest_tcp open AF_INET6 sockets and the container has no IPv6; agc_submit_progress, agc_submit_progress_no_timeline, agc_driver_pipelined_metadata_pass and agc_driver_pipelined_metadata_pass_draw_pipeline stop at vkCreateInstance (VK_ERROR_INCOMPATIBLE_DRIVER), as it has no Vulkan driver.
  • Mutation check on the head commit: removing the protocol and ceiling copy from scePthreadMutexInit, copying only the protocol, checking the output pointer before the protocol, returning 0 for a null output on a priority-protected mutex, or returning POSIX numbers from the SCE twins each makes guest_pthread_mutex_prioceiling fail. On the first commit, dropping the protocol check, the old-ceiling write, the owner check, the unlock or the range check each did too.
  • Windows (MinGW-w64 GCC 15.2.0 WinLibs, full build of addd914): build.yml with full=true, linux=false on my fork passed (run); the only skips were tests that need Vulkan or a display.

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

🤖 Generated with Claude Code

https://claude.ai/code/session_01WYjMwvLdPR8iX8EP8tQYWa

…iling

A mutex takes the protocol and ceiling of its attribute at init, and
pthread_mutex_getprioceiling, pthread_mutex_setprioceiling and their SCE
twins scePthreadMutexGetprioceiling and scePthreadMutexSetprioceiling
read and write it as FreeBSD 11.4 libthr and umtx do: EINVAL for a
static, adaptive or destroyed handle or a mutex without
PTHREAD_PRIO_PROTECT, and the set takes the mutex unless the caller
holds it and writes the previous ceiling. A ceiling outside the SCHED_RR
priority range throws, as the console's bound is unverified.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WYjMwvLdPR8iX8EP8tQYWa
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Progress report (9310f48 → 3aa61cb)

📈 System libraries: 26.58% (+0.02%, +4 implemented, -4 removed functions)

✅ 4 implemented
Library Name
libkernel pthread_mutex_getprioceiling_nid_postfix
libkernel pthread_mutex_setprioceiling_nid_postfix
libkernel scePthreadMutexGetprioceiling
libkernel scePthreadMutexSetprioceiling
🗑️ 4 removed
Library Name
libkernel_sys pthread_mutex_getprioceiling_nid_postfix
libkernel_sys pthread_mutex_setprioceiling_nid_postfix
libkernel_sys scePthreadMutexGetprioceiling
libkernel_sys scePthreadMutexSetprioceiling

Changed libraries (implemented exports)

Library Before After Change
libkernel 700/749 (93.46%) 704/753 (93.49%) +0.03%
libkernel_sys 127/833 (15.25%) 127/829 (15.32%) +0.07%

@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 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 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 6740 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 6830 core/libs/prx/libkernel/CMakeLists.txt
PR 6936 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 7088 docs/dev/debt/libkernel.md
PR 7090 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 7105 docs/dev/debt/libkernel.md
PR 7121 docs/dev/debt/libkernel.md
PR 7135 docs/dev/debt/libkernel.md
PR 7149 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 7156 core/libs/prx/libkernel/CMakeLists.txt
PR 7192 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 7447 docs/dev/debt/libkernel.md
PR 7464 docs/dev/debt/libkernel.md
PR 7509 docs/dev/debt/libkernel.md
PR 7532 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 7565 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 7804 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 8041 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/Pthread/include/Pthread.hpp
PR 8463 core/libs/prx/libkernel/CMakeLists.txt
PR 8477 core/libs/prx/libkernel/CMakeLists.txt
PR 8497 docs/dev/debt/libkernel.md
PR 8592 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
PR 8605 docs/dev/debt/libkernel.md
PR 9019 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 9097 core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 9156 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel_sys/Export.Discovery.cpp
docs/dev/debt/libkernel.md
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 9242 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 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 9491 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 9537 core/libs/prx/libkernel_sys/Export.Discovery.cpp
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 9684 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 9843 docs/dev/debt/libkernel.md
PR 9882 docs/dev/debt/libkernel.md
PR 9938 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 9947 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 10025 docs/dev/debt/libkernel.md
PR 10192 docs/dev/debt/libkernel.md
PR 10319 docs/dev/debt/libkernel.md
PR 10332 core/libs/prx/libkernel_sys/include/Api.hpp
PR 10335 core/libs/prx/libkernel_sys/Export.Discovery.cpp
PR 10421 core/libs/prx/libkernel_sys/Export.Discovery.cpp
PR 10442 docs/dev/debt/libkernel.md
PR 10552 docs/dev/debt/libkernel.md
PR 10558 docs/dev/debt/libkernel.md
PR 10645 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 10657 core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 10749 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 10755 core/libs/prx/libkernel/CMakeLists.txt
PR 10789 docs/dev/debt/libkernel.md
PR 10806 core/libs/prx/libkernel/CMakeLists.txt
PR 10810 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 10816 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 10817 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 10953 core/libs/prx/libkernel/CMakeLists.txt
PR 10979 core/libs/prx/libkernel/CMakeLists.txt
PR 11002 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 11031 core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 11034 core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 11042 docs/dev/debt/libkernel.md
PR 11212 core/libs/prx/libkernel_sys/Export.Discovery.cpp
PR 11215 core/libs/prx/libkernel/include/Api.hpp
docs/dev/debt/libkernel.md
PR 11216 core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 11219 docs/dev/debt/libkernel.md
PR 11223 docs/dev/debt/libkernel.md
PR 11247 docs/dev/debt/libkernel.md
PR 11446 core/libs/prx/libkernel/CMakeLists.txt
PR 11624 docs/dev/debt/libkernel.md
PR 11625 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 11628 docs/dev/debt/libkernel.md
PR 11661 docs/dev/debt/libkernel.md
PR 11689 docs/dev/debt/libkernel.md
PR 11698 docs/dev/debt/libkernel.md
PR 11849 docs/dev/debt/libkernel.md
PR 11851 core/libs/prx/libkernel/CMakeLists.txt
PR 11891 core/libs/prx/libkernel/CMakeLists.txt
PR 11894 core/libs/prx/libkernel/CMakeLists.txt
PR 11896 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 12078 core/libs/prx/libkernel/CMakeLists.txt
PR 12104 docs/dev/debt/libkernel.md
PR 12130 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
core/libs/prx/libkernel/Pthread/src/Mutex.cpp
core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 12139 core/libs/prx/libkernel/CMakeLists.txt
PR 12149 core/libs/prx/libkernel/CMakeLists.txt
PR 12170 docs/dev/debt/libkernel.md
PR 12202 docs/dev/debt/libkernel.md
PR 12506 core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 12544 core/libs/prx/libkernel/CMakeLists.txt
PR 12560 docs/dev/debt/libkernel.md
PR 12642 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
core/libs/prx/libkernel/Pthread/src/Mutex.cpp
core/libs/prx/libkernel_sys/Export.Discovery.cpp
core/libs/prx/libkernel_sys/include/Api.hpp
PR 12682 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 12688 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 12700 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 12741 docs/dev/debt/libkernel.md
PR 12826 core/libs/prx/libkernel/CMakeLists.txt
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 12854 docs/dev/debt/libkernel.md
PR 12868 core/libs/prx/libkernel/CMakeLists.txt
PR 12908 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 12922 docs/dev/debt/libkernel.md
PR 12925 docs/dev/debt/libkernel.md
PR 12965 core/libs/prx/libkernel/CMakeLists.txt
core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 12970 core/libs/prx/libkernel/CMakeLists.txt
docs/dev/debt/libkernel.md
PR 13224 docs/dev/debt/libkernel.md
PR 13336 docs/dev/debt/libkernel.md
PR 13499 core/libs/prx/libkernel/include/Api.hpp
PR 13504 docs/dev/debt/libkernel.md
PR 13506 docs/dev/debt/libkernel.md
PR 13507 docs/dev/debt/libkernel.md
PR 13552 docs/dev/debt/libkernel.md
PR 13556 docs/dev/debt/libkernel.md
PR 13560 docs/dev/debt/libkernel.md
PR 13576 docs/dev/debt/libkernel.md
PR 13577 docs/dev/debt/libkernel.md
PR 13582 docs/dev/debt/libkernel.md
PR 13587 docs/dev/debt/libkernel.md
PR 13598 docs/dev/debt/libkernel.md
PR 13600 docs/dev/debt/libkernel.md
PR 13660 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 13678 core/libs/prx/libkernel/include/Api.hpp
PR 13695 docs/dev/debt/libkernel.md
PR 13710 core/libs/prx/libkernel/CMakeLists.txt
PR 13725 core/libs/prx/libkernel/Pthread/src/Mutex.cpp
docs/dev/debt/libkernel.md

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

Checked against main 4a17c71 and FreeBSD libthr thr_mutex.c (_pthread_mutex_getprioceiling/_setprioceiling) and kern_umtx.c do_set_ceiling:

  • The POSIX checks match FreeBSD as far as I can see. Handles <= 2 and non-PRIO_PROTECT mutexes return EINVAL, the set takes the lock unless the caller already owns it, and old_ceiling is written only when non-null. Throwing outside 256..767 instead of applying RTP_PRIO_MAX seems reasonable, and it is recorded in the debt file.
  • The SCE twins can't succeed for a mutex made through the SCE API. scePthreadMutexattrSetprotocol (src/Mutex.cpp:149) validates the protocol and discards it, and scePthreadMutexInit (src/Mutex.cpp:159-166) copies only the type. The protocol and ceiling are copied only in pthread_mutex_init (Posix/Mutex.cpp:68-71). So scePthreadMutexattrSetprotocol(&a, 2) + scePthreadMutexInit(&m, &a, "m") + scePthreadMutexGetprioceiling(&m, &c) returns 0x80020016 for a mutex the title asked to be PRIO_PROTECT. The same happens with pthread_mutexattr_setprotocol + scePthreadMutexInit.
  • Suggested fix: store the protocol in scePthreadMutexattrSetprotocol, resetting the ceiling as pthread_mutexattr_setprotocol does, and move the protocol/ceiling copy into scePthreadMutexInit next to SetType. Then both init paths agree, and the "scePthreadMutexInit copies none" debt sentence can go. A test that creates the mutex through the SCE calls would cover it.
  • The PR text says the mutex takes its attribute's protocol and ceiling "in scePthreadMutexInit". The code does it only in pthread_mutex_init.

Reviewed with AI assistance (Claude Code); the checks above were run locally on my machine.

@cadenasynyster

cadenasynyster commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Windows run with a baseline.

Head 8a82455 merged onto main 1a745ae (clean). Windows 11 10.0.26300, WinLibs MinGW-w64 GCC 15.2.0 r7, CMake + Ninja, Release, -DBUILD_TESTING=ON.

With this PR, one run each: guest_pthread_mutex_prioceiling, guest_pthread_mutexattr, guest_pthread_mutex_errors, guest_pthread_timed_locks, guest_pthread_destroyed_objects, guest_kernel_sys all pass.

Baseline: with this PR's test and CMake but Pthread/Posix/Mutex.cpp, Pthread/include/Pthread.hpp and libkernel_sys/Export.Discovery.cpp taken from main, guest_pthread_mutex_prioceiling_tests.exe fails to link. The four missing symbols are pthread_mutex_getprioceiling_nid_postfix, pthread_mutex_setprioceiling_nid_postfix, scePthreadMutexGetprioceiling and scePthreadMutexSetprioceiling. No other target failed to build.

check_conventions.py --base origin/main passes.

Not run: the full CTest suite, repeated runs, Linux and macOS, a title, and pr_overlap.py. I did not check the overlap with #9713 that the bot lists. The baseline shows the test needs the new exports, not that the semantics match FreeBSD; I did not review those.

AI-assisted: yes, results above were run on this machine.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

@erickerxhalli Protocol and ceiling are copied only in Pthread/Posix/Mutex.cpp:69–70. Pthread/src/Mutex.cpp:149–157 discards the SCE protocol attribute, and :159–170 copies only type when creating the mutex, so an SCE-created PRIO_PROTECT mutex is rejected by the new accessors. Could you store/copy these attributes through the shared SCE path and add SCE-created and mixed POSIX/SCE regression cases, retaining the current POSIX tests?

danielradosa added a commit to danielradosa/AnyPS5 that referenced this pull request Oct 24, 2026
…getprioceiling and setprioceiling

Took the PR's four exports and test as is; removed our four libkernel_sys Export.Discovery stubs by hand (the patch hunks landed on neighbouring stubs) and kept both sides' libkernel.md entries.
@oneandonlydean

Copy link
Copy Markdown
Collaborator

@erickerxhalli The local declarations differ from main’s public headers: int pthread_mutex_getprioceiling_nid_postfix(const PthreadMutex* mutex, int* prioceiling) at core/libs/tests/GuestPthreadMutexPrioceiling.cpp:18 versus int pthread_mutex_getprioceiling_nid_postfix(void) at core/libs/prx/libkernel_sys/include/Api.hpp:136; int pthread_mutex_setprioceiling_nid_postfix(PthreadMutex* mutex, int ceiling, int* oldCeiling) at core/libs/tests/GuestPthreadMutexPrioceiling.cpp:19 versus int pthread_mutex_setprioceiling_nid_postfix(void) at core/libs/prx/libkernel_sys/include/Api.hpp:139; int scePthreadMutexGetprioceiling(PthreadMutex* mutex, int* prioceiling) at core/libs/tests/GuestPthreadMutexPrioceiling.cpp:20 versus int scePthreadMutexGetprioceiling(void) at core/libs/prx/libkernel_sys/include/Api.hpp:513; int scePthreadMutexSetprioceiling(PthreadMutex* mutex, int ceiling, int* oldCeiling) at core/libs/tests/GuestPthreadMutexPrioceiling.cpp:21 versus int scePthreadMutexSetprioceiling(void) at core/libs/prx/libkernel_sys/include/Api.hpp:516. Main now requires each exported function to be declared once, in the library's public header (checked by the public_headers tests). Could you use main’s public signatures and types throughout the implementation and tests, or explain why the public declarations need to change?

@BunnyFl

BunnyFl commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

Firmware check of the four calls, against libkernel_sys.sprx from firmware 13.42, since the checks here follow FreeBSD. libkernel.sprx gives the same results. I ran the calls in an emulator on the module itself, with attributes and mutexes created by the module's own pthread_mutexattr_* / scePthreadMutexattr* and pthread_mutex_init / scePthreadMutexInit.

  • SCE path (the point raised above): scePthreadMutexInit passes its attribute straight to the module's pthread_mutex_init, so an SCE-created mutex gets the protocol and ceiling the same way a POSIX one does. With scePthreadMutexattrSetprotocol(2) and scePthreadMutexattrSetprioceiling(300), the mutex has the priority-protect flag. Then scePthreadMutexGetprioceiling returns 0 with 300, and pthread_mutex_getprioceiling on the same mutex returns 0 with 300. With protocol 0 or 1, both getters return EINVAL / 0x80020016.
  • Get: a static (0), adaptive (1) or destroyed (2) handle, or a mutex without priority protection, gives EINVAL (22). The SCE twins give that plus 0x80020000 (0x80020016), as in this PR. These checks come before the output pointer is used, so pthread_mutex_getprioceiling(&m, nullptr) on a mutex without priority protection returns 22 rather than failing. That's the Throws(... getprioceiling(&mutex, nullptr)) line in CheckWithoutPriorityProtection, which this PR expects to throw. The output is only written for a priority-protected mutex. A null mutex pointer is read without a check.
  • Set: after the same handle and flag checks, the module makes the _umtx_op system call with UMTX_OP_SET_CEILING (7), passing the new ceiling and the old_ceiling pointer. It doesn't check the range, take the mutex or write old_ceiling itself. Those are done by the kernel, which isn't in this dump. So the 256–767 bound, waiting for another holder and the old-ceiling write can't be confirmed or contradicted from 13.42.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

@erickerxhalli two things. @BunnyFl's firmware run shows that pthread_mutex_getprioceiling(&m, nullptr) on a mutex without priority protection returns EINVAL before the output pointer is used. Could you make it do that, and replace the Throws(...) line in CheckWithoutPriorityProtection with an EINVAL check? (The SCE twin gives 0x80020016.) The set path's range, holder and old-ceiling behaviour depends on the kernel, so keep that in debt as unverified. Also, the header ask from my last comment is still open: please declare the four functions once, with these signatures, in libkernel_sys/include/Api.hpp and drop the test's local declarations.

erickerxhalli and others added 2 commits October 25, 2026 21:53
scePthreadMutexInit now copies the attribute's protocol and ceiling,
so a mutex made through the SCE calls, or through pthread_mutex_init,
which calls it, is priority-protected when its attribute says so. The
prioceiling getters check the handle and protocol before the output
pointer and return EINVAL for a mutex without priority protection
even with a null output, as firmware 13.42's libkernel_sys does.

The four functions are declared once in libkernel's Api.hpp with their
signatures, replacing the (void) discovery declarations in
libkernel_sys's Api.hpp and the test's local declarations. The test
adds SCE-created and mixed POSIX/SCE mutexes, and the debt entries
record the set path's kernel side as unverified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WYjMwvLdPR8iX8EP8tQYWa
@erickerxhalli

Copy link
Copy Markdown
Contributor Author

Thanks all, and thanks @BunnyFl for the 13.42 trace. Addressed in addd914, after merging main (which brought #8373) into the branch in 255253e:

  • SCE path (@oneandonlydean, @harisibrar1): scePthreadMutexInit now copies the attribute's protocol and ceiling, so a mutex made through the SCE calls gets them, and pthread_mutex_init gets them through it. The test adds a mutex made entirely through the SCE calls (protocol 2 with ceiling 300 returns 0 and 300; protocols 0 and 1 return EINVAL / 0x80020016), plus a POSIX attribute passed to scePthreadMutexInit and an SCE attribute passed to pthread_mutex_init, each read and written through the other API. The existing POSIX cases are kept.
  • Null output: the getters now check the handle and protocol before the output pointer, so pthread_mutex_getprioceiling(&m, nullptr) on a mutex without priority protection returns EINVAL, and the SCE twin returns 0x80020016. The Throws(...) line is replaced by those checks. A null output on a priority-protected mutex still throws, since the console writes through it.
  • Declarations: the four functions are declared once in libkernel/include/Api.hpp with their real signatures, and the test's local declarations are gone. They live in libkernel, not libkernel_sys, because this PR moves them out of the libkernel_sys discovery stubs, so I removed the four (void) declarations from libkernel_sys/include/Api.hpp instead of changing them there. public_headers passes.
  • Debt file: the set's range check, wait for another holder and old-ceiling write are now recorded as done by the console's kernel (UMTX_OP_SET_CEILING) and unverified. The get-path checks and the SCE path cite the 13.42 results here. The PR description is updated to match.

Re-run on addd914: full Linux ctest passes except 12 container-only failures (no IPv6, no Vulkan driver), and Windows passed. The mutation checks now also cover the SCE copy and the check order.


Generated by Claude Code

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

Copy link
Copy Markdown
Collaborator

@erickerxhalli The branch had conflicts with main, so I merged main into it to keep it moving. There's one merge commit, and your changes are as they were. Main had implemented pthread_mutex_setname_np while your branch implements the prioceiling pair, and each side removed its own libkernel_sys stub. So all three declarations now sit in prx/libkernel/include/Api.hpp, neither stub remains, and the mutex keeps both your protocol/ceiling fields and main's name fields. Full CI on the new head follows. If you'd rather rebase it yourself, feel free to replace it.

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

Copy link
Copy Markdown
Contributor Author

Thanks @oneandonlydean, your merge is fine by me, no need for me to rebase. I checked 2b29ac8: the diff against main is just this PR’s files, all four functions are declared once in libkernel/include/Api.hpp, and public_headers and the conventions check pass. Is there anything else you’d like changed before it can go in?

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

Copy link
Copy Markdown
Collaborator

@erickerxhalli no, nothing else is needed from you; thanks for checking the merge. Since then main has changed libkernel_sys again, so the branch conflicts in Export.Discovery.cpp and include/Api.hpp. We'll merge main in once more the same way, keeping your functions as they are, and then run the full CI on that head before merging.

…x-prioceiling

# Conflicts:
#	core/libs/prx/libkernel_sys/Export.Discovery.cpp
#	core/libs/prx/libkernel_sys/include/Api.hpp

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

build docs libkernel needs rebase Conflicts with main, rebase needed prx

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants