ref: bdf0ed62196f1e67d65b3346ae45d1a0e322bd00
dir: /lib/thread/spawn+linux.myr/
use sys use std use "common" use "tls" use "types" pkg thread = const spawn : (fn : (-> void) -> std.result(tid, byte[:])) ;; const Stacksz = 8*std.MiB extern const exit : (-> void) /* Holy shit flag mania. */ const Thrflag = sys.Clonevm | sys.Clonefs | sys.Clonefiles | \ sys.Clonesighand | sys.Clonethread | sys.Clonesettls | \ sys.Clonechildsettid const spawn = {fn -> spawnstk(fn, Stacksz) } const spawnstk = {fn, sz var stk, tos, hdr, 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, hdr) = initstk(stk, fn, sz) ret = sys.fnclone(Thrflag, tos, Zptr, (hdr : byte#), (&hdr.tid : sys.pid#), Zptr, (startthread : 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 startthread = {fn : (-> void) fn() exit() }