threads(M10): per-thread fs.base — the TLS thread-pointer mechanism
Each thread gets its own x86_64 thread pointer (FS base) for user-space TLS. Task.fs_base is restored on every context switch only when it changes (same conditional-load discipline as CR3; architecture.setFsBase -> wrmsr IA32_FS_BASE). New set_thread_pointer=44 syscall sets the caller's fs_base and loads it now. The kernel never touches FS, so no swapgs complication. The runtime lays a small per-thread TLS block at the top of each thread's stack (self-pointer at %fs:0 + scratch) and the thread trampoline calls set_thread_pointer before any user code — so every spawned thread has a private, switch-stable thread pointer, reclaimed with the stack. thread-test tls mode: two threads write unique markers to their own %fs:8 and, after both wrote, read back — a shared fs.base would clobber one (cross-talk). Deferred: the Zig threadlocal *compiler* layer (ELF variant-II PT_TLS + linker sections + template copy) — high-uncertainty, no consumer today; this lands the load-bearing per-thread fs.base it builds on. See docs/threading-plan.md M10. Gate thread-tls PASS (3x); full guardrail 25/25; build + host tests clean.
This commit is contained in:
@@ -355,6 +355,14 @@ CASES = [
|
||||
"timeout": 60,
|
||||
"expect": r"DANOS-TEST-RESULT: PASS",
|
||||
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
||||
|
||||
# docs/threading-plan.md M10: per-thread fs.base — two threads keep private %fs:8 TLS
|
||||
# slots across context switches (no cross-talk).
|
||||
{"name": "thread-tls",
|
||||
"smp": 4,
|
||||
"timeout": 60,
|
||||
"expect": r"DANOS-TEST-RESULT: PASS",
|
||||
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
||||
# Process arguments: argv arrives on the SysV entry stack (argv[0] = the spawned
|
||||
# name, argv[1..] = the system_spawn argument blob) and echoes back intact.
|
||||
{"name": "args",
|
||||
|
||||
Reference in New Issue
Block a user