[Based on #2079] runtime: store goroutine state in //llgo:gls#2090
Open
cpunion wants to merge 15 commits into
Open
[Based on #2079] runtime: store goroutine state in //llgo:gls#2090cpunion wants to merge 15 commits into
cpunion wants to merge 15 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
cpunion
force-pushed
the
codex/runtime-g-state-gls
branch
2 times, most recently
from
July 15, 2026 00:48
b543675 to
57ae899
Compare
cpunion
force-pushed
the
codex/runtime-g-state-gls
branch
from
July 15, 2026 08:54
57ae899 to
b651488
Compare
cpunion
marked this pull request as ready for review
July 15, 2026 10:22
cpunion
force-pushed
the
codex/runtime-g-state-gls
branch
2 times, most recently
from
July 15, 2026 20:52
63fe488 to
56564e7
Compare
This was referenced Jul 16, 2026
cpunion
force-pushed
the
codex/runtime-g-state-gls
branch
3 times, most recently
from
July 18, 2026 23:20
353c562 to
e363bbe
Compare
cpunion
force-pushed
the
codex/runtime-g-state-gls
branch
from
July 20, 2026 03:40
b373c9d to
a309b55
Compare
Store each immutable Func as one atomic pointer and validate the queried PC from the Func itself. This prevents concurrent cache replacement from combining a PC and function from different writers. Apply the same publication rule to the prebuilt function cache and stress multiple PCs during concurrent first use.
Give each package-backed locality block an owner-local TLS cache so hot accesses are O(1) regardless of the number of touched packages. Keep the block list only for GC reachability and teardown. Require locality variables to be unexported and reject go:linkname aliases. Add codegen, lifecycle, and 2/4/8-package performance coverage.
cpunion
force-pushed
the
codex/runtime-g-state-gls
branch
from
July 20, 2026 04:24
a309b55 to
34387d1
Compare
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.
Depends on #2079
Dependency
This PR is stacked on #2079 at
bf50d5347. #2079 provides//llgo:glsand the local-context lifecycle used here. The GitHub base remainsmainbecause the dependency branch is in a fork. The runtime-state implementation is37e6cd4a3; the follow-up pure-C linkage regression fix isd5bf6b8de.Problem
The hosted runtime currently stores state owned by one goroutine in several pthread-backed locations:
pthread_selfandpthread_equal.This gives related state separate ownership and lifetime rules, adds pthread-key lookups to the defer path, and makes every new per-goroutine field require more runtime machinery.
Change
Store the state in one runtime-owned
g:getgreturns¤tG; defer, panic/recover, Goexit, and main detection access fields of that object. This removes the three pthread keys, the pthread-backed defer handle, andmainThread.On hosted LLGo targets,
currentGis goroutine-local through #2079. Host builds and the currently single-context bare-metal and Nintendo Switch targets use the samegrepresentation backed by one ordinary global variable. No target logic is added to the compiler.The variable is zero-initialized. Normal package initialization marks only the initial context as main. A new goroutine gets zeroed runtime-package storage when it first reaches
getg; normal entry/exit and the non-returning Goexit path use #2079's existing context lifecycle.C library startup
With
currentGin GLS,runtime.initbecame the first runtime path that requires a local context. C library constructors previously called it before C entered an exported Go function; on Linuxc-archive, that crashed beforemain. Commit34387d149makesc-sharedandc-archiveconstructors install a process-lifetime context beforeruntime.init. Exported calls on the constructor thread inherit it, while calls from other C threads keep their entry-scoped contexts.Runtime cost
Apple M4 Max, macOS arm64, Go 1.26.5, LLVM 19.1.7,
GOMAXPROCS=2. Results are medians of 8 adjacent 750 ms samples. The hot accessor reports 0 B/op and 0 allocs/op; the goroutine rows report the B/op values below and 0 allocs/op.GetThreadDeferThe hot accessor is about 35.9% faster than the pthread-key baseline. Goroutines that do not touch the runtime
gshow no space regression. First defer use is about 65 B/goroutine higher because this PR intentionally leaves cold package-block allocation unoptimized: the 24-bytegpayload also needs the shared block header, alignment, and allocator rounding.Coverage and validation
The root Codecov job does not instrument production files in the nested
runtimemodule, so a passing patch percentage alone does not demonstrate these runtime paths. The previous 84.17722% Codecov report was generated after CI was cancelled: the macOS root coverage test was interrupted, and Ubuntu completed the test but was cancelled before upload, so Codecov only had the Dev LTO subset. Localatomiccoverage on the current stacked head reports 88.2% forssa; every function previously listed as missing inssa/locality.go,ssa/decl.go, andssa/package.gois 100% covered. Head37e6cd4a3completed both root coverage jobs, and Codecov reported that all modified and coverable lines were covered. Headd5bf6b8deis rerunning CI; locally, the affected entry-module paths reach 85.3% function coverage and the original Linux/amd64 pure-C PCLN integration failure passes. One macOS primary shard first hit the 30-minute job limit without a test error, then passed on the targeted rerun in 18m49s. The nested-runtime implementation is instead exercised by real LLGo integration tests:TestRuntimeGStateIsolationexercises concurrent defer ordering, panic/recover isolation, Goexit, and main-goroutine state.TestRuntimeDeferHeadIsolationobserves real active defer frames in two goroutines, verifies distinct heads, and verifies restoration after return.TestRuntimeDeferAccessorsexercises the Set/Get/Clear state transitions independently in two goroutines.Local validation was serialized with
GOMAXPROCS=2andGOFLAGS=-p=1; no existing test was skipped or ignored.test/go, and fulltest/llgoextpass; the new defer tests also pass 100 repetitions.selectsexecution, fulltest/go, and fulltest/llgoextpass in a container limited to 2 CPU and 512 PID, with a requested 15 GiB cap and an effective 11.66 GiB Docker VM cap.Commits
runtime: store goroutine state in GLS(37e6cd4a3)build: avoid runtime linkage for pure C programs(d5bf6b8de)runtime: initialize GLS context for C libraries(34387d149)Implements the runtime-state consumer described in #2077 on top of #2079.