summaryrefslogtreecommitdiff
path: root/lib/thread/spawn+openbsd.myr
blob: d330b5693c55b55c66c2380806f533cdf73ee6a4 (plain)
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
use std
use sys

pkg thread =
	type tid = uint64

	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, szp, fp, tos, tfp
	var ret

	stk = getstk(sz)
	if stk == sys.Mapbad
		-> `std.Fail "couldn't get stack"
	;;
	/* store size */
	tos = stk castto(std.intptr)
	tos -= sizeof(int64)
	szp = tos castto(sys.size#)
	szp# = Stacksz

	/* store func */
	tos -= sizeof((->void))
	fp = tos castto((->void)#)
	fp# = fn

	tfp = [
		.tcb = 0 castto(void#),
		.tid = &ret,
		.stk = tos castto(byte#),
	]
	if sys.__tfork_thread(&tfp, sizeof(sys.tforkparams), startthread castto(void#), 0 castto(void#))  < 0
		-> `std.Fail "couldn't spawn thread"
	;;
	-> `std.Ok (ret castto(tid))
}

const getstk = {sz
	var p, m

	p = sys.mmap(0 castto(byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon, -1, 0)
	if p == sys.Mapbad
		-> p
	;;
	/* stack starts at the top of memory and grows down. */
	m = p castto(std.intptr)
	m += sz castto(std.intptr)
	-> m castto(byte#)
}

const startthread = {fn : (-> void)
	fn()
	exit()
}