ref: c039e23ae4fd65431fb40f6d556d72a977725b0f
dir: /lib/thread/spawn+freebsd.myr/
use sys use std use "common" use "fsbase" use "tls" use "types" pkg thread = const spawn : (fn : (-> void) -> std.result(tid, byte[:])) ;; const Stacksz = 8*std.MiB extern const exit : (-> void) const spawn = {fn -> spawnstk(fn, Stacksz) } const spawnstk = {fn, sz var stk, tos, stksz, hdr, tid = -1, ret stk = sys.mmap((0 : byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon, -1, 0) if stk == sys.Mapbad -> `std.Err "couldn't get stack" ;; (tos, stksz, hdr) = initstk(stk, fn, sz) ret = sys.thr_new(&[ .startfn = (startthread : void#), .arg = (tos : void#), .stkbase = (stk : byte#), .stksz = stksz, .tid = (&hdr.tid : uint64#), .ptid = &tid, .flags = 2, .rtp = Zptr, ], sizeof(sys.thrparam)) if ret < 0 sys.munmap(stk, sz) -> `std.Err "couldn't spawn thread" ;; -> `std.Ok (tid : tid) } const initstk = {stk, fn, sz var stksz, len, tos, hdr, fp, env, envsz stksz = sz len = tlslen() stksz -= (sizeof(tlshdr) + ((len : sys.size) * sizeof(void#)) + 0xf) & ~0xf tos = (stk : std.intptr) + (stksz : std.intptr) hdr = (tos : tlshdr#) hdr.base = stk hdr.stksz = sz fn = std.fndup(fn) var fn1 = { /* We write `hdr.len` here because it follows `hdr.tid` so it gets overwritten by the kernel in `thr_new`. Even though `sys.pid` is 32 bits, `thr_param.tid` is a `uint64#` for legacy reasons. */ hdr.len = len setfsbase(hdr) fn() std.fnfree(fn) } envsz = std.fnenvsz(fn1) tos -= (envsz : std.intptr) stksz -= (envsz : sys.size) env = tos tos -= sizeof((->void)) stksz -= sizeof((->void)) fp = (tos : (->void)#) fp# = std.fnbdup(fn1, (env : byte#)[:envsz]) -> ((tos : byte#), stksz, hdr) } const startthread = {f : (-> void)# f#() exit() }