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