code wiki / (root) / nx_thread_pool.nx

nx_thread_pool.nx

buildroot/runtime/nx_thread_pool.nx

16333 B363 linesdepth 6pulls 8 transitivereach 198 importersview sourcekind tooltopic thread
docsdependenciesstructsconstsfunctions

about

nx_thread_pool.nx -- shared-queue thread pool (Rayon-precursor). Architecture: hw-sized worker fleet + single Vyukov MPMC queue of task records. Workers spin on the channel; each task carries a typed fn-pointer + ctx; sentinel tasks (is_sentinel == 1) signal a worker to exit. MVP shape -- single shared queue, not yet work-stealing. Work- stealing buys you locality when one worker is starving and another is buried; for compute-bound tasks of comparable cost the shared- queue model is within ~5% of work-stealing (per Rayon's own bench). Composes upward to work-stealing in a follow-up by giving each worker a private deque + a steal protocol; the public API does not change. Tasks live in a bump-allocated arena (NxPoolTask). Submit picks the next slot via atomic FAA on `next_task_slot`, fills it, sends the slot pointer through the channel. Worker receives the pointer, calls task.fn(task.ctx), bumps the completed-counter. Slot reuse is a future concern -- bench first. Composes against: [[vyukov_mpmc_channel]] (queue), [[atomic_intrinsics_real_amo]] (FAA counters), [[thread_clone_native_trampoline]] (worker spawn), [[nx_hw_dynamic_probes]] (worker sizing), [[fn_ptr_indirect_call]] (typed call site).

dependencies 5 imports · 38 importers

nx_syscalls.nx nx_atom.nx nx_thread.nx nx_chan.nx nx_hw.nx nx_thread_pool.nx nx_conv2d.nx nx_conv_speedup.nx nx_dot_simd_demo.nx nx_f32_llama_block_v4.nx nx_f32_llama_v4b.nx nx_f32_llama_v4p.nx nx_f32_matmul_t.nx nx_f32_q4k_matmul.nx nx_intfp_lm_simd_gate.nx nx_natfu_probe.nx

diagram shows first 10 each side; +0 more imports, +28 more importers in the complete lists below.

imports: nx_syscalls.nxnx_atom.nxnx_thread.nxnx_chan.nxnx_hw.nx

imported by: nx_conv2d.nxnx_conv_speedup.nxnx_dot_simd_demo.nxnx_f32_llama_block_v4.nxnx_f32_llama_v4b.nxnx_f32_llama_v4p.nxnx_f32_matmul_t.nxnx_f32_q4k_matmul.nxnx_intfp_lm_simd_gate.nxnx_natfu_probe.nxnx_nofloat_llm.nxnx_parallel.nxnx_parallel_simd_reduce.nxnx_parallel_test.nxnx_pipeline.nxnx_pipeline_test.nxnx_pool_ring_gate.nxnx_pool_stale_gate.nxnx_poolheavy.nxnx_ppdemo_parallel.nxnx_pteam.nxnx_q5_0_threaded_gate.nxnx_q5q8_ab.nxnx_q8_0_simd_gate.nxnx_q8_coldwarm.nxnx_q8_matmul_micro.nxnx_q8_mix_ab.nxnx_q8_scaling.nxnx_q8_st_bw.nxnx_qwen_native_gate.nxnx_qwen_wsl_timing_gate.nxnx_reader_squad_f32_gate.nxnx_sdfrender_mt.nxnx_sum_bench_all.nxnx_ta_parallel_grad_gate.nxnx_task_graph.nxnx_task_graph_test.nxnx_thread_pool_test.nx

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main nx_pool_new nx_hw_worker_count nx_hw_cpu_count sys_mmap sys_munmap sys_mmap ↻ nx_chan_new sys_mmap ↻ _nx_chan_cell sys_thread_create nx_thread_spawn sys_mmap ↻ nx_thread_spawn_fn sys_mmap ↻ nx_pool_submit nx_atom_faa_i64 nx_chan_send nx_chan_try_send _nx_chan_cell ↻ nx_thread_yield _pool_futex_wake_all sys_futex_wake nx_pool_wait nx_atom_load_i64 nx_thread_yield ↻ nx_atom_store_i64 _pool_futex_wait sys_futex_wait nx_pool_n_completed nx_atom_load_i64 ↻ nx_pool_shutdown nx_atom_faa_i64 ↻ nx_chan_send ↻ _pool_futex_wake_all ↻ nx_atom_load_i64 ↻ nx_thread_yield ↻ nx_pool_n_alive nx_atom_load_i64 ↻

structs

43struct NxPoolTask
56struct NxThreadPool

consts

39const NX_MAGIC_2147483647: i64 = 2147483647
40const NX_MAGIC_65536: i64 = 65536
41const NX_MAGIC_2000000000: i64 = 2000000000
49const NX_POOL_TASK_BYTES: i64 = 24
54const NX_POOL_ARENA_DEFAULT: i64 = 16384
74const NX_POOL_OFF_NEXT_SLOT: i64 = 24
75const NX_POOL_OFF_ALIVE: i64 = 40
76const NX_POOL_OFF_SUBMITTED: i64 = 48
77const NX_POOL_OFF_COMPLETED: i64 = 56
78const NX_POOL_OFF_TASK_EPOCH: i64 = 64
79const NX_POOL_OFF_WAITING: i64 = 72
96const NX_FUTEX: i64 = 98 // rv64 futex (table -> x86_64 202)
97const NX_FUTEX_WAIT_PRIV: i64 = 128 // FUTEX_WAIT | FUTEX_PRIVATE_FLAG
98const NX_FUTEX_WAKE_PRIV: i64 = 129 // FUTEX_WAKE | FUTEX_PRIVATE_FLAG
99const NX_POOL_SPIN: i64 = 64 // yields before sleeping. (TESTED 2026-07-10: busy-spin@50k helped pteam +54% but pool only +3% = noise, at the cost of idle-CPU burn for ALL shared-pool users -> reverted to idle-friendly yield-spin.)

functions

107func nx_pool_set_native(v: i64) -> i64 { g_pool_native = v; return 0 }
called by 1: main
108func nx_pool_is_native() -> i64 { return g_pool_native }
113func sys_futex_wait(addr: i64, seen: i64) -> i64
116func sys_futex_wake(addr: i64) -> i64
119func _pool_futex_wait(addr: *i64, seen: i64) -> i64
123func _pool_futex_wake_all(addr: *i64) -> i64
129func _nx_pool_worker_main(arg: *u8) -> i64
180func nx_pool_new(n_workers: i64, queue_cap: i64) -> *NxThreadPool
245func nx_pool_set_serial(v: i64) -> i64 { g_pool_serial = v; return 0 }
called by 1: main
247func nx_pool_submit(pool: *NxThreadPool, fn: func(i64) -> i64, ctx: i64) -> i64
277func nx_pool_wait(pool: *NxThreadPool, expected: i64) -> i64
304func nx_pool_shutdown(pool: *NxThreadPool) -> i64
332func nx_pool_n_alive(pool: *NxThreadPool) -> i64
called by 2: mainmain calls 1: nx_atom_load_i64
337func nx_pool_n_completed(pool: *NxThreadPool) -> i64
345func _nx_pool_self_test_task(ctx: i64) -> i64
349func main() -> i64