PPSA26578 (issue #7624) imports tgammaf (NID B2ZbqV9geCM) from libc,
and its bundled libc.prx does not export it, causing the process to
exit with 0xC0000139 (GetLastError: 127).
Export tgammaf_nid_postfix in core/libs/prx/libc/src/Math.cpp delegating
to std::tgamma(float), and add unit test coverage in GuestMath
verifying factorials, half-integers, poles, and negative values.
The saver thread took the snapshot lock with a blocking exclusive lock. Behind
a pipeline creation that runs for minutes (an NVIDIA compile of a 1.5M-word
compute pipeline), the queued writer made the shared_mutex hold every later
pipeline creation on every queue until the compile ended. The periodic save now
tries the lock and waits for the next interval when it is busy; SaveNow and the
teardown save still wait.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
PPSA26578 (issue #7624) imports nextafter (NID h+J60RRlfnk) from libc,
and its bundled libc.prx does not export it, causing the process to
exit with 0xC0000139 (GetLastError: 127).
Export nextafter_nid_postfix in core/libs/prx/libc/src/Math.cpp delegating
to std::nextafter(double, double), and add unit test coverage in
GuestMath verifying denormals, infinities, NaNs, and negative zero.
Kena's cached-space hits have no copied ranges, so the memo of their
committed pages saved nothing (imports pass 0 us per build with and
without it), and keeping it current needed a second commit-generation
bump in libc. The space is still stamped once per hit; the test that
commits pages between two hits stays.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The memo of a cached address space's committed pages is published
lock-free and rebuilt when the arena's commit generation moves, which a
commit now advances again when it ends. A trimmed space's last hit
moves back to its imports, and the space hit longest ago is trimmed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A hit in the read-only V# address-space cache described the committed
pages of every copied range again and stamped the space once per import.
The cached space now keeps its copied ranges' committed pages and is
stamped once per hit. APS5_NO_SPACE_COMMIT_MEMO=1 and
APS5_NO_SPACE_STAMP_ONCE=1 turn the two parts off.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
PPSA26578 (issue #7624) imports _ZSt26_Throw_bad_optional_accessv (NID
KwzEip7m6TM) from libc, and its bundled libc.prx does not export it,
causing the process to exit with 0xC0000139 (GetLastError: 127).
Implement std::bad_optional_access type record and vtable deriving from
std::exception, thrown through ThrowPlain, with what() returning
"bad_optional_access", and add unit test coverage in ExceptionRuntime.
As for the f64 rounding test: on a device without f64 DenormPreserve, a
mismatch in the modes that keep f64 denormals is reported as skipped;
the modes that flush them are still checked everywhere.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
v_add_f64 and v_mul_f64 ignored the FLOAT_MODE f16/f64 denormal field.
On RDNA2 (gfx1031) bit 6 clear flushes both inputs to a zero of their
sign, and bit 7 clear flushes a sum below 2^-1022 and a product whose
exact value rounded to 53 significant bits with an unbounded exponent
is below 2^-1022. The product test scales one source by 2^64 and
compares the host product with 2^-958.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
In a payload process on a PS5 (firmware 12.70),
sysctlbyname("kern.rng_pseudo") answers a size query with 64 and gives
at most 64 bytes per call, up to a 65536-byte buffer. A buffer smaller
than 64 bytes gets as many bytes as its length and a null length gets
none, both with -1 and ENOMEM; a null buffer with a null length returns
0, and errno is kept when the call succeeds. Here the whole buffer was
filled, a size query threw and the length was never changed. The 64
random bytes are now drawn only for a read that passes both a buffer
and a length.
AI-assisted: yes
Co-Authored-By: Claude Opus 5.5 <[email protected]>
An ANYPS5_ENABLE_ASAN build moves the guest arena up by 0x100000000000,
past AddressSanitizer's shadow gap, but the AGC driver memory that holds
the FS table (#6160) is still mapped at the fixed 0xfe0000000. That
address is in the shadow gap, so the mapping fails with EEXIST and no
test that initializes the driver runs under ASan.
The offset is now GuestArena::GuestAddressOffset in GuestArena.hpp, and
the driver memory and the FS table move by it like the arena. Builds
without ASan keep 0xfe0000000. agc_driver_compute_fs_table_calls skips
in an ASan build: its shader builds the PS5's fixed table address from
literals, as titles' shaders do, and that address can't be mapped there.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
guest_getrlimit failed on macOS because the host's soft and hard
RLIMIT_NOFILE differed. On macOS it now also checks that the limit does
not exceed kern.maxfilesperproc, and, as on Windows, that guest pipes
fail with EMFILE within 64 descriptors of the reported limit. The pipe
loop moves into a helper that both use.
getrlimit(RLIMIT_NOFILE) reports the host's limits, and libkernel
raised the soft limit to the hard one at load only on Linux. On macOS
the soft limit stayed below an unlimited hard limit (1048576 and
infinity in a shell here, 256 and infinity by default), so the two
differed. XPSemu (PPSA97358) then raises the soft limit to the hard one
in QEMU's os_setup_limits, and setrlimit refuses the change.
macOS fails with EMFILE at kern.maxfilesperproc (10240 here) whatever
the soft limit, even an unlimited one. At load, libkernel now sets both
limits to the smaller of the hard limit and kern.maxfilesperproc, so
getrlimit reports the descriptor count after which opening fails. The
Linux path still raises the soft limit to the hard one.
Lavapipe reports no f64 DenormPreserve, so the shaders get no
DenormPreserve 64 and it may flush f64 denormals; the rows of modes that
keep them then fail with or without the recompiler change (frexp, floor,
ceil and fract of 2^-1074 on Mesa 25 and 26). As in F64FmaSubnormals,
a mismatch in those modes is reported as skipped on such a device. The
modes that flush f64 denormals are still checked on every device.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
v_floor_f64, v_ceil_f64, v_fract_f64, v_frexp_mant_f64 and
v_frexp_exp_i32_f64 ignored the FLOAT_MODE f16/f64 denormal field. On
RDNA2 (gfx1031) bit 6 clear flushes a denormal input to a zero of its
sign, so v_ceil_f64 of 2^-1074 is 0 instead of 1, and bit 7 clear
flushes the denormal result v_fract_f64 gives for a positive denormal.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Windows crash report walks every other thread's rbp chain only, so
a thread waiting inside ntdll or in code built without frame pointers
showed no frames at all. For a thread whose chain yields fewer than two
frames, scan the 32 KiB above its rsp while it is suspended and print
up to 24 words that point at executable memory.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T86KdkUbEv7m5hrCbPbkAp
Review of the benchmark report:
- The file is written to `<name>.tmp` and moved over the previous one, so a
crash or kill during a rewrite keeps the last complete report.
- A dedicated writer keeps only the newest pending snapshot, so two reports
can no longer be joined into one file when the writer falls behind.
- The report is formatted on the writer thread. The presenter hands over the
kept intervals, which are shared and never copied, so the interval that
closes no longer pays for formatting every earlier one.
- Hosts that are not x86 or report no CPU brand string leave the host fields
out instead of failing every summary line.
- A `contentVersion` that is not a string, or does not fit, is left empty
instead of failing the title's metadata.
- Tests cover the 240-interval rotation and `intervals_dropped`, the
newest-only writer, the pending write on stop and the atomic replace.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
libSceNetCtl exports sceNetCtlGetStateV6, sceNetCtlRegisterCallbackV6
and sceNetCtlUnregisterCallbackV6 but not sceNetCtlGetInfoV6 (NID
Jy1EO5GdlcM). Dragon Ball Xenoverse 2 (PPSA08587) imports it, and an
import that no system library exports stops a title before its entry
point: on Linux ld.so refuses the relinked executable with "undefined
symbol: Jy1EO5GdlcM", and on Windows the entry stub prints "FAIL:
unresolved ELF import Jy1EO5GdlcM from libSceNetCtl.prx" and raises
0xC0000139. The title's tester reports that it does not call the
function before its loading screen.
It is a Sony network-control call with no FreeBSD counterpart, and
neither its parameters nor the IPv6 info layout are known, so it is
declared without parameters and throws through
NotImplemented_nid_no_patch, as CONTRIBUTING.md asks of exports that
cannot be implemented. The gap is recorded in
docs/dev/debt/libSceNetCtl.md.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A one-sample depth target under a multisampled rasterizer without
MSAA_ENABLE is drawn as a one-sample draw at the pixel center, but a pixel
program that runs with PS_ITER_SAMPLE threw. Ghost of Tsushima (PPSA02225)
draws its depth-only pass this way (2x PA_SC_AA_CONFIG, PA_SC_MODE_CNTL_1
0x06030000, KILL_ENABLE, no sample index or coverage input) and stops on it.
Every sample is taken to be at the pixel center on this path, so
invocations per sample would get the same inputs and give the same depth,
kill and color results, and the target keeps sample 0's. Such a program is
now drawn once per pixel, without sample shading. ANCILLARY and
SAMPLE_COVERAGE inputs still throw. The debt entry notes that only the
memory writes of such a program can differ.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Nested conversions such as the one closing mktime no longer re-read TZ, so
the instant and the normalised fields come from one zone. The race test now
covers mktime and strftime.
Copy the guest TZ under the guest environment lock so a concurrent setenv
cannot free it while it is read, and hold one lock across the zone switch
and the conversion so the fields of two zones are never mixed. Document the
host rejection, Windows zone name and stale tm_zone limits.
Guest setenv, putenv and unsetenv only change the guest environment, while
the time conversions read the host TZ, so a guest that set TZ and called
tzset still got host local time. Copy a changed guest TZ to the host before
each local conversion and call tzset again.
Monster Hunter Wilds imports sceVoicePausePort, sceVoiceResumePort and
sceImeSetConsecutiveClauseConversionEnabled, which no library exported,
so the loader stopped at the first of them.
sceVoicePausePort and sceVoiceResumePort check the library and the port
like sceVoiceResetPort. sceImeSetConsecutiveClauseConversionEnabled has
no public reference and throws.
Co-Authored-By: Claude Opus 5.5 <[email protected]>