Implement scePthreadGetschedparam and scePthreadSetschedparam on top of
the thread priority, POSIX utimes and fsync on top of sceKernelUtimes
and sceKernelFsync, and sceUserServiceGetAccessibilityZoomFollowFocus
like the other accessibility queries. Add the remaining imports of
PPSA12544 as unimplemented exports and record unknown NIDs and
signatures in the technical debt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
clock_gettime and clock_getres served three FreeBSD clock ids with the wrong
clock or not at all:
- CLOCK_VIRTUAL (1) was the monotonic clock on Windows and threw on Linux; it
is the user CPU time of the process.
- CLOCK_PROF (2) threw on both hosts; it is the user plus system CPU time of
the process.
- CLOCK_SECOND (13) returned the coarse realtime clock with nanoseconds and a
sub-second resolution; it is the current second with tv_nsec 0 and a
resolution of one second.
Behaviour follows FreeBSD 11 clock_gettime(2) and kern_clock_gettime /
kern_clock_getres in sys/kern/kern_time.c.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scePthreadKeyDelete frees a key slot and the next scePthreadKeyCreate
hands the same index out again, but every thread kept the value it had
stored under that index. The new key read the previous key's value
instead of NULL, and at thread exit its destructor was called on that
stale pointer.
Each slot now carries a sequence number, as in FreeBSD libthr. A thread
value is visible to scePthreadGetspecific and to the exit destructors
only while its sequence matches the slot's, so a new key starts as NULL
in every thread, as POSIX requires, and a deleted key reads NULL.
scePthreadGetspecific stays lock-free and scePthreadSetspecific no
longer takes the key lock.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lock the guest pages of the range with VirtualLock or mlock, following FreeBSD mlock(2): the range is widened to guest pages, a zero length succeeds, a wrapping range is EINVAL and a range that is not mapped and accessible is ENOMEM. The Windows working set limits and the Linux RLIMIT_MEMLOCK soft limit are raised when the lock needs it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sceAmprCommandBufferWaitOnAddress took (address, reference, mask,
compare) and WaitOnCounter (counter, reference, compare), and both read
the compare value as WAIT_REG_MEM (0 always, 1 <, 2 <=, 3 ==, ...).
ampr_emu, which replaces libSceAmpr for retail titles on the console,
has (address, reference, compare, flush) and (counter, reference,
compare, flush) with the SCE compare values (0 ==, 1 > unsigned,
2 < unsigned, 3 !=), so waits were decoded as other comparisons and
could block forever or pass early.
WriteAddressFromCounterPairOnCompletion takes one counter index, not
two, and WriteKernelEventQueueOnCompletion an int id and no user data.
Counter indices above 127, compare values above 3, flush values above 1
and misaligned wait addresses return EINVAL, as in ampr_emu.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nanosleep and _nanosleep forwarded the result of sceKernelNanosleep, which
returned -1 for a rejected request: errno was never set, and the sce call
returned a value that is not an sce error. A request with negative seconds
was rejected as well, where FreeBSD's kern_nanosleep returns 0 without
sleeping.
nanosleep and _nanosleep now return -1 with errno set to EINVAL when tv_nsec
is outside [0, 1000000000) and to EFAULT for a null request;
sceKernelNanosleep returns the matching SCE_KERNEL_ERROR code. A request
with valid nanoseconds and negative seconds returns 0 at once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sceAmprCommandBufferPushMarker, PushMarkerWithColor, PopMarker, SetMarker
and SetMarkerWithColor record a marker command, and the matching
sceAmprMeasureCommandSize functions return its size. The APR executor
skips markers, as it does a nop.
Signatures follow the ampr_emu reimplementation of libSceAmpr.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The POSIX layer only exported init, destroy, rdlock, wrlock and unlock.
pthread_rwlock_tryrdlock, pthread_rwlock_trywrlock,
pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock now wrap the
existing scePthreadRwlock functions and accept the static initializer.
The timed variants take an absolute CLOCK_REALTIME deadline. Like
FreeBSD libthr they try the lock first and only validate abstime when
the lock is not free. A null abstime throws, as pthread_mutex_timedlock
does.
scePthreadRwlockTryrdlock and scePthreadRwlockTrywrlock return EBUSY
when the caller already holds the write lock instead of calling into
std::shared_timed_mutex, where that is undefined behaviour.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The PS5 libthr (FreeBSD) creates error-checking mutexes by default and has
PTHREAD_MUTEX_ADAPTIVE_NP (type 4); relocking an error-checking or adaptive
mutex returns EDEADLK. Default mutexes were Normal and type 4 was mapped to
Normal, so a relock threw instead of returning EDEADLK, which aborted an
Unreal Engine title's recursive directory scan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
open, _open, stat, unlink and rmdir forwarded the result of their sceKernel
twin, so a failure returned 0x8002xxxx instead of -1 and errno was never set
to the guest error. They now return -1 with errno set to the code carried by
the sce error, and report a null pointer as EFAULT and an empty path as
ENOENT.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scePthreadAttrGet wrote priority 700 and left the affinity of the
destination untouched, whatever the thread was created with or set to
afterwards. It now reports the values the thread holds, as
pthread_attr_get_np already does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pthread_barrier_init threw for any non-null attributes object, and no
function could create one. Add pthread_barrierattr_init, _destroy,
_getpshared and _setpshared after FreeBSD libthr, and let
pthread_barrier_init take the object.
PTHREAD_PROCESS_SHARED still throws in pthread_barrierattr_setpshared:
FreeBSD 9.0 rejects it and 11.0 accepts it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sceKernelSyncOnAddressWait parks the calling thread while the 32-bit word
at the address still holds the expected value, until
sceKernelSyncOnAddressWake releases it or the timeout expires.
sceKernelSyncOnAddressWake releases up to the requested number of threads
parked on the address, in arrival order.
The libc.prx bundled with SDK 9 titles imports both for its once
primitive, so those titles stopped at load with an unresolved import.
# Conflicts:
# docs/dev/TechnicalDebt.md
libkernel did not export sceKernelMapNamedFlexibleMemoryInternal, which
the libc bundled with SDK 9 titles imports. It now forwards to
sceKernelMapNamedFlexibleMemory: the mapping counts against the flexible
budget, gets the range name and is released by sceKernelMunmap. Older
libc builds call the public function at the same sites with the same
arguments and result handling.
The known callers pass flag 0x8000, whose meaning is unknown. It is
still rejected as an unsupported mapping flag and is recorded in
TechnicalDebt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sceKernelCancelSema was a throwing stub. It now releases every thread
blocked in sceKernelWaitSema with SCE_KERNEL_ERROR_ECANCELED without
consuming tokens, sets the count to setCount (the initial count when
setCount is negative) and reports how many threads were waiting. A
setCount above the maximum returns SCE_KERNEL_ERROR_EINVAL and changes
nothing.
Waiters are counted separately from waiterCount, which is only
decremented when a waiter leaves, so two cancels in a row do not report
the same thread twice.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CLOCK_THREAD_CPUTIME_ID (14) and CLOCK_PROCESS_CPUTIME_ID (15) threw
"unsupported clock_id" on Windows while the Linux branch already maps
them to the native clocks. clock_gettime now returns the user + kernel
time from GetThreadTimes / GetProcessTimes, and clock_getres reports the
clock interrupt period from GetSystemTimeAdjustment, which is the step
those counters actually advance by.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Returns 1 when the address lies in an executable PT_LOAD segment of the
given dl_phdr_info, following FreeBSD lib/libc/gen/elf_utils.c (9.x and
11.x branches). The stub parameters become (dl_phdr_info*, void*) to
match the FreeBSD declaration; a null dl_phdr_info throws.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sceKernelGetEventId, sceKernelGetEventFilter, sceKernelGetEventFflags,
sceKernelGetEventData and sceKernelGetEventUserData return the matching
field of the KernelEvent filled by sceKernelWaitEqueue and throw on a
null event. sceKernelGetEventError still throws NotImplemented.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>