Commit Graph
253 Commits
Author SHA1 Message Date
Adrià 7c3bfa8632 Merge pull request #5962 from nikowolf123/feat/libc-crash-register-text
feat(libc): print the text that registers point at in Windows crash reports
2026-10-17 06:51:43 +02:00
screammandClaude Fable 5.1 9f4a8d6ec5 feat(libkernel): serve the console CA list from the host trust store
Titles that bundle OpenSSL load the console's CA file from the sandbox
directory and fail every HTTPS request without it. ProsperoRadio
(PPSA99001, libcurl 8.18.0 + OpenSSL 3.5.2) on main + #4796 + #4525:

  [ProsperoRadio][http] https://all.api.radio-browser.info/json/servers: Problem with the SSL CA cert (path? access rights?) (error adding trust anchors from file: /gkbHtXc3Wq/common/cert/CA_LIST.cer)

SwanStation (PPSA98510) stops on the same file (#5001).

The guest path resolver now accepts exact-path providers, and libkernel
registers one for /<sceKernelGetFsSandboxRandomWord()>/common/cert/CA_LIST.cer.
On first use it writes a PEM bundle once per process to
cert_cache/CA_LIST.cer in the run directory, read-only: on Windows the
current user's ROOT and CA system stores, elsewhere SSL_CERT_FILE or the
first distro bundle that exists. Without a certificate the path keeps
resolving under the guest root and does not exist, as before. Every other
path under the sandbox word is unchanged. The console file's format and
the rest of its common/cert directory are unverified and recorded in
docs/dev/debt/libkernel.md.

With this change, #4796, #4525 and #5025 on Windows 11, 60 s each:

  [ProsperoRadio][http] 11846160 bytes in 1458 ms: 1161 passes, 803 waits (679 woken) for 1428 ms
  [ProsperoRadio][catalog] page offset=0 bytes=11846160 objects=10000 accepted=9549 total=9549
  ...
  [ProsperoRadio][catalog] page offset=60000 bytes=1712035 objects=1494 accepted=1436 total=59371

  [SwanStationPS5] update: latest 1.2.5, this 1.1.3, available
  [SwanStationPS5] gamedb: index written

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-17 02:24:02 +00:00
NikoandClaude Opus 5.5 b263cbbb1b feat(libc): print the text that registers point at in Windows crash reports
Unreal titles end in their own libc fatal path with the UTF-16
LowLevelFatalError message in a register, and the crash report shows
only the first 64 bytes of it as hex words, so the message is lost
(#4238: Demon Slayer PPSA03490, Stray PPSA02100).

For every general register that points at readable memory starting
with at least four printable ASCII characters, as UTF-16LE or as single
bytes, the report now prints the text up to a NUL, the first other
character, 512 characters or the end of readable memory (each page is
checked with VirtualQuery before it is read).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 23:33:43 +02:00
Adrià 5b70a50680 Merge pull request #5955 from fma-rc/fix/libkernel-linux-guest-module-protect
fix(libkernel): register a relinked guest module's image when Linux protects its pages
2026-10-16 23:29:46 +02:00
Alexej Szpevák b71434d9b7 feat(libc): read app0.zar beside app0 and refuse archive-only paths elsewhere
A ZArchive named app0.zar beside app0/ is a read-only layer under it. libc opens it at the first path resolution, looks paths missing from app0/ up case-insensitively, reads files across compressed blocks and keeps the archived descriptor table with shared positions.

Resolving an archive-only path through a call that does not read the archive throws instead of failing with ENOENT, as do opendir of a directory present in both places, fdopen of an archived descriptor and chdir into the archive. A path through .. in an archive-only directory resolves.
2026-10-16 20:03:26 +02:00
Adrià a4782fe11d Merge pull request #4855 from fdfawef324/feat/agc-submission-ring
feat(agc): keep the last submissions per queue and dump them on a stall or crash
2026-10-16 12:32:48 +02:00
fdfawef324andClaude Opus 5.5 13b171cab5 feat(agc): keep the last submissions per queue and dump them on a stall or crash
A GPU hang or a crash in a title leaves no record of what the queues
were last given: APS5_TRACE_GPU prints every submission (too much to
leave on), and the WAIT_REG_MEM timeout message shows only the packet
before the wait on the waiting queue.

Each queue now keeps a ring of its last 16 submissions
(APS5_PM4_RING=<n>, 0 to 4096, 0 disables): the TraceMs time in tenths
of a millisecond, serial, size, guest address and a copy of the first
512 dwords after indirect buffers are inlined, recorded under the
driver lock next to the serial, REWIND tails included. The ring of a
queue and the failure report registration are set up at the top of
Submit, before any output is reserved, so recording under the lock
does not allocate. Disabled, Submit only tests a static flag; enabled,
it costs one bounded copy per submission.

DumpSubmissionRings decodes the kept dwords with Pm4::PacketWords and
the new Pm4::KnownName, which returns the decoder's names as views of
static strings (empty for an unknown opcode, printed as UNKNOWN_0x%02x);
Pm4::Name now builds its std::string from it. Every line is formatted
with integer and string conversions only into a 512-byte stack buffer
and written with one WriteFile / write(2) on the stderr handle, so the
dump does not allocate from the C runtime heap, lines from other
threads do not interleave and the CRT stream lock is not taken (the
rule of #3871). The header gives the number of queues and the ring
size, and each queue line the submissions recorded and kept.

libc gets a small registry of failure reports
(LibcRegisterFailureReport_nid_no_patch, Unregister, Run); Run runs
the registered reports the first time it is called and returns at once
after that. The Windows crash report runs it after the thread dump of
an unhandled exception, after SIGABRT (which also covers the
APS5_HANG_DUMP_SECS timed dump, since it aborts) and after an invalid
CRT parameter, so an abort after a reported exception does not print
the rings twice. The driver registers its dump at the first submission
and unregisters at static destruction; the dump there waits a bounded
time for each ring lock. What the crash-path dump cannot do (a ring
held by the crashed thread, rings corrupted by the crash, Linux) is
recorded in technical debt.

APS5_STALL_WATCHDOG_SECS=<n> (0 to 86400, 0 disables) makes a waiter
that has not progressed for n seconds dump the rings once per wait: a
WAIT_REG_MEM (progress as for APS5_GPU_WAIT_TIMEOUT_MS: another packet
runs or completes), a REWIND waiting for the title, and a compute
submission held behind queue 0. The last one prints under the driver
lock, so submissions and the other queues wait for it (USAGE.md says
so). Both variables are read at the top of Submit, so an invalid value
of either throws at the first submission and never later inside a GPU
worker. The order wait behind queue 0 releases its order hold on scope
exit, so a throwing dump cannot leave it counted.

No packet semantics change; packet sizes and names are those of the
existing decoder (PM4 type-3 header layout as in Mesa
src/amd/common/sid.h). The queue bound of Submit and of the rings is
one constant, SubmissionQueueEnd.

Tests: agc_driver_pm4_tests gets ten modes, each its own ctest:
agc_driver_pm4_ring (APS5_PM4_RING=4, six submissions on queue 0 and
two on 0x20: the dump holds #3..#6 and #1..#2 in order, nothing
older), agc_driver_pm4_ring_empty (one line), _ring_disabled (one
line), _ring_invalid and agc_driver_pm4_stall_watchdog_invalid
(APS5_STALL_WATCHDOG_SECS=1x: the submission throws and is not
executed), _ring_report (LibcRunFailureReports_nid_no_patch dumps the
rings), _ring_report_heap (Windows: with ucrtbase.dll's HeapAlloc and
HeapReAlloc imports counting calls from the reporting thread, the
failure report of a submission holding INDEX_BUFFER_SIZE names it and
allocates nothing, while Pm4::Name of the same header is seen
allocating), and with APS5_STALL_WATCHDOG_SECS=1 a WAIT_REG_MEM
(agc_driver_pm4_stall_watchdog), a REWIND (_stall_watchdog_rewind) and
a compute submission held behind a queue 0 rendering wait
(_stall_watchdog_order), each held for about 2.5 s, dump once and
complete when released. The PM4 catalog test checks KnownName against
every opcode and custom name. windows_backtrace_failure_report checks
that abort() runs the registered reports once and not an unregistered
one; windows_backtrace_failure_report_once that abort() does not run
them again after an earlier run. With the dump decoding through
Pm4::Name, agc_driver_pm4_ring_report_heap fails with "the failure
report allocated from the C runtime heap"; with Run resetting its
flag, windows_backtrace_failure_report_once prints the report twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 11:18:26 +02:00
AlxcBTW b82d688ed8 fix(agc): flush the log queue, bounded, where the process ends without exit handlers
Lines queued behind the logger were lost when the process ended through
abort(), std::terminate, the Windows crash report or a guest _Exit,
because only driver failure, Driver::stop and a normal exit flushed the
queue.

libc keeps one end flush (LibcSetEndFlush_nid_no_patch) and runs it from
those paths. Its first registration chains a SIGABRT handler in front of
the previous one, so every abort() and std::terminate in the process is
covered, on Linux as well; with the default disposition the handler
restores it and raises again, so raise(SIGABRT) still ends the process.
Guest abort() and _Exit, and ReportCrash for the first fatal exception,
run the flush directly. AsyncLog registers a bounded flush (FlushFor, 2 s)
that polls two counters and takes no lock, so a dying process cannot hang
on a blocked stream or on the queue lock; after its first timeout it
returns at once. Flush counts queued and finished entries instead of
watching the queue and the writer flag, so it waits for the lines queued
before the call and not for a moment in which no thread is logging.

agc_async_log_fatal runs the test executable as a child that queues lines
behind a held stream and ends in abort(), std::terminate(), raise(SIGABRT)
(POSIX) or an access violation (Windows), and once more with the stream
never released. The lines of the first four must arrive in order, the last
child must end after the bound, and every child has a watchdog.
agc_async_log gains the bounded flush case.
2026-10-15 20:42:16 +02:00
AlxcBTW ad85ed13ac perf(agc): format and write steady-state log lines off the queue worker
Texture creation logged one stdout line per texture and per mip through
WriteLogLine, which formatted with the mingw printf and flushed every
line on the queue worker (about 786k lines in a 25 minute cave run).

AsyncLog keeps a bounded queue and a logger thread. AGC_LOG_DEFERRED
captures numeric arguments on the caller and formats them on the logger
thread; WriteLogLine hands finished lines to a per-module sink in
libc/LogMacros.hpp that AgcDriver installs, so all AgcDriver stdout
lines keep their order and are written one flush per batch. A full queue
blocks the caller, so no line is dropped. Flush runs on driver failure,
shutdown and at exit. APS5_LOG_SYNC=1 restores the synchronous path.

Identical "deferred write-back failed" notes are printed three times per
10 s and then counted into one "repeated N more times" line. A
"[log] 10 s" line reports lines, bytes, caller time and logger time
(APS5_LOG_STATS=0 hides it).
2026-10-15 20:42:16 +02:00
Adrià e6134fd0d9 Merge pull request #5827 from hamb3r/perf/precise-wait-spin-tail
perf(libc): add sub-tick spin tail to PreciseSleepUs and PreciseSleepUntil
2026-10-15 20:34:20 +02:00
Adrià da85abc480 Merge pull request #5774 from wachi35676/fix/libc-printf-unsigned-sign-flags
fix(libc): ignore the space and + flags for unsigned printf conversions
2026-10-15 18:36:17 +02:00
Adrià 21ca964f3f Merge pull request #5632 from babyhuey/fix/libc-closed-stream-writes
fix(libc): fail stream calls on a stream that a failed freopen closed
2026-10-15 17:03:43 +02:00
Dean Galvin eac8bfcfc0 fix(libc): list the directory once for a missing path that may be a relinked module
A read-only open, stat or reachability check of a missing path listed its
directory twice: once for a case-insensitive match of the name and again for
a case-insensitive match of the relinked <name>.guest.prx (#5434). Both
names are now matched in the same listing. Precedence and the ambiguous-name
errors are unchanged.
2026-10-15 13:59:12 +13:00
Dean 95945006ec Merge pull request #4629 from mugurc/fix/libcxx-portability
fix(libs): build with libc++
2026-10-15 10:46:05 +13:00
hamb3r ea690728c3 perf(libc): limit Windows PreciseSleepUs spin tail to pacing sleeps 2026-10-14 23:26:08 +03:00
David-cmrg 2dd7f2b0e3 fix(libSceSystemService): end LoadExec exit without running guest exit handlers 2026-10-14 21:41:22 +02:00
Adrià 9811e9d4b7 Merge pull request #5218 from YossiYad/fix/guest-arena-mapping-hint
fix(libkernel): fall back below a mapping hint with no room above it
2026-10-14 21:05:23 +02:00
Adrià 066442c961 Merge pull request #5143 from xXPBSXx/fix/mprotect-unmapped-einval-v2
fix(libkernel): fail sceKernelMprotect over an unmapped range with EINVAL instead of aborting
2026-10-14 21:05:05 +02:00
Adrià 587b63d2a3 Merge pull request #5073 from krishalivaibhav/codex/memory-service-lifetime
fix(memory): preserve process-owned services during exit
2026-10-14 20:33:53 +02:00
ChadandClaude Opus 5.5 5bf18f0d71 perf(libc): remember clean pages once per run in Windows write collects
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:21:19 -05:00
fma-rc c1783f9d64 fix(libkernel): register a relinked guest module's image when Linux protects its pages 2026-10-14 18:24:45 +02:00
hamb3r 6976be9c10 perf(libc): add sub-tick spin tail to PreciseSleepUs and PreciseSleepUntil
- Windows (`_WIN32`): replace full-duration waitable-timer sleep in `PreciseSleepHundredNanos` and the repeated `PreciseSleepUs` call loop in `PreciseSleepUntil` with a hybrid sleep-then-spin helper (`PreciseSleepFromCounterWithTimer`) that sleeps on the thread-local high-resolution waitable timer up to a 250 us spin tail, falls back to `std::this_thread::sleep_for` if timer setup/wait fails, and finishes the remaining window using `QueryPerformanceCounter` + `YieldProcessor()` (thresholded to 200 ns and ceiling-rounded via `PreciseHundredNanosToQpcTicks` for non-10MHz QPC frequencies).
- Linux & POSIX (`!_WIN32 && !__EMSCRIPTEN__`): replace repeated `nanosleep` loop in `PreciseSleepUs` and `PreciseSleepUntil` with `PreciseSleepFromNanos` using `clock_gettime(CLOCK_MONOTONIC)`. On Linux (`__linux__`), cache `PR_SET_TIMERSLACK` (`1 ns`) once per thread (`thread_local`) and sleep via `clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME)` up to a 15 us spin tail (falling back to a conservative 100 us tail if `prctl` fails; 100 us `nanosleep` tail on other POSIX platforms) before finishing with `_mm_pause()` on x86 or `std::atomic_signal_fence` on non-x86.
- Tests: expand `core/libs/tests/PreciseWait.cpp` to assert that the 31-sample median of `PreciseSleepUs(50)` stays below 90 us (which fails on `main` at ~118 us on Linux and ~518 us on Windows) and verify ceiling QPC tick conversion and timer fallbacks.
2026-10-14 17:59:41 +03:00
Yossi Yadgar a016b4f2bc fix(libkernel): fall back below a mapping hint with no room above it
A mapping without MAP_FIXED treated its address as the lowest place it
could go, and a hint at or above the end of the guest arena threw on the
host. FreeBSD 11.4's vm_mmap_object places such mappings with
vm_map_find_min, which takes the address as a hint only: it tries at or
above it, then again from its minimum address.

GuestArenaAllocateFromHint does the same in the arena: at or above the
hint when it lies below the arena's end and a range fits there, otherwise
from the arena's start. MapPlaced and the Windows mmap_aligned use it for
hinted mappings; GuestArenaAllocateAtOrAbove keeps its meaning for the
callers that need a range above an address.

PS5CEMU-HAR (PPSA99360) reserves its JIT range with
sceKernelReserveVirtualRange and a hint near its own code, a host address
above the arena here, and aborted with "mapping address hint is above the
guest address space arena" when launching a 3DS title.
2026-10-14 17:41:31 +03:00
Adrià f3434892bc Merge pull request #5862 from MarcZX100/feat/windows-worker-thread-names
feat(windows): name presenter and queue worker threads
2026-10-14 16:39:02 +02:00
MarcZX100 445db4d013 feat(windows): name presenter and queue worker threads 2026-10-14 14:02:27 +00:00
MarcZX100 2cc4999420 feat(libc): add optional log timestamps 2026-10-14 13:55:30 +00:00
Muhammad Wasif Ali WasifandClaude Opus 5.5 9d9554948c fix(libc): ignore the space and + flags for unsigned printf conversions
The guest formatter passed the flags of %o, %u, %x and %X to the host, and
MinGW's printf prefixes a space to %u when the space flag is set: "% u" of 5
gave " 5". C17 7.21.6.1 applies both flags to signed conversions only, and
FreeBSD 11.4 vfprintf clears the sign for every unsigned conversion (nosign).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 15:03:45 +05:00
TideOPL b14d844855 perf(libc): remember ranges proven collectable until the mappings change 2026-10-14 09:43:40 +01:00
TideOPL 2af88da01f perf(libc): walk the shared views of a write collect in order 2026-10-14 09:43:40 +01:00
Dean Galvin 8cc20401a2 fix(libc): forget a released section's pages even while views remain on Windows
WindowsMappings keys each physical page's state (moved into the section,
saved bytes of an unmapped resident page) by the section handle value.
sceKernelReleaseDirectMemory frees the backing before it unmaps the views,
so ForgetSection ran while those views still existed and kept their slots.
After the views went, the slots stayed under a handle value that Windows
hands out again, and the next direct allocation whose section got that
value started with the old page state: its first mapping went to the
section instead of private memory, or received the old allocation's bytes.

Views now share ownership of their slot, ForgetSection drops every slot
of the section at once, and JIT shared memory forgets its section before
closing it too.
2026-10-14 21:11:38 +13:00
babyhuey 292752ff5a fix(libc): fail stream calls on a stream that a failed freopen closed 2026-10-14 02:20:06 -04:00
Dean 6546a33944 Merge pull request #4728 from Ondra97/codex/fix-fdopen-access-mode
fix(libc): reject incompatible fdopen access modes on Windows
2026-10-14 19:06:55 +13:00
krishalivaibhav d50eed2df3 fix(memory): preserve process-owned services during exit 2026-10-14 07:18:19 +02:00
Dean 22beaa2e7a Merge pull request #4628 from mugurc/fix/asm-macho-symbols
fix(libs): spell inline assembly symbols for Mach-O hosts
2026-10-14 17:26:02 +13:00
thibautandClaude Opus 5.5 71da166a18 fix(libc): keep resident mappings to direct memory backings on Windows
Map made every singly mapped section page private resident memory. A JIT
or shm_open section is file backed and committed: its bytes live in the
file, and its alias descriptors map duplicated handles, which the physical
page slots do not match, so a resident copy diverged from the file, and
committing its view on a demote failed with access denied
(guest_jit_shared_memory). Only direct memory backings, mapped through the
new GuestArenaMapDirect, now become resident; other sections keep main's
shared views. Shared pages are committed only while their section page is
reserved, as on main.

The socket host write tests map their direct memory a second time, so the
write-protected shared path they check is still the one they exercise.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V1W4jdNSKTV7xwuS6xQPJV
2026-10-14 02:39:10 +02:00
DotDebianandClaude Opus 5.5 d9852df2a2 fix(libc): track writes to singly mapped direct memory without faults on Windows
A direct memory page mapped at one guest address now lives in private
MEM_WRITE_WATCH memory at that address, and its writes are collected with
GetWriteWatch like flexible memory: no fault is raised. A page mapped at a
second address moves its whole resident run into the section, behind a
read-only fence while it is copied, and every address becomes a view of it,
tracked by write protection. Unmapped resident pages that are not blank are
kept in a private reservation until they are mapped again, not in the
section.

Ported onto main's 4 KiB subpage tracking of shared views: resident runs
keep a per-page collected bit and enter the fresh ranges, so Fresh and
Armed collections select them like shared views; a demoted run carries its
collected bits into the views and reports every page once. MapAlias throws
through refuse() when a resident run extends outside the aliased range, and
the caller keeps main's fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V1W4jdNSKTV7xwuS6xQPJV
2026-10-14 02:39:10 +02:00
xXPBSXx e528ac9c58 Merge remote-tracking branch 'upstream/main' into d-5143-merge
# Conflicts:
#	core/libs/prx/libkernel/CMakeLists.txt
2026-10-14 02:21:10 +02:00
Dean 7a0c838ca4 Merge pull request #4875 from nikowolf123/perf/libc-write-watch-capacity
perf(libc): size each write-watch query to the region it covers
2026-10-14 12:12:10 +13:00
Dean c7601b7971 Merge pull request #4164 from hamb3r/feat/libc-unity-il2cpp-runtime
feat(libc): add missing Unity IL2CPP runtime imports and Dinkumware helpers
2026-10-14 10:45:32 +13:00
Dean 8d98e8851f Merge pull request #4474 from JJenkx/fix/multisample-target-retirement
fix(agc): retire fully unmapped multisample targets
2026-10-14 10:23:12 +13:00
hamb3r 8652dbe35b feat(libc): add missing Unity IL2CPP runtime imports and Dinkumware helpers
Add missing libc.prx symbols required by Unity IL2CPP runtime:
- Implement _Dtest double classification in Math.cpp
- Implement _Inf double constant in Math.cpp
- Implement sceLibcBacktraceGetBufferSize and sceLibcBacktraceSelf in Backtrace.cpp
- Implement _Cnd_signal in Threads.cpp
- Implement _ZNSt8ios_base7_AddstdEPS_ in RuntimeSupport.cpp
- Implement __pointer_type_info and __function_type_info vtables in TypeInfo.cpp
- Remove duplicate stubs from libSceAmpr/Export.cpp
- Add unit tests in GuestMath.cpp and GuestLibcThreads.cpp
- Document unverified behaviors in docs/dev/debt/libc.md
2026-10-13 19:01:30 +03:00
xXPBSXxandClaude Sonnet 5.5 05ffb45164 fix(libkernel): fail sceKernelMprotect over an unmapped range with EINVAL instead of aborting
The allocation tracker threw a runtime_error (a hole in the protected range) from inside
sceKernelMprotect, which terminated the title. mprotect already turned the exception into
EINVAL. sceKernelMprotect and sceKernelMtypeprotect now check that the range is registered
first and return EINVAL; the retype of direct mappings is skipped on failure.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 17:41:52 +02:00
Adrià c496fd530f Merge pull request #4546 from codingreapermaps/feat/libc-call-trace-runtime
feat(libc): record traced import calls on Windows
2026-10-13 16:51:55 +02:00
JJenkx f7fd7569fa fix(agc): retire fully unmapped multisample targets 2026-10-13 10:37:07 -04:00
Adrià 9dac817b19 Merge pull request #4548 from coltken95/fix/libc-printf-nan
fix(libc): print NaN without a sign in the guest printf formatter
2026-10-13 16:31:34 +02:00
codingreapermapsandClaude Opus 5.5 3953a8d49e feat(libc): record traced import calls on Windows
TraceImport_nid_no_patch wraps a function of a library named in
APS5_TRACE_CALLS in a thunk that records the import, the thread and
the caller in a ring and counts the call, then jumps to the function.
One target keeps one thunk, so function pointers compare equal. The
crash and abort reports print the last 64 calls and the 32 most called
imports. Nothing calls TraceImport_nid_no_patch yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 16:13:12 +02:00
NikoandClaude Opus 5.5 44767a7b97 perf(libc): size each write-watch query to the region it covers
WindowsMappings::Collect handed GetWriteWatch the whole remaining output
capacity for every private region it walked. The call's cost follows that
capacity, not the size of the range: on Windows 11 (26200) a query of one
16 KiB region took 0.35 us with room for 4 entries and 6.5 us with room
for the 65536 the write tracker passes. Flexible memory is committed in
16 KiB allocations, one region each, so a resetting walk over 33 MiB of it
took 14.7 ms, 5.8 times a memcmp of the same bytes.

Each query now gets room for the pages its region spans, which is the most
it can report, so every walk returns the same pages; the 33 MiB walk takes
1.23 ms. guest_memory checks that a walk over eight 16 KiB allocations
reports every stored page once, in order, with room for 32, 5 and 1 pages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:40:33 +02:00
Dean 9fa50827dd Merge pull request #4532 from DavidSamir/fix/libc-rename-replace-open-destination-windows
fix(libc): replace an open or read-only destination in rename on Windows
2026-10-14 00:38:14 +13:00
Mouad-Scriptz-0andClaude Fable 5.1 df3d027ebe perf(libkernel): find guest allocations and direct mappings by address
sceKernelVirtualQuery, sceKernelMunmap, sceKernelReleaseDirectMemory and the
reservation paths walked a copy of the whole allocation registry or of every
direct mapping under one lock on each call. The registry now answers lookups
from its ordered map, applies range replacements as patches instead of
rebuilding the map, and direct mappings carry an index by physical offset so a
release finds only the mappings it covers. Minecraft (PPSA17221) holds about
7,000 direct mappings and spent its world generation in these walks.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-13 23:11:32 +13:00
Dean 2890f95494 Merge pull request #5025 from 0xRickx/fix/libkernel-sys-rename-import
fix(libkernel_sys): reach rename through a _nid_no_patch export
2026-10-13 22:37:36 +13:00