ref: bdcd9c57965c02da5e30e71ff5eaeb0a71b26ca4
dir: /lib/thread/spawn+osx.myr/
use sys use std use "tls" use "types" pkg thread = const spawn : (fn : (-> void) -> std.result(tid, byte[:])) ;; const Stacksz = 8*std.MiB extern const exit : (-> void) extern const start : (-> void) const __init__ = { var ret ret = sys.bsdthread_register(\ (start : void#), \ /* start */ (0 : void#), \ /* wqthread */ (0 : uint32), \ /* sz */ (0 : uint32), \ /* dummy */ (0 : void#), \ /* targconc */ (0 : uint32)) /* queueoff */ if ret < 0 std.fatal("unable to init threads: {}", ret) ;; } const spawn = {fn -> spawnstk(fn, Stacksz) } const spawnstk = {fn, sz var stk, tos, 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 = initstk(stk, fn, sz) ret = sys.bsdthread_create( \ (tramp : void#), \ /* start */ (tos : void#), \ /* arg */ (tos : void#), \ /* stack */ (0 : void#), \ /* pthread struct */ 0x01000000) /* flags (PTHREAD_START_CUSTOM): don't alloc stack in kernel */ if (ret : std.size) < 0 sys.munmap(stk, sz) -> `std.Err "couldn't spawn thread" ;; -> `std.Ok (stk : 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.tid = (stk : tid) hdr.len = len hdr.base = stk hdr.stksz = sz fn = std.fndup(fn) var fn1 = { setgsbase(hdr) fn() std.fnfree(fn) } envsz = std.fnenvsz(fn1) tos -= (envsz : std.intptr) env = tos tos -= sizeof((->void)) fp = (tos : (->void)#) fp# = std.fnbdup(fn1, (env : byte#)[:envsz]) -> (tos : byte#) } /* thread trampoline, called by `start`. We set up the args for the closure and env on the stack, and then we call it from here, doing the cleanup and exit at the end. */ const tramp = {f : (-> void)# f#() exit() }