Skip to content

fix(libkernel): report thread attribute inheritance and null-output errors as measured on a PS5 - #10130

Merged
adriadam10 merged 8 commits into
boykopovar:mainfrom
orezraey:fix/libkernel-pthread-attr-measured-ps5
Oct 26, 2026
Merged

adriadam10 merged 8 commits into
boykopovar:mainfrom
orezraey:fix/libkernel-pthread-attr-measured-ps5

Conversation

@orezraey

@orezraey orezraey commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

What

Thread-attribute edge cases measured on a retail PS5 (firmware 13.60) with three homebrew probes calling libkernel_sys.sprx from a payload process. The sources and console logs are in this gist (pcond, pcond2, pattr).

The condition-variable change moved to #10177, as requested in review.

scePthreadAttrGet reports the inheritance a thread was created with: 0 for an explicit-scheduling thread and 4 for an inheriting one or one created from a freshly initialised attribute. Before, it always reported 4. pthread_attr_get_np now copies the same inheritance, as FreeBSD's copies the whole attribute; before, it left the caller's value. A null attribute at creation was not measured. The policy and priority it reports already matched:

  • the creator's for an inheriting thread (1 and 700 here, even when the attribute said round-robin 700);
  • the attribute's for an explicit one.

scePthreadAttrGetinheritsched with a null output returns EINVAL, as scePthreadAttrGetschedpolicy does. Before, it threw. Both also return EINVAL for a null or uninitialized attribute, which AnyPS5 already did. A new attribute holds policy 1, inheritance 4 and priority 700, also as before.

Already matching, so nothing in this diff changes them:

  • scePthreadCondTimedwait returns EPERM (0x80020001) for an unowned mutex of each type (default, error-checking, recursive, normal, adaptive), the adaptive static initializer (slot 1), a null slot and a mutex held by another thread.
  • It returns EINVAL for the destroyed mutex (slot 2).
  • It times out with 0x8002003c, also for 0 µs.
  • A recursive mutex locked twice is released completely during the wait (another thread's trylock succeeds) and relocked to depth 2.

The debt entries are updated.

Not modelled: a slot of 2 or 3 crashed the console's condition calls, and so does AnyPS5, which dereferences it. pthread_attr_get_np returned EINVAL for the payload's main thread, so its answer for other threads stays unmeasured.

Tested

Windows 11, MinGW (winlibs), and Linux (Ubuntu on WSL 2, GCC), at head 3345e2047d (main merged in after #9573, keeping its createSuspended field next to this PR's inheritance).

  • guest_pthread_attr checks the inheritance scePthreadAttrGet and pthread_attr_get_np report for an explicit and an inheriting thread.
  • guest_pthread_attr_errors checks EINVAL for a null scePthreadAttrGetinheritsched output.
  • These are the only tests this diff changes. Both fail with main's Pthread sources and pass with this branch's.
  • The thread and attribute tests pass three runs in a row on both systems: guest_pthread_attr, guest_pthread_attr_errors, guest_pthread_attr_stack, guest_pthread_create_suspended, guest_pthread_schedparam, guest_pthread_start, guest_pthread_join_detach and guest_kernel_sys_thread_defaults.
  • The condition-variable tests, including guest_pthread_destroyed_objects, belong to fix(libkernel): mark a destroyed condition variable with 1 and accept destroying a null one, as measured on a PS5 #10177 and are reported there.
  • tools/check_conventions.py passes.

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 (feat(libkernel_sys): create threads suspended and resume them #9573, which edited the same lines, has merged and this PR is refreshed over it)
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

orezraey and others added 5 commits October 22, 2026 20:47
…ibute queries as measured on a PS5

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

@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 PS5 probe evidence supports the destroyed condition marker, null-destroy behavior, inherited scheduling query, and null-output error changes; GCC 12.2 syntax checks passed for the changed implementation and tests, as did conventions, diff-check, and main-sync (5 ahead/29 behind; merge clean). The author reports the three directly affected tests and 14 related Windows thread/condition tests passing three times. Please split the condition-variable changes (Cond.cpp and destroyed-object tests) from the independent thread-attribute changes (Attr.cpp, inheritance state/query tests) into separate topic branches, as required by the repository’s one-branch-per-topic rule. The attribute portion also conflicts with open PR #10133 in docs/dev/debt/libkernel.md; coordinate a single combined entry and landing order with that author, preserving both sets of measured attribute behavior. Add Depends on if either branch needs the other first, then refresh and rerun focused tests and checks. Hosted policy checks pass; product jobs are skipped by the workflow.

@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 6740 docs/dev/debt/libkernel.md L78-80

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/Pthread/src/Thread.cpp
PR 4563 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
core/libs/prx/libkernel/Pthread/src/Thread.cpp
PR 4630 docs/dev/debt/libkernel.md
PR 5021 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
core/libs/prx/libkernel/Pthread/src/Thread.cpp
docs/dev/debt/libkernel.md
PR 6149 docs/dev/debt/libkernel.md
PR 6936 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
core/libs/prx/libkernel/Pthread/src/Thread.cpp
docs/dev/debt/libkernel.md
PR 7192 docs/dev/debt/libkernel.md
PR 7201 core/libs/prx/libkernel/Pthread/src/Thread.cpp
PR 7447 docs/dev/debt/libkernel.md
PR 7509 docs/dev/debt/libkernel.md
PR 7804 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
core/libs/prx/libkernel/Pthread/src/Thread.cpp
docs/dev/debt/libkernel.md
PR 8010 docs/dev/debt/libkernel.md
PR 8592 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
core/libs/prx/libkernel/Pthread/src/Thread.cpp
PR 8605 docs/dev/debt/libkernel.md
PR 9156 docs/dev/debt/libkernel.md
PR 9199 docs/dev/debt/libkernel.md
PR 9284 docs/dev/debt/libkernel.md
PR 9293 docs/dev/debt/libkernel.md
PR 9297 docs/dev/debt/libkernel.md
PR 9302 docs/dev/debt/libkernel.md
PR 9389 docs/dev/debt/libkernel.md
PR 9491 docs/dev/debt/libkernel.md
PR 9509 docs/dev/debt/libkernel.md
PR 9557 docs/dev/debt/libkernel.md
PR 9566 docs/dev/debt/libkernel.md
PR 9575 docs/dev/debt/libkernel.md
PR 9947 docs/dev/debt/libkernel.md
PR 10105 docs/dev/debt/libkernel.md
PR 10179 docs/dev/debt/libkernel.md
PR 10385 core/libs/prx/libkernel/Pthread/include/Pthread.hpp
docs/dev/debt/libkernel.md
PR 10442 docs/dev/debt/libkernel.md
PR 10552 docs/dev/debt/libkernel.md
PR 10621 docs/dev/debt/libkernel.md
PR 10848 docs/dev/debt/libkernel.md
PR 11085 docs/dev/debt/libkernel.md
PR 11264 docs/dev/debt/libkernel.md
PR 11267 docs/dev/debt/libkernel.md

@BunnyFl

BunnyFl commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

I checked the condition-variable and scePthreadAttrGetinheritsched parts against the PS5 firmware 13.42 libkernel and libkernel_sys modules, running them in an emulator (head e2b8771). Both modules give the same results, and they match this PR.

  • scePthreadCondDestroy on a condition object stores 1 in the slot and returns 0. On a null slot it returns 0 and leaves the slot null.
  • With the slot holding 1, scePthreadCondDestroy, scePthreadCondSignal, scePthreadCondBroadcast, scePthreadCondWait and scePthreadCondTimedwait all return 0x80020016 and leave the slot at 1.
  • scePthreadAttrGetinheritsched returns 0x80020016 for a null attribute, an uninitialized one and a null output. Otherwise it writes the stored inheritance and returns 0.

I didn't run scePthreadAttrGet: its copy of the thread's attribute uses AVX instructions the emulator doesn't support.

AI-assisted: yes (Claude Code).

…l request

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@orezraey orezraey changed the title fix(libkernel): follow the destroyed condition marker and thread attribute queries as measured on a PS5 fix(libkernel): report thread attribute inheritance and null-output errors as measured on a PS5 Oct 23, 2026
@orezraey

Copy link
Copy Markdown
Contributor Author

@MarcZX10 Split as requested: the condition-variable change is now #10177. For the attribute debt conflict, #10133 now carries this branch and combines both entries, so this one lands first. @BunnyFl thanks for the 13.42 check; #10177 cites it.

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

Re-review of current head 886a2b249cf0dcbe75f954e89dbdaadea960e1ef. The condition-variable implementation and its test were successfully moved out to #10177, leaving the thread-attribute behavior as this PR's topic. #10133 now declares Depends on: #10130, so the debt-file landing order is recorded. The remaining review issue is that this PR's Tested section still attributes guest_pthread_destroyed_objects and the condition-variable cases to this change, and says all three affected tests fail on main and pass with it. Those condition changes are no longer in this PR's file diff; please update the test report to identify the attribute tests actually changed here and distinguish any checks that now belong to #10177. The focused attribute evidence can remain; the report should match the exact current diff. Hosted product jobs are path-skipped.

@orezraey

Copy link
Copy Markdown
Contributor Author

@MarcZX10 Updated the Tested section to the current head 886a2b249c. It now lists only guest_pthread_attr and guest_pthread_attr_errors, the two tests this diff changes; I rebuilt with main's Pthread sources to confirm both fail there and pass with the branch. The condition-variable tests, including guest_pthread_destroyed_objects, are now reported only on #10177. The scePthreadCondTimedwait notes in What are now labelled as already matching, since nothing here changes them.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 24, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 24, 2026
@orezraey

Copy link
Copy Markdown
Contributor Author

@zaryabzip: #9573 changes the same lines as this PR in core/libs/prx/libkernel/Pthread/Posix/Attr.cpp and core/libs/prx/libkernel/Pthread/src/Attr.cpp (git merge-tree of both heads over current main conflicts there). I propose it lands first; I will then merge main into this branch, keeping both sides' behaviour, and rerun its tests. Depends on now lists it (merge order only).

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 25, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 25, 2026
@adriadam10 adriadam10 self-assigned this Oct 26, 2026
@adriadam10
adriadam10 dismissed MarcZX10’s stale review October 26, 2026 14:23

Dismissing a stale review: the requested changes were addressed after it (new head) and the merge queue blocks on it. Please request changes again if anything is still open.

@adriadam10
adriadam10 merged commit 7903201 into boykopovar:main Oct 26, 2026
11 of 12 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the inheritance reported by scePthreadAttrGet and pthread_attr_get_np (explicit 0, inheriting/default 4), the EINVAL for a null scePthreadAttrGetinheritsched output, both tests (they fail on main's sources) and the debt entries against the measurements in the description; the condition-variable change is gone to #10177 and the Tested section matches the head; merged.

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.

4 participants