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

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 ran the Guest pthread initialization path. This draft adds default-off Guest TLS attachment for those callbacks and a separately activated interface for selected libc state.

The branch stays as one five-commit series. The review fixes are folded into the existing Guest TLS commit; no follow-up fix commit was added.

Commit guide

Order Commit Purpose
1 edaa9425856 Share CPU cloning setup without changing thread policy.
2 182f1cba1df Share callback frames and distinguish user callbacks from internal helpers.
3 e183e0fbb84 Preserve the selected Guest runtime root across exec.
4 a1991d92a06 Add opt-in Guest TLS attachment, loader refresh, fork/exit coordination, and focused regressions.
5 e97cb175aaf Add explicitly selected errno, h_errno, and locale propagation boundaries.

Review changes

  1. DTV generation: the private attached-thread inventory version is no longer written to dtv[0]. A separate loader generation is seeded from a DTV initialized by the Guest loader, then advanced once for each r_brk transaction whose Guest-loader TLS inventory changes. This records consecutive load/unload transactions even when no attached callback runs between them. KZT-only external registrations do not advance this generation. An early loader callback prepares constructor TLS without committing the attached inventory; callbacks reached while the serialized loader operation is active use the same preparation-only path. The completed refresh publishes the tracked loader generation without calling _dl_allocate_tls_init again or reinitializing live TLS values.
  2. Blocking attached callbacks: selected blocking I/O and non-PI futex waits temporarily release only the fork execution guard. The callback keeps its CPU/TLS ownership and native cancellation remains disabled. Internal helpers and threads already preparing fork do not take this path.
  3. Aborted fork syscalls: early fork-writer ownership now has idempotent abort handling for seccomp rejection, syscall-user-dispatch rejection, failure, and restart completion. A real internal restart keeps the scope; a seccomp errno numerically equal to a restart code closes it.
  4. Full TB flush: the Guest fork entry hook is installed together with the loader hook after a complete TB flush. Saved translated instructions are reset for the new TB, the Guest address is retained for the current exec image, and exec clears the cached address.

The Guest TLS commit also includes the GLib declaration headers required to build the current upstream AOT tests with older GLib headers and warnings treated as errors.

Activation and ownership

  • Guest TLS requires LATX_KZT_GUEST_TLS=1 and an effective KZT library group. The default remains off.
  • Guest TLS does not implicitly activate libc-state propagation. Consumers select the libc boundary explicitly.
  • Native pthread/glibc state remains authoritative. Guest CPU/TLS allocations belong to their attached contexts, and private pointers are not copied between libc instances.
  • Locale projections are owned per Guest context; a borrowed handle must be duplicated before modification or release.

Validation

The final source is rebased onto upstream 97429a33e82e0957baac261f1ec2ba343e599700 and was built on LoongArch64 with 16 KiB pages, GCC 8.3, and host glibc 2.28:

mkdir build && cd build
../configure --target-list=x86_64-linux-user \
    --enable-latx --enable-kzt --optimize-O1 \
    --extra-ldflags=-ldl --disable-docs --enable-tests
ninja -j16
meson test --suite lat-pr-fast --print-errorlogs
  • Complete lat-pr-fast: 34 passed, 0 failed, 0 skipped.
  • New lifecycle regressions on Guest glibc 2.28: 8/8 passed.
  • The same lifecycle regressions on Guest glibc 2.39: 8/8 passed.
  • Existing robust mutex, pthread TSD alias, C++ TLS lifetime, and 64-cycle A/B TLS dlopen stress: 4/4 passed, including cold/warm AOT rounds.
  • Explicit bidirectional errno, h_errno, and locale boundary: passed.
  • The DTV regression keeps one native-attached thread alive while ordinary Guest code performs consecutive TLS load/unload transactions; the retained value remains 12345 rather than reverting to its initializer.
  • The full-flush regression observes the fork hook after a complete TB flush and completes the Guest-libc lock-contention topology.

A downstream composition using the dependent liblat branch and a separate JVM adapter also passed lat-pr-fast 34/34. MATLAB R2020b completed three consecutive desktop runs: JVM and native JVM/NBL mappings were observed, arithmetic completed, the desktop window matched the process, each run remained active for 90 seconds, and all three exited naturally with status 0. Ready times were 19.29 s, 18.28 s, and 19.30 s. The JVM adapter and NBL sources are not part of this PR.

Remaining limits

  • A separate topology where the native-attached thread itself calls Guest fork() still produces a child failure on both the old and new branches. It is outside the four reviewed cases and remains open.
  • Resolver-state isolation and non-glibc Guest layouts remain outside the supported attached-thread profile.
  • This PR remains Draft pending renewed review and hosted CI for the rewritten head.

Checklist

  • Read CONTRIBUTING.md.
  • All five commits preserve their author-matching DCO sign-offs.
  • Final candidate build, focused regression, complete fast-suite, LoongArch, and downstream application evidence are recorded above.

@LaurenIsACoder
LaurenIsACoder force-pushed the lauren/kzt-guest-tls branch 2 times, most recently from 4d7379d to e1262a7 Compare September 13, 2026 08:25
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