ref: ad2292fd624c6e2979388fb93f06dd20643ca507
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()
}