ref: ff88594df5c5df6fb8f227ab8e5df3529ba6e72f
dir: /lib/thread/spawn+openbsd.myr/
use std use sys use "common" use "tls" use "types" pkg thread = const spawn : (fn : (-> void) -> std.result(tid, byte[:])) pkglocal var exitstk : byte# ;; const Stacksz = 8*std.MiB extern const exit : (-> void) var exitstk const __init__ = { /* We need a valid stack at all times, so we allocate one ahead of time to swap to before we invalidate a stack. */ exitstk = getstk(16) std.assert(exitstk != sys.Mapbad, "error: failed to mmap exitstk\n") } const spawn = {fn; -> spawnstk(fn, Stacksz) } const spawnstk = {fn, sz var stk, tos, hdr, tfp, ret stk = getstk(sz) if stk == sys.Mapbad -> `std.Err "couldn't get stack" ;; (tos, hdr) = initstk(stk, fn, sz) tfp = [ .tcb = (hdr : void#), .tid = (&hdr.tid : sys.pid#), .stk = (tos : byte#), ] ret = sys.__tfork_thread(&tfp, sizeof(sys.tforkparams), (startthread : void#), (0 : void#)) if ret < 0 sys.munmap(stk, sz) -> `std.Err "couldn't spawn thread" ;; -> `std.Ok (ret : tid) } const initstk = {stk, fn, sz var len, tos, hdr, fp, env, envsz len = tlslen() tos = (stk : std.intptr) + (sz : std.intptr) tos -= (sizeof(tlshdr) + ((len : std.intptr) * sizeof(void#)) + 0xf) & ~0xf hdr = (tos : tlshdr#) hdr.len = len hdr.base = stk hdr.stksz = sz envsz = std.fnenvsz(fn) tos -= (envsz : std.intptr) env = tos tos -= sizeof((->void)) fp = (tos : (->void)#) fp# = std.fnbdup(fn, (env : byte#)[:envsz]) -> ((tos : byte#), hdr) } const getstk = {sz -> sys.mmap((0 : byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon | sys.Mstack, -1, 0) } const startthread = {fn : (-> void) fn() exit() }