Repository navigation
[M1-ALLOC-01 fix] Attribute the alloc window to the owner thread - #78
Merged
Merged
Conversation
Master run 37519998162: macOS arm64 STILL failed TileMapZeroAlloc after the settle-window fix — 48 blocks, first site now resolved to SkyLight +CGSSnarfAndDispatchDatagrams (the WindowServer client's datagram dispatch). The macOS graphics framework chain (loaded by the GL/GLFW suites earlier in the same binary) keeps doing background heap work on its own threads — first QuartzCore's one-time init, now ongoing WindowServer datagram dispatch — and the process-wide window was counting it. 'Settle until clean' is a coin flip against an ongoing background activity; it is not the fix. Root cause: the watch's contract (G-R1, FR-2.2) is that the LOOP'S THREAD — the tick path — allocates nothing; it never said every thread in the process must. The process-wide counter measured the wrong thing: any background thread (framework, render, OS) that allocates during a window was tripping the loop's invariant. Fix: owner-thread attribution. allocWatchArm() records the calling thread as the window's owner; watchRecord() counts only the owner thread's allocations (plus the existing logging-emit exclusion). This is strictly more correct for the per-tick assertion too — it could previously false-fire on any background allocation during a tick. The disarmed hot path is unchanged; the armed non-owner path costs two loads + a branch. - New regression test ZeroAlloc.WatchExcludesNonOwnerThreads (a non-owner thread's allocation inside an armed window is not counted; fails on the old process-wide semantics). - tilemap zero-alloc test: the settle workaround is removed — a single honest window, now structurally immune to framework background work; the failure message keeps the dladdr site resolution (module + symbol). - Contract updated in alloc_watch.h, docs/api/alloc_watch.md, game_loop.h/.cpp, and the related test/doc comments; laige-api.json regenerated (symbol set unchanged — line shifts + one summary text).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Master run 37519998162: macOS arm64 still failed
TileMapZeroAllocafter the settle-window fix of PR #77 — 48 blocks, first site resolved (via the dladdr diagnostic) to:Root cause
The macOS graphics framework chain (loaded by the GL/GLFW suites earlier in the same test binary) keeps doing background heap work on its own threads — PR #77's run showed QuartzCore's one-time init, this run shows the ongoing WindowServer datagram dispatch. The settle-until-clean workaround is a coin flip against ongoing background activity — and it was never the right fix, because the watch was measuring the wrong thing:
the contract (G-R1 / FR-2.2) is that the LOOP'S THREAD allocates nothing — it never said every thread in the process must. A process-wide counter trips the loop's invariant on any background thread's allocation.
Fix: owner-thread attribution
allocWatchArm()records the calling thread as the window's owner;watchRecord()counts only the owner thread's allocations (in addition to the existing logging-emit exclusion). Strictly more correct for the M1-ALLOC-01 per-tick assertion too — it could previously false-fire on any background allocation during a tick. The disarmed hot path is unchanged; the armed non-owner path costs two atomic loads + a branch.ZeroAlloc.WatchExcludesNonOwnerThreads(a non-owner thread's allocation inside an armed window is NOT counted; fails on the old process-wide semantics).tilemapzero-alloc test: the settle workaround is removed — one honest window, structurally immune to framework background work; the failure message keeps the dladdr site resolution (module + symbol) for future flakes.alloc_watch.h,docs/api/alloc_watch.md,game_loop.h/.cpp, related test/doc comments;laige-api.jsonregenerated (symbol set unchanged — line shifts + one summary text).Verification
ci:macoslabel) — they are the execution evidence.