The conflict with #13908 in docs/dev/debt/libkernel.md keeps both sides: this branch's pthread_getaffinity_np entry, followed by #13908's sentence on the EFAULT fallback for a mask pointer that cannot be read or written.
A title is jailed (agreed on #11216). FreeBSD 11.4 prison_priv_check denies
PRIV_SCHED_RTPRIO, PRIV_SCHED_SET and PRIV_SCHED_SETPRIORITY to a jailed caller.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
rooklz measured on a PS5 that pthread_getaffinity_np accepts any set of 8 to
16 bytes, zero-fills it past byte 8, and returns ERANGE below 8 bytes and from
24 up. Sets of 17 to 23 bytes are not measured and still throw.
scePthreadCondSignalto and pthread_cond_signalto_np answered EPERM for a
handle that is not a live thread, where a PS5 on firmware 13.60 returns
ESRCH. The check sits between the null-thread and not-waiting checks, as
that console orders them.
The mutex yield step counts each yield in a counter that
MutexYieldsForTest_nid_no_patch reads. With no spins and a yield count
of 5, a waiter woken while another thread holds its mutex must yield
exactly 5 times before it blocks, for each mutex type and for the outer
level of a recursive mutex held twice. With WakingLock::lock calling
the native lock directly the count stays 0 and the test aborts.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
FreeBSD 11.4's _mutex_cv_lock takes the mutex back through
mutex_lock_common, so a woken waiter tries once, spins and yields by
the mutex's counts before it blocks. The wait here called the native
lock directly; it now goes through the same spin and yield path as
scePthreadMutexLock.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sched_getparam, sched_getscheduler and sched_setparam with the own pid
from a thread other than the main thread act on the main thread once it
has registered through scePthreadSelf, as FreeBSD's p1003_1b.c selects
the first thread. Before registration, after the main thread exits and
on macOS they still throw.
FreeBSD's mutex_lock_common tries the lock before mutex_lock_sleep
spins or yields, so a free mutex with yield loops and no spins was
yielding before its first try here.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Lock and timed lock now try the mutex up to the spin count with a pause
between tries, then up to the yield count with a yield before each try,
before they block, as FreeBSD 11.4's mutex_lock_sleep does. Trylock and
a lock the thread already holds do not spin. A uniprocessor host skips
the spins and keeps the yields.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
On Windows, sceKernelRaiseException threw for a thread created suspended
and not resumed yet. FreeBSD libthr starts such a thread with signals
blocked and restores its mask on resume, so the signal stays pending and
is delivered on that thread once it runs.
The raise is now recorded in the thread's pendingException with a
compare-exchange, and the thread exchanges it for -1 when it leaves the
creation wait and delivers it to itself before its start routine. Both
sides use one atomic, so a raise racing a resume is either taken by the
thread or, after it started, delivered as for a running thread. Raises
while pending are merged, as for a standard signal.
guest_pthread_create_suspended now runs the deferred-delivery case on
every host, with a second raise while the thread is suspended.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
pthread_condattr_getclock reached NotImplemented_nid_no_patch for a null
output pointer with a valid attribute. Measured as a payload process on
a device, that call faults, as does scePthreadCondattrGetclock in the
same case, so both now throw std::invalid_argument. Every other measured
result of the condition attribute clock getters and setters already
matched. The test covers every invalid clock ID from -1 to 16.
PS5_PayloadSDK measured in a title (firmware 12.09) that
pthread_getaffinity_np answers sets of 8 and 16 bytes and returns ERANGE
for 32 bytes or more, so FreeBSD's 32-byte cpuset_t is refused. The call
accepted exactly 32 bytes and refused every other size. Sizes under 8
keep ERANGE; 17 to 31 bytes, between the measured sizes, throw.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
FreeBSD's sys_rtprio_thread returns ESRCH for an unknown lwpid before a
failed copyin of the struct, so the copy-in now follows the thread
lookup, and RTP_SET with an unknown lwpid and an unreadable struct
reports ESRCH. Tests pin that order and sched_rr_get_interval's pid check
before its copy-out.
rtprio_thread read and wrote the guest rtprio struct in place, and
sched_rr_get_interval wrote the interval in place, so a non-null pointer
into unmapped or read-only memory crashed the host. rtprio_thread now
copies the struct in with GuestCopyIn_nid_no_patch before the thread
lookup for RTP_SET, as FreeBSD's sys_rtprio_thread does, and builds the
RTP_LOOKUP result locally and copies it out with
GuestCopyOut_nid_no_patch. sched_rr_get_interval copies its interval out
the same way. A failed copy returns EFAULT.
Keep a copy of the name with the semaphore and move the export from the libkernel_sys stub into libkernel next to the other sem_* exports.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>