shithub: mc

Download patch

ref: 85fac5706cb0c63869be6512e1d61731428e3b19
parent: 317eb918900dfe2a9e37fcc5acde58400b143f5a
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Dec 14 17:28:31 EST 2015

Spawn and exit on FreeBSD

--- a/lib/thread/bld.proj
+++ b/lib/thread/bld.proj
@@ -8,7 +8,22 @@
 	future+linux.myr
 	exit+linux-x64.s
 
+	# freebsd impl of thread primitives
+	spawn+freebsd.myr
+	exit+freebsd-x64.s
+
+	# shitty spinlock based fallbacks
+	condvar.myr
+	mutex.myr
+	future.myr
+
 	atomic-impl+x64.s
 	atomic.myr
 ;;
 
+bin smoketest =
+	atomictest.myr
+	test/util.myr
+
+	lib thread
+;;
--- /dev/null
+++ b/lib/thread/exit+freebsd-x64.s
@@ -1,0 +1,23 @@
+/*
+const thread.exit	: (stacksz : std.size -> void)
+NOTE: must be called from the bottom of the stack, since
+we assume that %rbp is in the top 4k of the stack.
+*/
+.globl thread$exit
+thread$exit:
+	/* find top of stack */
+	movq	%rbp,%rdi	/* addr */
+	andq	$~0xfff,%rdi	/* align it */
+	addq	$0x1000,%rdi
+
+	/* munmap(base, size) */
+	movq	$73,%rax	/* munmap */
+	movq	-8(%rdi),%rsi	/* size */
+	subq	%rsi,%rdi	/* move to base ptr */
+	syscall
+
+	/* thr_exit(null) */
+	movq	$431,%rax	/* exit */
+	xorq	%rdi,%rdi	/* 0 */
+	syscall
+	
--- /dev/null
+++ b/lib/thread/spawn+freebsd.myr
@@ -1,0 +1,74 @@
+use sys
+use std
+
+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 : byte#, tid, ctid, ret
+	var szp, fp, tos
+
+	stk = getstk(sz)
+	if stk == sys.Mapbad
+		-> `std.Fail "couldn't get stack"
+	;;
+	tid = -1
+	/* find top of stack */
+	tos = (stk castto(std.intptr)) + (sz castto(std.intptr))
+
+	/* store the stack size */
+	tos -= sizeof(sys.size)
+	sz -= sizeof(sys.size)
+	szp = tos castto(sys.size#)
+	szp# = Stacksz
+
+	/* store the function we call */
+	tos -= sizeof((->void))
+	sz -= sizeof((->void))
+	fp = tos castto((->void)#)
+	fp# = fn
+
+	ret = sys.thr_new(&[
+		.startfn = startthread castto(void#),
+		.arg = tos castto(void#),
+		.stkbase = stk castto(byte#),
+		.stksz = sz,
+		.tid = &ctid,
+		.ptid = &tid,
+		.flags = 2,
+		.rtp = 0 castto(sys.rtprio#)
+	], sizeof(sys.thrparam))
+
+	if ret < 0
+		-> `std.Fail "couldn't spawn thread"
+	;;
+	-> `std.Ok tid 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
+	;;
+	m = p castto(std.intptr)
+	-> m castto(byte#)
+}
+
+const startthread = {fn : (-> void)#
+	fn#()
+	exit()
+}
+