threads(M4): futex_wait/futex_wake, the blocking primitive
New private syscalls futex_wait(addr, expected, timeout_ns)=40 and futex_wake(addr, count)=41. A waiter is a .blocked task tagged with Task.futex_addr (no queue linkage); futex_wait reads the user word under the big lock and parks only if it still equals expected, so a concurrent wake can't slip between the check and the block. futex_wake scans the task table and readies up to count waiters in the same address space. A timed wait also sets wake_at so the existing wakeExpired times it out; futex_addr staying non-zero (only futex_wake clears it) distinguishes timeout from a real wake. Waiters park in-kernel, so an idle core still halts (no busy-wait). runtime.Thread.Futex mirrors std.Thread.Futex (wait/timedWait/wake). thread-test gains a futex mode: a waiter parks, the main thread wakes it (serial order waiting/waking/woke, asserted by the case regex), and timedWait reports a timeout. Gate thread-futex PASS (3x); 18 guardrail cases green incl. sleep/event/ipc blocking paths; build + host tests clean.
This commit is contained in:
@@ -66,9 +66,16 @@ pub const SystemCall = enum(u64) {
|
||||
thread_spawn = 37, // thread_spawn(entry, stack_top, arg, exit_endpoint) -> tid: start a task sharing the caller's address space at `entry` on `stack_top`, `arg` in rdi; exit_endpoint (a handle, or no_cap) is notified when it ends — how join waits (docs/threading.md)
|
||||
thread_exit = 38, // thread_exit(): end the calling thread, dropping one reference to its address space (destroyed on the last)
|
||||
current_core = 39, // current_core() -> index: the dense 0-based index of the core the caller is running on (for parallelism/affinity introspection)
|
||||
futex_wait = 40, // futex_wait(addr, expected, timeout_ns) -> status: if *addr == expected, block until woken or the timeout; returns futex_woken/mismatch/timed_out (docs/threading.md)
|
||||
futex_wake = 41, // futex_wake(addr, count) -> woken: wake up to `count` tasks blocked in futex_wait on `addr` in this address space
|
||||
_,
|
||||
};
|
||||
|
||||
/// `futex_wait` return codes (in rax).
|
||||
pub const futex_woken: u64 = 0; // woken by a futex_wake
|
||||
pub const futex_mismatch: u64 = 1; // *addr != expected on entry; the caller did not block
|
||||
pub const futex_timed_out: u64 = 2; // the timeout elapsed before a wake
|
||||
|
||||
/// How a process ended — recorded by the kernel at death, queried by the
|
||||
/// supervisor with `process_exit_reason`, and the input to its restart decision
|
||||
/// (docs/process-lifecycle.md): a clean exit meant to stop, a fault wants a
|
||||
|
||||
Reference in New Issue
Block a user