Skip to content

LATX, feat: Add opt-in Guest TLS and explicit libc boundaries - #470

Draft
LaurenIsACoder wants to merge 5 commits into
lat-opensource:masterfrom
LaurenIsACoder:lauren/kzt-guest-tls
Draft

LATX, feat: Add opt-in Guest TLS and explicit libc boundaries#470
LaurenIsACoder wants to merge 5 commits into
lat-opensource:masterfrom
LaurenIsACoder:lauren/kzt-guest-tls

Conversation

@LaurenIsACoder

@LaurenIsACoder LaurenIsACoder commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Summary / 变更说明

A native library can call back into x86-64 Guest code from a pthread that never executed the Guest pthread initialization path. Such a thread needs its own Guest CPU, stack, TCB and DTV; copying an ELF TLS image alone does not establish a usable Guest libc thread context.

This draft adds default-off Guest TLS management for native-thread callbacks, followed by a separately activated interface for propagating selected libc state. The five commits are kept in one PR so reviewers can examine the preparation, runtime change and explicit libc interface in order.

Commit guide

Order Commit Purpose
1 2b0e27c77b94 Extract shared CPU-cloning setup without changing the existing thread policy.
2 d3df926d6b58 Share callback-frame handling and distinguish user callbacks from internal helpers, preserving the existing callback ABI.
3 924b71061743 Preserve an explicit -L runtime selection through LAT_LD_PREFIX across Guest exec, with a focused parent/child regression test.
4 794084bdf99e Add opt-in Guest TLS attachment, live-loader inventory and generation refresh, thread/fork/exit coordination, and focused tests. Initialize the attached TCB's real TID and robust-list fields before entering the Guest allocation helper.
5 4d7379d866e4 Add explicitly selected native-call boundaries for errno, h_errno and locale-name propagation. Keep locale projections owned by individual Guest contexts and document borrowed-handle lifetime.

The first four commits form the Guest TLS infrastructure; the fifth layers the libc boundary interface on top. This PR contains only these five commits and has no application-specific native-runtime adapter.

Transient loader-busy handling

A native thread can first call back while the Guest loader is changing its TLS inventory. Attachment previously collapsed a transient BUSY snapshot result into a hard failure and returned without executing the callback. Preserve that result before any Guest TLS allocation or helper execution, release the failed attempt's resources and locks, and retry with bounded backoff. Permanent initialization errors still fail immediately; persistent busy does not cause unlimited retries or context allocation.

The change belongs to commit 4. It does not implement general recovery from failures after Guest code has started or after a loader mutation has committed.

Activation and ownership

  • Guest TLS requires LATX_KZT_GUEST_TLS=1 and an effective KZT library group. The default remains off.
  • Enabling Guest TLS alone does not activate libc-state propagation. Consumers explicitly use the libc-boundary entry points; ordinary callbacks remain separate.
  • Native pthread/libc ownership is retained. Guest CPU/TLS resources belong to the attached context, and private libc pointers are not copied across the two libc instances.
  • Locale projections are per-context borrowed handles. Consumers must obtain an owned duplocale() copy before modifying or releasing one. Context teardown releases projections in their owning libc.

Details: Guest TLS and explicit libc boundaries.

Validation / 验证

Tested source: 4d7379d866e4197fb439ee142f1ebcedc7b2b2e5, without an application adapter, on a LoongArch ABI1 host with 16 KiB pages, GCC 8.3 and glibc 2.28. Guest fixtures were compiled and linked against a matching x86-64 glibc 2.28 sysroot, then executed on the LoongArch host.

Build and fast-suite commands:

mkdir -p build-review
cd build-review
../configure --target-list=x86_64-linux-user \
    --enable-latx --enable-kzt --enable-tests --disable-werror \
    --optimize-O1 --extra-ldflags=-ldl --disable-docs \
    --meson=meson --with-git-submodules=ignore
ninja -j6 latx-x86_64
meson test --suite lat-pr-fast --print-errorlogs

Full lat-pr-fast result: 27 passed, 0 failed, 0 skipped, 0 timed out.

Rebased onto upstream bfe17ae7c1b5c32e3f519dd52da280b6988ef43d before this validation. The no-adapter PR endpoint was independently rebuilt and tested. The optional kzt-attach-busy.gdb regression passes all three cases: a single busy snapshot is retried and the callback executes; a permanent error remains an error; persistent busy exits within the retry budget.

Focused fixtures were executed directly using the separately built Guest/Host artifacts. The native callback invocation uses:

run_guest_fixture() {
    env LD_PRELOAD="$HOST_PROBE" \
        BOX64_LD_LIBRARY_PATH="$GUEST_LIBS" \
        LATX_AOT=0 LATX_KZT=1 LATX_KZT_LIBS=core,x11 \
        LATX_KZT_GUEST_TLS=1 \
        "$EMULATOR" -U LD_PRELOAD -E "LD_LIBRARY_PATH=$GUEST_LIBS" \
        -L "$GUEST_ROOT" "$@"
}
Focused check Result
Existing-thread callbacks with Guest TLS unset and set to 0; native-thread attachment with it set to 1 Passed all three cases.
TID at the actual Guest loader allocation-helper entry (kzt-bootstrap-tid.gdb) The old binary entered with TID 0; the fixed binary passed all seven observed entries and exited normally.
Two-thread explicit libc/locale boundary fixture Failed with the old shared projection cache; passed with per-context projections, including mutation/release of an owned duplicate.
Attached robust-mutex owner exit A blocked Guest waiter was awakened and received EOWNERDEAD.
Dynamic TLS loading Passed 64 A/B dlopen/dlclose cycles involving Guest, native-attached and concurrent threads.
Runtime root across exec Passed both exported-selection and mapped-libc checks in parent and child. Removing only the runtime-selection fix made the fixture fail.

The first four-commit endpoint was also built independently and passed its applicable focused checks. The integration runners are registered with Meson; compiler-dependent runners were not all executed end-to-end on this host, so the direct-fixture results above should not be read as a complete latx-integration suite pass.

Draft review points and remaining limits

  • Unrecoverable errors: the implementation retains process termination where loader/TLS consistency cannot be guaranteed, including some post-load/post-unload failures. General safe abort of an arbitrary Guest callback back into the Host is not implemented. Please review whether this failure policy is acceptable for the explicitly enabled profile; this is still an open design decision before merge.
  • Resolver state: the extended ABI1 probe observes shared Guest __res_state() backing storage on attached threads. Resolver APIs are outside the supported attached-thread profile; errno/h_errno propagation is not resolver isolation.
  • The supported profile is x86-64 glibc Guest TLS. Other libc layouts, additional loader namespaces, PI robust futexes and arbitrary non-local exits need separate work and validation.
  • This validation uses an O1 test build. The complete release/configuration matrix, additional integration coverage and real-application acceptance remain separate gates. No zero-overhead or complete application-compatibility claim is made.

Checklist / 检查项

  • I have read CONTRIBUTING.md. / 我已阅读 CONTRIBUTING.md
  • Every commit contains an existing author-matching DCO sign-off. / 每个提交均保留与作者一致的 DCO 签署。
  • Relevant build/test results and remaining validation limits are included. / 已提供构建、测试结果和剩余验证边界。

Extract CPU clone initialization without changing existing callers or thread policy.

Signed-off-by: Hanlu Li <heuleehanlu@gmail.com>
Preserve the existing callback ABI, including float results and Host floating-point register preservation. Add explicit helper-call entry points for subsequent TLS initialization.

Signed-off-by: Hanlu Li <heuleehanlu@gmail.com>
Keep common runtime options available in release builds and propagate an explicit -L selection through LAT_LD_PREFIX. A re-executed Guest must use the same loader and libc as its parent.

Add test-runtime-prefix-exec to check the exported selection and mapped Guest libc before and after exec. Reverting the runtime-root fix makes the fixture fail; the fixed build passes on LoongArch ABI1.

Signed-off-by: Hanlu Li <heuleehanlu@gmail.com>
Keep Guest TLS management disabled unless LATX_KZT_GUEST_TLS=1 and KZT is effective. Attach native-created threads from an immutable template, initialize Guest TLS from live loader state, and coordinate generation refresh, callback execution, fork and thread exit. Keep existing library registration and disabled-mode loader behavior. Add policy, loader and native-thread callback tests.

Initialize the attached TCB thread ID and robust-list fields before calling the Guest loader allocation helper. The debugger regression reaches that helper with TID 0 before the fix and with the real thread ID after it. Opt-in off/on, robust owner death and 64-cycle dynamic loading regressions pass on LoongArch ABI1.

Supply the new runtime-gate variables in the standalone TB-flush test fixture so the complete KZT-enabled lat-pr-fast suite links and runs.

Co-authored-by: sunguoyun <sunguoyun@loongson.cn>

Signed-off-by: Hanlu Li <heuleehanlu@gmail.com>
…ries

Provide an initially inactive libc boundary broker for errno, h_errno and locale names. Keep Guest thread destruction in the TLS runtime. Consumers explicitly initialize and activate the broker; enabling Guest TLS alone does not enable semantic propagation. Keep private libc pointers within their owning domain.

Own locale projections per Guest context, document borrowed handles, and release each projection in its owning libc during context teardown. The two-thread regression fails with the old shared cache and passes with separate contexts, including mutation and release of an owned duplicate.

Signed-off-by: Hanlu Li <heuleehanlu@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant