Background
Go implements syscall.AllThreadsSyscall by stopping the world and running the same syscall on every OS thread registered in the runtime. It deliberately returns ENOTSUP when cgo is linked because the runtime cannot account for arbitrary threads created by C.
LLGo has the same limitation, and it is stronger in C-library modes: a host executable and its libraries may create threads before or after loading LLGo code. Enumerating /proc/self/task finds snapshots of Linux thread IDs, but does not by itself solve creation races, safely interrupt every thread, or coordinate with non-LLGo code.
PR #2098 therefore returns ENOTSUP. A real implementation needs an explicit thread-ownership design rather than a best-effort process scan.
Proposal
Define the supported thread set separately for each build mode.
Standalone executables
- register every OS thread created or adopted by the LLGo runtime
- synchronize thread creation and destruction with an all-thread operation
- establish a stop/barrier and per-thread syscall protocol
- compare results exactly as the Go runtime does and fail safely on disagreement
- define signal-mask, locked-thread, callback, and teardown behavior
c-shared and c-archive
- keep
ENOTSUP by default because LLGo does not own all process threads
- document whether an optional host-cooperation API is useful and safe
- do not treat
/proc/self/task enumeration alone as correctness
Other platforms
The design must state whether support is Linux-only initially or how Darwin and other pthread targets obtain equivalent guarantees.
Acceptance criteria
- a precise definition of LLGo-owned, adopted, and foreign threads
- race-free behavior during concurrent thread creation and exit
- functional multi-thread tests using a harmless syscall such as
getpid
- negative tests proving C-library modes return
ENOTSUP when foreign threads may exist
- stress and race/sanitizer coverage for the synchronization protocol
This proposal is intentionally separate from libc trampolines and synctest scheduling.
Related: #2098, #2129
Background
Go implements
syscall.AllThreadsSyscallby stopping the world and running the same syscall on every OS thread registered in the runtime. It deliberately returnsENOTSUPwhen cgo is linked because the runtime cannot account for arbitrary threads created by C.LLGo has the same limitation, and it is stronger in C-library modes: a host executable and its libraries may create threads before or after loading LLGo code. Enumerating
/proc/self/taskfinds snapshots of Linux thread IDs, but does not by itself solve creation races, safely interrupt every thread, or coordinate with non-LLGo code.PR #2098 therefore returns
ENOTSUP. A real implementation needs an explicit thread-ownership design rather than a best-effort process scan.Proposal
Define the supported thread set separately for each build mode.
Standalone executables
c-sharedandc-archiveENOTSUPby default because LLGo does not own all process threads/proc/self/taskenumeration alone as correctnessOther platforms
The design must state whether support is Linux-only initially or how Darwin and other pthread targets obtain equivalent guarantees.
Acceptance criteria
getpidENOTSUPwhen foreign threads may existThis proposal is intentionally separate from libc trampolines and synctest scheduling.
Related: #2098, #2129