On a PS5 (firmware 12.70), of the values 0, 1, 2 and -1,
pthread_condattr_setpshared accepts only 0 and leaves the attribute
unchanged otherwise. pthread_condattr_getpshared reports 0 and returns
EINVAL for a null, uninitialized or destroyed attribute, also with a
null output. With an initialized attribute a null output crashes the
console; here it throws.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Measured on a PS5 (firmware 12.70): the getter reports 0, and of the
values 0, 1, 2 and -1 the setter accepts only 0 and checks the value
before the attribute. A null or uninitialized attribute, or a null
output, crashes the console; here it throws.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a PS5 (firmware 12.70), of the values 0, 1, 2 and -1,
pthread_spin_init, pthread_barrierattr_setpshared and
pthread_mutexattr_setpshared accept only PTHREAD_PROCESS_PRIVATE (0);
1, 2 and -1 return EINVAL and leave the attribute unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scePthreadCondInit, and pthread_cond_init through it, threw when attr
pointed to a null attribute: a zeroed one that was never initialized or
one that scePthreadCondattrDestroy has set to null. FreeBSD 11.4 libthr
(thr_cond.c, cond_init) takes a null attribute as the default one and
creates a CLOCK_REALTIME condition variable. A PS5 (firmware 13.60)
takes a zeroed attribute as the default one in scePthreadMutexInit
(#4158). Take it as the default here too, as scePthreadMutexInit and
scePthreadCreate already do.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PSFlyCast (PPSA99247) imports pthread_condattr_setpshared (3BpP850hBT4)
from libkernel and fails to load without it:
"./app.elf: symbol lookup error: ./app.elf: undefined symbol: 3BpP850hBT4".
The attribute stores PTHREAD_PROCESS_PRIVATE (0) or
PTHREAD_PROCESS_SHARED (1); a null or uninitialized attribute and any
other value return EINVAL without changing it, following FreeBSD 11
libthr thr_condattr.c and pthread_mutexattr_setpshared here. Sharing
across processes is not modeled, as for mutexes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sovthwyu4H63RMbRVha2Sy
MeasureStackReserve took the distance from the stack top to a local
variable. In an ANYPS5_ENABLE_ASAN build that local lives on
AddressSanitizer's fake stack (detect_stack_use_after_return is on by
default on Linux), away from the thread's stack, so the reserve could
come out negative. scePthreadCreate then asked the guest arena for a
stack of nearly 2^64 bytes and threw 'guest address space arena
exhausted'. The frame address is on the real stack in every build.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pthread_rwlock_timedrdlock, pthread_rwlock_timedwrlock and
pthread_mutex_timedlock threw for a null abstime. FreeBSD's libthr
passes a null abstime on to the untimed kernel lock, so these calls
then wait like pthread_rwlock_rdlock, pthread_rwlock_wrlock and
pthread_mutex_lock.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both threw std::invalid_argument for a null or uninitialized attribute.
FreeBSD's libthr returns EINVAL for one, as the other scePthread
attribute calls here already do. The clock id is still stored as
given.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scePthreadAttrGetstack, Getstackaddr, Getguardsize, Setguardsize,
Setstack and Setstackaddr threw for a null attribute, a null pointer
argument or a stack below the 16 KiB minimum. FreeBSD's libthr returns
EINVAL for those, as the pthread_attr_* wrappers here and the other
scePthreadAttr calls already do.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FreeBSD's libthr rejects a null sched_param and, under SCHED_FIFO or
SCHED_RR, a priority outside sched_get_priority_min..max with ENOTSUP,
and a policy outside SCHED_FIFO..SCHED_RR with ENOTSUP. The wrappers
returned EINVAL for the null parameter and stored any priority or
policy.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WindowsThreadLocal<T>::slot was a template static, so its dynamic
initialization was unordered against the timer self-test in Time.cpp.
With APS5_TRACE_TIMERS set, the self-test ran first, used slot 0 and
aborted every title with "Cannot bind native thread state". The slot is
now a function-local static. guest_nanosleep_timer_self_test runs
guest_nanosleep_tests with APS5_TRACE_TIMERS=1 on Windows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KwsvKtVsZDLefysUM9m2QS
Morrowind imports rtprio_thread, pthread_setconcurrency and pthread_getconcurrency and stops at start-up. Report every guest thread as normal priority and accept a set without applying it; store the concurrency level as a hint. Recorded in the libkernel debt.
PS5CEMU-HAR (PPSA99360, ps5-payload-dev build, relinks with
--trap-sdk-syscall-stubs) imports pthread_setaffinity_np (5KWrg7-ZqvE)
from libkernel.prx. babyhuey's run with #3787 merged onto main e7c70a2d
(PR #3787, 2026-10-12T10:54:44Z) stops at it:
Windows: FAIL: unresolved ELF import 5KWrg7-ZqvE (pthread_setaffinity_np) from libkernel.prx
Linux: undefined symbol: 5KWrg7-ZqvE (pthread_setaffinity_np)
It follows FreeBSD 11.4 libthr thr_affinity.c (8c639945) over
kern_cpuset_setaffinity: another thread is looked up first (EINVAL for
null, ESRCH when unknown or finished, as _thr_find_thread without dead
threads), a size other than the 32-byte cpuset_t returns ERANGE, the
mask is clipped to sceKernelGetAvailableCpumask and an empty result
returns EDEADLK, as cpuset_setaffinity does. The affinity is stored on
the guest thread through scePthreadSetaffinity, for the caller and for
any live guest thread.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Measured on a PS5 (firmware 13.60): a thread created with
PTHREAD_INHERIT_SCHED, a null attribute or a default attribute runs at
its creator's priority, whatever priority the attribute holds; with
explicit scheduling it takes the attribute's priority.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On Linux, glibc maps the stack of every guest thread near the top of the
host address space (around 0x7fff00000000). On the console, application
stacks lie inside the application area below 0xFC00000000, and guest code
relies on that: ChakraCore's garbage collector indexes a 4 MiB table with
address >> 18, so it only covers addresses below 1 TiB and reports
Js::OutOfMemoryException for a stack above it.
Map each guest thread's stack with DoMapAnon, which allocates from the
guest arena, behind a PROT_NONE guard page, and pass it to pthread_attr_setstack.
The stack is freed after a join; the stack of a detached thread is freed once its
host thread is gone from /proc/self/task.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a PS5 (firmware 13.60) pthread_setschedparam and
scePthreadSetschedparam accept only SCHED_FIFO and SCHED_RR with a
priority of 256 to 767 or 896 to 959, return EINVAL otherwise, and
keep the policy for pthread_getschedparam. A created thread takes the
policy of explicit scheduling attributes, or its creator's when it
inherits. Here any policy and priority were accepted and SCHED_FIFO
was always reported.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Allow calling threads to query and set affinity using their own thread ID in addition to -1. Return ESRCH for non-matching thread or process IDs and EINVAL for invalid level/which arguments instead of throwing NotImplemented, matching FreeBSD cpuset semantics.
pthread_atfork (U9t5kJAWPnA, aerolib) appends the prepare, parent and
child handlers to a process-wide list under a lock and returns 0, or
ENOMEM when the entry cannot be allocated, as FreeBSD 11.4's
_pthread_atfork does (lib/libthr/thread/thr_fork.c:78-100, freebsd-src
8c639945a44588f6cfdddfb057bb5aad88735da0). Null handlers are accepted;
FreeBSD's fork skips them. The handlers never run: fork
(libkernel_sys) throws and vfork is absent, so no child process is
created. The list is kept, in registration order, for a later fork
(PthreadAtforkHandlers_nid_no_patch); recorded in TechnicalDebt.
XPSemu (PPSA97358) calls it from a constructor, before main
(ZiZc3/XPSemu 8eec07b4, util/rcu.c:488-495):
static void __attribute__((__constructor__)) rcu_init(void)
{
smp_mb_global_init();
#ifdef CONFIG_POSIX
pthread_atfork(rcu_init_lock, rcu_init_unlock, rcu_init_child);
#endif
rcu_init_complete();
}
so a throwing export would stop the title before main. Predicted stop
removed (registry index 255, not run):
FAIL: unresolved ELF import U9t5kJAWPnA from libkernel.prx
guest_pthread_atfork checks registration order, null handlers,
concurrent registration from four threads and that no handler runs.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit f37bccf6efd76edcde5d582800c89b83fdd30472)