diff options
author | Ori Bernstein <ori@eigenstate.org> | 2015-12-14 22:28:31 -0800 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2015-12-14 22:29:20 -0800 |
commit | 85fac5706cb0c63869be6512e1d61731428e3b19 (patch) | |
tree | 9a18e4ee0f49dc267cea491ed108ce1fd5dc0e26 /lib/thread | |
parent | 317eb918900dfe2a9e37fcc5acde58400b143f5a (diff) | |
download | mc-85fac5706cb0c63869be6512e1d61731428e3b19.tar.gz |
Spawn and exit on FreeBSD
Diffstat (limited to 'lib/thread')
-rw-r--r-- | lib/thread/bld.proj | 15 | ||||
-rw-r--r-- | lib/thread/exit+freebsd-x64.s | 23 | ||||
-rw-r--r-- | lib/thread/spawn+freebsd.myr | 74 |
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() +} + |