1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
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()
}
|