scePthreadMutexTimedlock on a mutex the caller holds, and
scePthreadRwlockTimedrdlock and scePthreadRwlockTimedwrlock on a rwlock
it holds for writing, returned EDEADLK at once. The console returns
ETIMEDOUT, as the prosper console oracle measured. They now sleep until
the timeout and return ETIMEDOUT, as FreeBSD libthr does. The POSIX
timed locks call these and change with them.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceLncUtilLoadExec takes the same path and null-terminated argument
list, which the SystemService call passes on to it on the console. It
returns sceSystemServiceLoadExec's result: the same parameter errors,
the same refusals for paths it cannot start, and "exit" ends the title
in the same way.
sceLncUtilIsAppSuspended, sceSystemServiceIsAppSuspended and
sceLncUtilIsSpeculativeLaunch write false for the running title's app
ID. The title that calls them is running and has no shell to suspend
it. It was started from the host rather than by sceLncUtilLaunchApp,
so no LncLaunchParam asked for a speculative launch. Another app ID
and a null output still throw.
sceLncUtilGetAppLaunchedUser, sceSystemServiceGetAppLaunchedUser and
sceShellCoreUtilGetUserFocus write the initial user for the running
title's app ID. That is the user sceUserServiceGetInitialUser and
sceUserServiceGetForegroundUser report. Another app ID and a null user
pointer still throw.
sceLncUtilGetAppId and sceLncUtilIsAppLaunched accept the running
title's ID as sceSystemServiceGetAppId does, and
sceLncUtilGetAppIdOfRunningBigApp returns what
sceSystemServiceGetAppIdOfRunningBigApp returns. Both big-app lists
write the running title's app ID as their only entry, because AnyPS5
runs one title. Another title ID, a null pointer and a list capacity of
0 still throw.
sceKernelWaitCommandBufferCompletion waits for an AMM submission as
libSceAmpr's sceAmprAmmWaitCommandBufferCompletion does: 0 once the
submission has run, SCE_KERNEL_ERROR_ESRCH for an id that was never
submitted. The signature follows ampr_emu's libkernel hook targets,
where the libSceAmpr wait forwards to it.
guest_kernel_sys submits a map written by sceKernelWriteMapCommand,
waits for it and uses the mapped page, and checks ids 0 and past the
last submission.
The twelve AMM kernel writers record into a caller buffer the command
their libSceAmpr command buffer sibling appends, built with the shared
encoder: sceKernelWriteMapCommand, sceKernelWriteMapWithGpuMaskIdCommand,
sceKernelWriteMapDirectCommand, sceKernelWriteMapDirectWithGpuMaskIdCommand,
sceKernelWriteUnmapCommand, sceKernelWriteRemapCommand,
sceKernelWriteRemapWithGpuMaskIdCommand, sceKernelWriteMultiMapCommand,
sceKernelWriteMultiMapWithGpuMaskIdCommand,
sceKernelWriteModifyProtectCommand,
sceKernelWriteModifyProtectWithGpuMaskIdCommand and
sceKernelWriteModifyMtypeProtectWithGpuMaskIdCommand.
The signatures follow ampr_emu's libkernel hook targets: the sibling's
arguments as 64-bit values between the destination and the size output.
A null destination only reports the size and a null size output only
writes, as for sceKernelWriteModifyMtypeProtectCommand. Invalid ranges,
offsets and protections return the sibling's SCE_KERNEL_ERROR_EINVAL and
write nothing; protection or mask bits above 32 are rejected too.
guest_kernel_sys compares each writer with its sibling on valid and
invalid arguments, in both modes.
The graphics pipeline store kept a fixed 1024 entries and the pipeline journal replayed at most
1024 records, and a replayed pipeline that found the store full was dropped. A title whose
working set is larger rebuilt the rest at the draw on every run, and evicted pipelines it kept
using were rebuilt again and again.
The bound now starts at 1024 and doubles up to 4096: a journal replay that does not fit grows it
instead of dropping the pipeline, and so does eviction churn (a ghost list of evicted keys, checked
every bound/32 evictions: more than half of them came back). It never shrinks during a run;
APS5_PIPELINE_STORE_ENTRIES still fixes it. The journal loads its last 4096 records by default
(APS5_PIPELINE_JOURNAL_ENTRIES). Resident pipelines are bounded by count, not bytes.
agc_driver_recorder_tests --benchmark-pipeline-store-memory [count] (opt-in, not registered)
builds count graphics pipelines with one fragment module each through CachedPipeline and prints
process private bytes and VK_EXT_memory_budget heap usage before and after: with the triangle
shaders about 59 KiB host and no device memory per pipeline on an RTX 4090, 100 KiB host and
8 KiB device-local on a UHD 770.
Tests: agc_pipeline_store_growth (fails on main), agc_pipeline_store_fixed_bound,
agc_pipeline_store_replay_growth (replays on one thread: the mock Vulkan is not thread-safe).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_017SNUYRd7sRKZrMYpquAsnU
sceUsbdGetDevice, sceUsbdGetDeviceSpeed, sceUsbdGetMaxPacketSize,
sceUsbdGetMaxIsoPacketSize, sceUsbdOpenDeviceWithVidPid,
sceUsbdSetInterfaceAltSetting, sceUsbdClearHalt and
sceUsbdDetachKernelDriver follow FreeBSD 11.4 libusb10.c over the host
libusb. The packet sizes and the alternate setting checks are done as
FreeBSD does them, so the library records which interfaces are claimed,
and a device stays known while a handle to it is open.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
An ITIMER_REAL expiry with a guest SIGALRM handler throws, since guest
handlers are never run from the timer thread. On Linux and Windows that
throw goes through libc's exception runtime, so an uncaught one runs the
guest's std::set_terminate handler. On macOS the host keeps libc++abi,
so the throw ended in libc++abi's terminate and the guest handler never
ran. Throw through the guest runtime there, and record the general
macOS gap in the libc debt file.
Ported from #8658.
Co-authored-by: Himansh Raj <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>