Skip to content

docs(libkernel): record select limits as measured on a PS5 - #10310

Merged
adriadam10 merged 5 commits into
boykopovar:mainfrom
orezraey:docs/libkernel-select-measured-ps5
Oct 26, 2026
Merged

adriadam10 merged 5 commits into
boykopovar:mainfrom
orezraey:docs/libkernel-select-measured-ps5

Conversation

@orezraey

@orezraey orezraey commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

What

select measured on a retail PS5 (firmware 13.60) through libkernel_sys.sprx from a payload process. The source and console log are in this gist (pselect). The debt entry said the console's answer for a timeout outside the host clock's range was unknown.

The console:

  • accepts a timeout of INT32_MAX, 2^32 and INT64_MAX seconds (on a descriptor that is already ready, so the wait itself was not observed), and fails a negative tv_sec or tv_usec and a tv_usec of 1000000 or more with EINVAL, as AnyPS5 does;
  • leaves the timeout unchanged and fails a negative nfds with EINVAL, as AnyPS5 does;
  • clears a set descriptor at nfds when the timeout expires with nothing ready (nfds 16, descriptor 16), as FreeBSD writes back whole 64-bit fd_mask words, as AnyPS5 does since fix(libkernel): clear select bits from nfds to the end of their word #10777. With nfds 0 the bit stays set on both;
  • accepts an nfds of 1025, where AnyPS5 fails any nfds above 1024 with EINVAL, and fails with EBADF when a bit above its last open descriptor is set (measured with nfds 1000 and descriptor 999, where AnyPS5 also fails EBADF), as FreeBSD 11.4's select_check_badfd does. The probe's sets hold 1024 bits, so the results at nfds 1025 and 65536 depend on the bytes past them.

Only the debt entry changes: the last difference touches how far the guest's descriptor tables reach (files may go past the 1024 sockets), so it is recorded for a separate change.

Tested

Not tested: documentation only (head 59d248674f, which merges current main 14c99b52ac with #10501's pselect entry; the entry's "where AnyPS5 keeps it" clause was dropped earlier). 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: feat(libkernel_sys): implement sigqueue #9389, docs(debt): note how titles call inet_pton #10162 (merge order only: they edit the same lines; this PR is refreshed after them)
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the docs label Oct 23, 2026
@github-actions

github-actions Bot commented Oct 23, 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 4630 docs/dev/debt/libkernel.md
PR 5021 docs/dev/debt/libkernel.md
PR 6149 docs/dev/debt/libkernel.md
PR 6740 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 docs/dev/debt/libkernel.md
PR 7192 docs/dev/debt/libkernel.md
PR 7447 docs/dev/debt/libkernel.md
PR 7509 docs/dev/debt/libkernel.md
PR 7804 docs/dev/debt/libkernel.md
PR 8010 docs/dev/debt/libkernel.md
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 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 10442 docs/dev/debt/libkernel.md
PR 10499 docs/dev/debt/libkernel.md
PR 10552 docs/dev/debt/libkernel.md
PR 10621 docs/dev/debt/libkernel.md
PR 11042 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
PR 11341 docs/dev/debt/libkernel.md

@orezraey

Copy link
Copy Markdown
Contributor Author

@GitamarT045T3R @xXPBSXx: #9389 and #10162 change the same lines as this PR in docs/dev/debt/libkernel.md (git merge-tree of both heads over current main conflicts there). I propose they land first; I will then merge main into this branch, keeping both sides' behaviour, and rerun its tests. Depends on now lists them (merge order only).

@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 c9b7582 and the linked gist (pselect.c / pselect.log), plus Socket.cpp and SocketSelectDeadline.hpp on main:

  • The numbers in the new debt line match the log, and main's validation at Socket.cpp:189 matches the "as here" parts. The branch still merges cleanly with main.
  • One case in the log differs from AnyPS5, though the description says it matches. In nfds_below_fd (nfds 16, fd 16 set, timeout 0) the console returned 0 with the bit cleared (bit=0). Main returns 0 and leaves bit 16 set, because the timeout path (Socket.cpp:319-325) clears only the requested descriptors, all below nfds. FreeBSD's kern_select seems to copy out whole fd_mask words, which would explain it (and why nfds_0_ready left the bit alone). Could this go into the entry, or into a follow-up?
  • Small wording point: the EBADF was measured with nfds 1000 and fd 999, where AnyPS5 also gives EBADF; as written it reads like an nfds > 1024 result. Maybe "accepted 1025, and, like FreeBSD 11.4's select_check_badfd, fails EBADF for a set bit above the last open descriptor (measured with nfds 1000)".
  • Probe note: the sets are uint64_t set[16], so with nfds 1025 or 65536 the kernel reads bits past the array. "No EINVAL at 1025" stands, but the 1025 return of 1 and the 65536 EBADF depend on whatever stack bytes follow the array, so a re-probe with larger sets would pin them down.
  • Optional: how long the console actually waits on an out-of-range timeout is still unmeasured; keeping a plain "unknown" sentence would leave that open question visible.

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

… case as measured

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

Copy link
Copy Markdown
Contributor Author

@harisibrar1 thanks, you are right about nfds_below_fd. 9dd91b6f23 adds it to the entry (the console cleared descriptor 16 with nfds 16 on an expired timeout, where AnyPS5 keeps it; with nfds 0 both leave it), says the EBADF was measured with nfds 1000, where AnyPS5 agrees, notes that the 1024-bit sets make the 1025 and 65536 results depend on the bytes past them, and keeps the console's wait on an out-of-range timeout as unknown. The description now says the same, and the entry is 986 characters.

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

Re-checked head 9dd91b6 against main feb5059:

  • The entry now records the nfds_below_fd difference (the console cleared descriptor 16 with nfds 16 on an expired timeout, where AnyPS5 keeps it; nfds 0 leaves it in both), which matches the log and main's timeout path in Socket.cpp.
  • The EBADF clause now says it was measured with nfds 1000, the probe caveat about 1024-bit sets at nfds 1025/65536 is there, and the unknown wait for a saturated timeout is stated plainly.
  • It still merges cleanly into main. Thanks, LGTM.

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

@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 measurements and the limits of the probe are recorded carefully, and the earlier review verified the updated wording against the console log. Before merge, the branch still needs the declared integration work: #9389 and #10162 remain open, and this PR is based on f57e4ef, 7,503 commits behind current main. docs/dev/debt/libkernel.md has also changed repeatedly since that base. Please refresh after the two documented merge-order dependencies land, resolve the current-main debt-file edits while preserving this select result, and rerun the conventions/overlap checks on the final head. As a documentation-only PR, no runtime test is needed.

@harisibrar1

Copy link
Copy Markdown
Contributor

@orezraey Thanks for measuring nfds_below_fd. I opened #10777 to make AnyPS5 match it: select now clears the bits from nfds to the end of their 64-bit word on success, as FreeBSD 11.4's putbits copies roundup(nfds, 64) bits back, and leaves them alone for nfds 0. It credits your log. Whichever of the two lands second can drop the "where AnyPS5 keeps it" sentence from this entry; I'm happy to do that on mine if this one lands first.

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

@orezraey

Copy link
Copy Markdown
Contributor Author

@harisibrar1 Thanks. Agreed: if #10777 lands first, I will drop the "where AnyPS5 keeps it" sentence from this entry when I refresh it; if this one lands first, you drop it on yours.

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

Copy link
Copy Markdown
Contributor Author

@harisibrar1 #10777 landed first, so as agreed I merged current main into this branch in 9319aee and dropped the "where AnyPS5 keeps it" clause from the select entry, which now matches the clearing #10777 added. Only the debt line changes; check_conventions passes and the description names the new head.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 26, 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 26, 2026
@adriadam10 adriadam10 self-assigned this Oct 26, 2026
@adriadam10
adriadam10 dismissed MarcZX10’s stale review October 26, 2026 16:19

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 570089a into boykopovar:main Oct 26, 2026
9 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the new select debt entry against Socket.cpp on main (1024 limit and nfds/tv_usec validation, time_point::max() saturation, word-wide clearing from #10777) and the linked log; conventions green, docs-only; merged.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants