fix(hos): report the game's mapped pages as used memory; commit the heap lazily on Windows #324
No reviewers
Labels
No labels
area/accessibility
area/audio
area/input
area/install
area/menu
area/renderer
area/saves
area/upscaling
good first issue
gpu/amd
gpu/igpu
gpu/intel
gpu/nvidia
help wanted
kind
bug
kind
chore
kind
docs
kind
feature
kind
performance
kind
question
needs measurements
platform/linux
platform/steam-deck
platform/windows
preview
priority
critical
priority
high
priority
low
status
blocked
status
confirmed
status
duplicate
status
invalid
status
needs-info
status
wontfix
testing wanted
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot!324
Loading…
Reference in a new issue
No description provided.
Delete branch "JosephPursley/Longshot:fix/windows-guest-memory"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
On Windows the game's own memory keeps growing as you visit areas, because the emulated OS tells it far more memory is free than really is, so it maps more and more pages for its caches (4.9 GB after three areas, 7.9 GB in a longer play session). On a 32 GB PC this pushed the system to about 1 GB of free commit.
What changed
hos_used_memory()inhost/hos_mem.cadds the pages the game mapped throughAllocateMemoryPages(counted in a page bitmap, uncounted inFreeMemoryPages) to the used memory thatQueryMemoryInfo(+0x08) and svcGetInfo7/22 (host/hos_svc.c) report, capped at the console's total so the game's free = total − used (at 0x8080f010) can never wrap. The game now sizes its caches against what the console really has. The bitmap is kept a GB of the guest window at a time, allocated on first use (no 16 MB static array charged to Windows' commit).SetMemoryHeapSizeno longer commits the whole heap up front.commit_on_touchinhost/mkw_glue.ccontinues when another thread already committed the page (a first-touch race), but not for an execute fault, which still reaches the crash report; that retry is compiled on Windows only (#ifdef _WIN32), so on Linux every fault in the guest window still reaches the crash report as on main.hos_commitnow returns whether the range is committed, andread_at/WriteFileinhost/nn_fs.ccommit guest buffers beforeReadFile/WriteFileand return an error, 0xCA01, when that commit is refused, instead of a short read or write. 0xCA01 is the codehos_mem.candhos_svc.calready return as out of memory; by Horizon's numbering it issvc::ResultInvalidSize(out of memory is 0xD001), and what OoT does with either is unknown.imports_give_back()(gpu/vk/vk_memory.cpp),RX_VK_IMPORT_HIGHdefaults to 85 on Windows NVIDIA (it was off on all of Windows); Windows AMD and Intel stay off unless the switch is set, and there the pools it gives back (GRACE mode) leave the budget at once and are freed afterRX_VK_RETIRE_SECS.memory_guest_imported()(every platform) also counts pools given back whose memory isn't freed yet.tests/test_commit_limit.pycutshos_commitby its new signature, and checks thatcommit_on_touch's retry of a committed page is there and under#ifdef _WIN32;tests/test_texel_buffer_ownership.pycutsimports_give_backat its reworded comment.docs/development.md's switch reference.Flags and settings
HOS_MEMINFO_OLD=1HOS_HEAP_COMMIT=1SetMemoryHeapSize(old Windows behaviour)RX_VK_IMPORT_HIGH=<percent>RX_VK_RETIRE_SECS=<s>HOS_PAGES_LIMIT=1AllocateMemoryPagespast the console's total (diagnostic)All five are in
docs/development.md(withRX_VK_IMPORT_LOW,RX_VK_IMPORT_CAP_MBandRX_VK_RETIRE_MIN_SECS, which this PR doesn't change).Measurements
The numbers below are for
40caf46f, before the review fixes and the rebase; they have not been taken again on5e8a89b8. On Windows NVIDIA the fixes change nothing these runs reached (the used-memory cap only acts past the console's total, which B2 stayed under; the valve's default there is the same), but they are to be measured again before ready.main:
ae96bad3(the base40caf46fwas measured on)this PR: fix/windows-guest-memory @
40caf46f(now5e8a89b8on main351affd9, not yet measured)Hardware: NVIDIA GeForce RTX 3060, driver 610.88, AMD Ryzen 7 5800X3D, 32 GB RAM, Windows 11 Pro
Scene: one save (Hyrule Field, adult), then debug teleports to Kokiri Forest, Kakariko Village, Market (and Death Mountain Trail / Zora's Domain, refused in every run: "an event is playing"), ~40 s each, walking; 1920x1080 headless, audio off.
Method: one build; the old behaviour with
HOS_MEMINFO_OLD=1 HOS_HEAP_COMMIT=1 RX_VK_IMPORT_HIGH=0(A), this PR's defaults (B); interleaved A1, B1, A2, B2, ~6 min each, driven over the control bridge. Process memory sampled every ~12 s; mapped pages from themem: the game's mapped pageslog line.Baseline: this PR @
40caf46f, old behaviour (A2)Why not main: the A runs turn this PR's changes off in the same binary, so both sides share the build and caches.
How to reproduce:
longshot_ctl.py launch <game> --headless --env HOS_AUDIO=0 [--env HOS_MEMINFO_OLD=1 --env HOS_HEAP_COMMIT=1 --env RX_VK_IMPORT_HIGH=0], press A untilplay,teleport 0,teleport 2,teleport 3, holding ~40 s each.Matched pair (A2/B2, same route: Kokiri → Kakariko → Market), end of run:
40caf46f, old behaviour (A2)40caf46f(B2)First pair (A1 reached only Kokiri because its teleports were refused, so the route is not matched): mapped pages 3,841 vs 2,560 MB, private 28,552 vs 26,402 MB.
Both B runs stop at 2,560 MB of mapped pages whatever the route; the A runs grow with each area. An earlier longer play session by hand (not interleaved) reached 7.9 GB of mapped pages and ~20 GB of working set with the old behaviour, against ~2.6 GB and ~13.9 GB with this PR.
Testing
Tested: at
40caf46f, RTX 3060 / Windows 11: the four runs above, plus about an hour of hand play (title, Kokiri Forest, Hyrule Field) with no crash or visible problem.tests/run_all.pyat40caf46f: the same 6 failures with and without the change (that PC's setup). The review fixes in58dc267c(the used-memory cap, the NVIDIA-only default, the fs commit errors, the execute-fault check, the lazily allocated bitmap) and5e8a89b8(the first-touch retry on Windows only) were written without building or running anything: not compiled, not run in the game,tests/run_all.pynot run on them yet. No test request results yet (none opened).Not tested:
hos_used_memory) andmemory_guest_imported's count of pools given back but not yet freed apply on every platform; only the lazy heap commit is Windows-only. Not run there at all.RX_VK_IMPORT_HIGHset, untested.Needs other testers:
RX_VK_IMPORT_HIGH=85, expecting no device loss (request to open)Screenshots
Nothing on screen.
Risk and rollback
SetMemoryHeapSize; it can come at any first touch, on any thread, mid-play (a 5 scommit_waitstall, then the out-of-memory notice and a crash report). In exchange the heap no longer charges ~6.9 GB of commit up front. A file read or write whose buffer can't be committed now returns an error (0xCA01) to the game, where before it got a short read or write; what the game does with it is untested.RX_VK_IMPORT_HIGHis set.HOS_MEMINFO_OLD=1,HOS_HEAP_COMMIT=1andRX_VK_IMPORT_HIGH=0turn each part off; reverting the commits is enough.Reviewer notes
Overlaps the 5.6 memory row with https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/223 (Linux renderer pressure, separate code apart from
imports_give_back()). Coordinating with rogasse's Windows investigation of the same row. The review fixes are in their own commits on top (58dc267c, then5e8a89b8for the Linux fault loop) so the author's commit stays as it was apart from the rebase.Issues
See https://git.magicbean.dev/MagicBeanDev/Longshot/issues/89
Checklist
For everyone
type(scope): description).main.python -I -B tests/run_all.pyrun and passing (any failure that also fails onmainis named above). (not run on5e8a89b8; the run at40caf46fhad 6 failures from that PC's setup, the same on main, still to be named one by one)40caf46f, one matched pair; to be measured again on5e8a89b8)third_party/untouched (a new folder with aPROVENANCE.mdinstead).If applicable
Assisted-by:/Co-Authored-By:trailers.docs/tested-configurations.mdfor each measured run. (to do, with the new measurements)tests/that reads changed source updated in this PR, not weakened.5e8a89b8not built on either yet;40caf46fbuilt on Windows only)🤖 Generated with Claude Code
Code review of
40caf46f(read only: nothing built or run here). No comments or test-request results on the PR yet; the CI jobs for this head are still pending (only the description check has run, and passed).The idea is right and the numbers are convincing for Windows/NVIDIA: telling the game what it really has mapped is the fix for the growth, and lazy heap commit is the right answer to Windows charging the whole 6.9 GB heap against RAM + page file up front. The ReadFile/WriteFile commits cover the only kernel-mode writes into guest memory I can find in
host/(Vulkan imports already commit their range invk_memory.cpp), and the first-touch race fix is sound.Must change before merge
hos_used_memory()can return more thanhos_total_memory(nothing refusesAllocateMemoryPagesby default, and B2 already sits ~350 MB under the line). The game'stotal - usedthen wraps to a huge free figure and the growth comes back. Clamp it (inline).memory_guest_imported's new evicted-pool check apply on every platform. That needs one Linux run before merge (the PR already lists it; the request isn't opened yet).RX_VK_IMPORT_HIGH=85on Windows turns the live-import valve on for AMD and Intel, where it was turned off because of device losses (issues 17, 309, 571 per the comment). The GRACE wait is a plausible cure but is untested on those vendors. It needs a Windows AMD and/or Intel run before it ships as a default, or keep it NVIDIA-only for now.main @ <hash>,tests/run_all.py, docs for the four switches plusRX_VK_RETIRE_SECS(now read by this valve too and missing from Flags and settings), and the tested-configurations row. Two comments invk_memory.cpp(lines 3407 and 3425) still say the valve is off on Windows. Note thattests/test_texel_buffer_ownership.pycutsimports_give_backat the text// (longshot) Off by default, so if you reword that comment, update the test in the same commit.Suggestions (inline): a failed lazy commit in
read_atgoes on into aReadFilethat will fail; the first-touch retry should not apply to execute faults; the 16 MB static bitmap is charged to commit on Windows.v3.0.0: not as it stands. It changes what the game sees on every platform and turns on a valve on the two vendors where it caused device losses, with one GPU measured. It can go in if the Linux and AMD/Intel runs come back clean in time. Otherwise, split it: the used-memory report plus the lazy heap after a Linux run, and the Windows valve default after AMD/Intel runs.
@ -3429,1 +3435,4 @@// after a wait there (retired_mode GRACE) without them, so the pools this valve takes wait the same way: held, the table// already off them, until RX_VK_RETIRE_SECS (30) have passed since, and only then queued for the GPU (retired_value). What// waits is counted as given back, so the valve does not take more for the same bytes. RX_VK_IMPORT_HIGH=0: off, as beforestatic const int high = std::clamp(env_int("RX_VK_IMPORT_HIGH", 85), 0, 100);This is the default that changes for Windows AMD and Intel, where the valve was off because of device losses right after imports went back (the comment at 3425, still unchanged, says so, as does 3407). The GRACE wait mirrors what fixed the retired pools, but nothing in the PR has run on either vendor. It needs a Windows AMD/Intel run before it ships as a default. Until then,
85for NVIDIA only (dev.props.vendorID == 0x10DE) would keep the measured gain. Please also update the two stale comments, and the test's// (longshot) Off by defaultcut marker if you reword 3425.@ -242,0 +247,4 @@#if defined(_WIN32)static int commit_all = -1;if (commit_all < 0) commit_all = env_on("HOS_HEAP_COMMIT");if (size > hos_heap_size && commit_all) hos_commit(HOS_HEAP_BASE + hos_heap_size, size - hos_heap_size);Windows commit semantics are right here: committed-but-untouched pages still count against RAM + page file, and reserve does not. What changes is where a refusal at the commit limit appears. Before, it was one failure at
SetMemoryHeapSize. Now it is any first touch, on any thread, mid-play (a 5 scommit_waitstall, then a crash report plus the out-of-memory box). That is a fair trade for ~5 GB less commit, but please state it under Risk and rollback.@ -280,0 +294,4 @@memory resident, a working set of 19.6 GB, against the console's 12 GB in all). One bit a 4 KB page of the guest window,so that pages mapped twice or freed twice count once. HOS_PAGES_LIMIT=1: past the console's total (heap + pages),AllocateMemoryPages fails as it would there; unset, only counted and logged */static uint64_t mapped_bits[(HOS_GUEST_SPACE >> 12) / 64];Nit: 512 GB / 4 KB / 8 = 16 MB of
.bss. On Windows, image sections are charged to commit when the image loads, so this adds 16 MB of commit to a PR that is about commit. A two-level map, or one bit per 64 KB granule, would cost almost nothing. Not a blocker.@ -280,0 +328,4 @@LOCK();const uint64_t mapped = mapped_bytes;UNLOCK();return base + hos_heap_size + mapped;This can exceed
hos_total_memory:AllocateMemoryPagesis not refused by default (HOS_PAGES_LIMIToff), and B2 already ends ~350 MB from the line. Past it, the game'sfree = total - used(0x8080f010) wraps to a huge figure, and it maps without limit again, which is the bug this PR fixes. Clamp it:const uint64_t used = base + hos_heap_size + mapped; return used < hos_total_memory ? used : hos_total_memory;(GetInfo 7/22 get the same value).@ -88,0 +87,4 @@if (!VirtualQuery(p, &mbi, sizeof mbi)) return EXCEPTION_CONTINUE_SEARCH;/* (another thread committed this 64 KB between the fault and the look: the access is tried again. The heap is committed ontouch now (hos_mem.c), and two threads touching one new chunk at once crashed the second in the boot's module loads) */if (mbi.State == MEM_COMMIT && mbi.Protect == PAGE_READWRITE) return EXCEPTION_CONTINUE_EXECUTION;Right for the race. One edge: an execute fault (
ExceptionInformation[0] == 8, DEP) on a committed RW guest page would now return CONTINUE_EXECUTION forever: a host jump into the guest window spins at 100% instead of reachingreport_crash. Checkrec->ExceptionInformation[0] != 8before retrying.@ -420,1 +420,4 @@const int away = hos_vcore_away(); /* (as OpenFile: no core held through the read) *//* (the kernel's ReadFile does not fault pages in: a heap page nothing touched yet (hos_mem.c, committed on touch) iscommitted for it first, or the read fails with ERROR_NOACCESS) */if (size && hos_guest_range(buf, size)) hos_commit(buf, size);If this commit is refused (the commit limit after
commit_wait, or any other error),hos_commitonly logs, and theReadFilebelow then fails with ERROR_NOACCESS and returns 0 bytes. The game gets a short read rather than a clear error. Consider havinghos_commitreturn whether it succeeded, and returning 0 (or the out-of-memory result) without callingReadFilewhen it fails. Same for WriteFile at 475. (On Linux this is a no-op inside the guest window, so it's fine there.)A player's v3.0.0-rc.3 log looks like the case this PR is for, on another 32 GB PC. It ended in a device lost in Kakariko Graveyard (child, after using the magic bean spot), about 110,000 frames into the session.
PC: RTX 3060 Ti 8 GB, NVIDIA 621.01, Windows, 32 GB RAM, 2 GB page file (
boot: 32689 MB of memory, 2048 MB of swap), so the commit limit is about 34.7 GB.Memory over the session (from
vk: memory:andvk: commit limit near:):gsys::ModelResourceMgr(GpuHeap)reached 0 KB free during area loads (the heap-full retries took 480 blocks, about 3 MB, from parent heaps).The crash:
submit 770398 failed (-4). Both checkpoints (stage 0x1 and 0x2000) stop at the same marker, a write-back of pool0x103a800000. The next draw never reached the top of the pipe, so no shader in it hung. The log has no driver-side reason for the reset, so the tie to commit is very likely but not proven.rc.3 has no
mem: the game's mapped pagesline, so the game's own share can't be split out here. Still, the private memory growth (+14 GB) is the pattern your A runs show. A 2 GB page file is a harsh case worth testing this PR on: with the heap committed lazily, it should keep this PC clear of the limit.The log stays with us (it has the player's paths); I can share figures from it if you need more.
40caf46f0625ca294064Review fixes pushed as
25ca2940(a commit of its own on top of the author's, both rebased onto main9fccd0fd; the author's commit is unchanged apart from the rebase). Per point of the review (#324 (comment)):hos_used_memory()is capped athos_total_memory, so the game's free = total − used can't wrap (QueryMemoryInfo and GetInfo 7/22 get the same value).memory_guest_imported's count of pools given back but not yet freed apply everywhere; Risk and Not tested say so, and a Linux run is listed as needed.RX_VK_IMPORT_HIGHdefaults to 85 on Windows NVIDIA only (dev.props.vendorID == 0x10DE); Windows AMD and Intel stay off unless the switch is set. Documented in the code, the Flags table and docs/development.md.SetMemoryHeapSize.hos_commitreturns whether the range is committed;read_atandWriteFilein nn_fs.c returnsvc::ResultOutOfMemory(0xCA01) when it is refused, without calling ReadFile/WriteFile.commit_on_touchdoesn't retry an execute fault (ExceptionInformation[0] == 8), so a jump into guest memory reaches the crash report.RX_VK_IMPORT_LOW/CAP_MB,RX_VK_RETIRE_MIN_SECS) are in docs/development.md;RX_VK_RETIRE_SECSis in the Flags table; the two comments in vk_memory.cpp that said the valve is off on Windows are updated, andtests/test_texel_buffer_ownership.pycuts at the reworded one.tests/test_commit_limit.pycutshos_commitby its newintsignature.Nothing was built or run for this push: not compiled, no
tests/run_all.py, no game run. The measurements in the description are still 40caf46f's. Still needed before ready: a build on both Windows and Linux,tests/run_all.py, a Linux run, Windows AMD and Intel runs (defaults, and withRX_VK_IMPORT_HIGH=85if the valve should go on there), and the Windows NVIDIA A/B measured again on25ca2940with a tested-configurations row. It stays WIP.Re-review of
25ca2940(our fix commit) and of the rebase, read only: nothing built or run here. Read first: the description, llun's log comment and the fix comment (#324 (comment)). No test-request results yet.Rebase (
4f4502a9): intact. Its diff against9fccd0fdand 40caf46f's diff againstae96bad3have the same added and removed lines in each of the six files (sorted per file), and 4f4502a9's parent is9fccd0fd, so nothing of main is reverted. Main has since moved to351affd9(four renderer commits touching other hunks ofvk_memory.cppanddocs/development.md): a rebase before ready, not now.CI on
25ca2940: nothing compiled it. Only the title, actionlint, third-party notes and description checks ran (all passed); the Python source checks, the SPIR-V fixtures and the third-party upstream check were skipped.The review's points on
25ca2940:hos_total_memory: fixed. GetInfo 6/21 and QueryMemoryInfo +0x00 report that same total, so free can't wrap; theHOS_MEMINFO_OLDpath is unchanged.dev.props.vendorID == 0x10DE, the same testretired_mode()already uses.devis set by then becauseimports_give_backfirst runs frommemory_begin_submission. Linux stays 85, andtest_retired_give_back.py's needles still match.ReadFileentry points pass&oom, andread_athas no other callers. The refused path gives the core back (hos_vcore_back) before it returns.WriteFile's explicitreturnis needed, sinceRETonly sets x0. The otherhos_commitcallers (hos_mem.c ×5, hos_svc.c, hos_main.c) ignore the newint, which is fine in C. No other declaration of it exists. On Linux, the shim's in-window commit returns the address, so the result is always 1. See the nit inline about which result 0xCA01 is.pages_count_lockedcall holds the hos_mem lock, so leaves are allocated under it. Nothing touches the bitmap from the exception handler, so nothing is allocated in a vectored handler. On a failedcallocthe pages are neither counted nor marked, so mapping and freeing stay consistent and the report errs low. Themap == 2probe counts a missing leaf as all new. Sizes: 512 × 8 B static, 32 KB a leaf.HOS_HEAP_COMMITis under#if _WIN32;RX_VK_RETIRE_SECSis read only in GRACE). The two stale comments are reworded. The test cuts match the new source exactly:"int hos_commit(uint64_t addr, uint64_t size)"," // (longshot) Default by OS and vendor"(the#ifdeffalls after the cut, so the stubbed compile doesn't needdev), andtest_guest_copies.py's two needles inread_at/WriteFileare still present.Must change: the Linux hang (inline on
host/mkw_glue.c). Point 6 was fixed with a test the Linux shim never meets, and the underlying regression is the author's retry, which our first review called sound without looking at Linux. Until it is fixed, "Linux run needed" can't come back clean on a bad fault.Still needed before ready, once that is fixed: a build on Windows (llvm-mingw) and Linux;
tests/run_all.py; a Linux run; Windows AMD and Intel runs (defaults, and withRX_VK_IMPORT_HIGH=85if the valve is to go on there); the Windows NVIDIA A/B measured again on the new head with a tested-configurations row; the three test requests opened; a rebase on main.@ -88,0 +91,4 @@/* (another thread committed this 64 KB between the fault and the look: the access is tried again. The heap is committed ontouch now (hos_mem.c), and two threads touching one new chunk at once crashed the second in the boot's module loads.Not an execute fault (8, DEP): a jump into guest memory would fault again at once, forever; it goes on to the crash report) */if (mbi.State == MEM_COMMIT && mbi.Protect == PAGE_READWRITE && rec->ExceptionInformation[0] != 8)Linux: this turns every fault in the guest window into an endless loop. The POSIX shim's
VirtualQueryreports every guest page asMEM_COMMIT+PAGE_READWRITEwithout asking the kernel (host/posix/win32_posix.c, 'the guest window ... which VirtualQuery reports as committed').on_signalsetsExceptionInformation[0]only to 0 or 1 (REG_ERR & 2), never 8. So on Linux any SIGSEGV or SIGBUS above guest 0x100000 returns CONTINUE_EXECUTION here, and the faulting instruction runs again forever at 100% CPU. That covers a host jump into guest memory (NX), and a SIGBUS from the memfd-backed window when memory runs out. On main,State != MEM_RESERVEsent all of these on toreport_crash. The!= 8check fixes it for Windows only.Linux has no lazy commit, so the race this retry is for can't happen there. Simplest fix: put the retry under
#ifdef _WIN32. Optionally, have the shim also set 8 whenREG_ERR & 0x10(an instruction fetch), so the execute test means the same on both, but SIGBUS would still need the#ifdef. Iftest_commit_limit.pyshould guard it, a needle on the#ifdefwould do.@ -87,6 +87,7 @@ const char *hos_romfs_dir, *hos_user_dir;#define R_PATH_EXISTS 0x402 /* fs::ResultPathAlreadyExists */#define R_NOT_MOUNTED 0xCA02 /* fs::ResultInvalidMountName-ish: no such mount */#define R_TARGET_NOT_FOUND 0x7D402 /* fs::ResultTargetNotFound (save data) */#define R_OUT_OF_MEMORY 0xCA01 /* svc::ResultOutOfMemory: the guest buffer could not be committed (Windows) */Nit: by Horizon's numbering, 0xCA01 is kernel (module 1) description 101,
svc::ResultInvalidSize;svc::ResultOutOfMemoryis description 104, 0xD001 (Atmosphère'ssvc_results.hpp, yuzu'ssvc_results.h). The label is inherited:hos_mem.candhos_svc.calready return 0xCA01 under the same comment. So this follows the house convention, and fixing them all is out of scope. Either way the game gets a failure where before it got a short read (the firstReadFilereturnedfs::ResultOutOfRange; the other two returned success with fewer bytes). I can't tell from here what OoT does with either. Worth fixing the comment (or using 0xD001) and the description's wording, so nobody relies on the game treating it as out of memory.25ca2940645e8a89b8faPushed
5e8a89b8on main351affd9(rebased, linear; the author's commit and58dc267c, formerly25ca2940, have the same +/- lines as before). It fixes the Linux hang from the re-review (#324 (comment)):commit_on_touch's retry of a page another thread committed is now under#ifdef _WIN32. On Linux the VirtualQuery stand-in calls every guest page committed and read-write and the signal handler never sets 8, so every SIGSEGV/SIGBUS in the guest window looped at 100% CPU; now they reach report_crash as on main.tests/test_commit_limit.pychecks that the retry is there and under#ifdef _WIN32(no #else/#elif around it).host/nn_fs.cgets a one-line comment that 0xCA01 is the house's out-of-memory code andsvc::ResultInvalidSizeby Horizon's numbering; the label is unchanged. The description says 0xCA01 rather than svc::ResultOutOfMemory, and names the new head. Nothing was built or run here: not compiled, no tests, not run in the game. Still WIP.Light re-review of
5e8a89b8(the follow-up to review 1225). Both points are fixed; nothing new found.Linux reaches report_crash again. On Linux the guest window is one read-write mapping, so the
VirtualQuerystand-in inhost/posix/win32_posix.calways answersMEM_COMMIT/PAGE_READWRITEthere. With the retry now inside#ifdef _WIN32, a SIGSEGV or SIGBUS in the window goes past the null-page check and then hitsmbi.State != MEM_RESERVE, which returnsEXCEPTION_CONTINUE_SEARCH. The signal shim then passes it to the unhandled filter,report_crash. That is the same path ascommit_on_touchon main (351affd9), where both checks sat on one line.Windows is unchanged. The code inside the
#ifdefis the same as in58dc267c; only the comment grew. The preprocessor block doesn't cross any brace.recandmbiare still used outside it, so Linux gets no unused-variable warning.The test is tighter, not looser.
tests/test_commit_limit.pyonly adds lines. Its retry string matches the source byte for byte and must appear exactly once. The check fails if the nearest#ifdef _WIN32above it is followed by#endif,#elseor#elifbefore the retry, or ifreturn EXCEPTION_CONTINUE_EXECUTION;comes after the closing#endif.The 0xCA01 nit is handled. The new comment above
R_OUT_OF_MEMORYnames it as Horizon'ssvc::ResultInvalidSize. Optional: the define's own trailing comment still sayssvc::ResultOutOfMemory, so the two disagree. Rewording that trailing comment would remove the contradiction.The rebase onto
351affd9is clean. The +/- lines of2e8cbd66and58dc267care identical to those of4f4502a9and25ca2940.CI on
5e8a89b8is green, but light. The title, actionlint, third-party notes and description template checks pass. The Python source checks, the SPIR-V fixtures and the third-party upstream check were skipped on this WIP run, sotest_commit_limit.pyhasn't run in CI yet.Still to do before this leaves WIP:
python -I -B tests/run_all.py, or CI's Python source checks once they run on this PR.CRASH:log line.Light review, code only: nothing was built or run.
Superseded by #324 (comment): the points it asked for are fixed; what's left is listed there.
Superseded by #324 (comment): the points it asked for are fixed; what's left is listed there.
WIP: fix(hos): report the game's mapped pages as used memory; commit the heap lazily on Windowsto fix(hos): report the game's mapped pages as used memory; commit the heap lazily on Windows