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