summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-12-14 22:28:31 -0800
committerOri Bernstein <ori@eigenstate.org>2015-12-14 22:29:20 -0800
commit85fac5706cb0c63869be6512e1d61731428e3b19 (patch)
tree9a18e4ee0f49dc267cea491ed108ce1fd5dc0e26
parent317eb918900dfe2a9e37fcc5acde58400b143f5a (diff)
downloadmc-85fac5706cb0c63869be6512e1d61731428e3b19.tar.gz
Spawn and exit on FreeBSD
-rw-r--r--lib/thread/bld.proj15
-rw-r--r--lib/thread/exit+freebsd-x64.s23
-rw-r--r--lib/thread/spawn+freebsd.myr74
3 files changed, 112 insertions, 0 deletions
diff --git a/lib/thread/bld.proj b/lib/thread/bld.proj
index 61fd68f..b94628e 100644
--- a/lib/thread/bld.proj
+++ b/lib/thread/bld.proj
@@ -8,7 +8,22 @@ lib thread =
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
+;;
diff --git a/lib/thread/exit+freebsd-x64.s b/lib/thread/exit+freebsd-x64.s
new file mode 100644
index 0000000..d8952b6
--- /dev/null
+++ b/lib/thread/exit+freebsd-x64.s
@@ -0,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
+
diff --git a/lib/thread/spawn+freebsd.myr b/lib/thread/spawn+freebsd.myr
new file mode 100644
index 0000000..63d97fe
--- /dev/null
+++ b/lib/thread/spawn+freebsd.myr
@@ -0,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()
+}
+