summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2017-09-09 21:45:56 -0700
committerOri Bernstein <ori@eigenstate.org>2017-09-20 00:13:58 -0700
commit566ae48232e80b003d88d21a8e42f3371367143c (patch)
tree1cd2405fc233cfc6111f4f30947b5043f1d66c62
parented37a0edd2a9c2f992d1f50c38203de7457e2a62 (diff)
downloadmc-566ae48232e80b003d88d21a8e42f3371367143c.tar.gz
Move to custom stack on OSX. System-allocated just doesn't do it for us.
-rw-r--r--lib/thread/spawn+osx.myr60
-rw-r--r--lib/thread/start+osx-x64.s41
2 files changed, 80 insertions, 21 deletions
diff --git a/lib/thread/spawn+osx.myr b/lib/thread/spawn+osx.myr
index bedaa42..4e99598 100644
--- a/lib/thread/spawn+osx.myr
+++ b/lib/thread/spawn+osx.myr
@@ -34,15 +34,41 @@ const spawn = {fn
}
const spawnstk = {fn, sz
- var tid : tid, ret
+ var stk : byte#, tid, ret
+ var szp, f, tos, env, envsz
+ stk = getstk(sz)
+ if stk == sys.Mapbad
+ -> `std.Err "couldn't get stack"
+ ;;
+ tid = -1
+
+ /* find top of stack */
+ tos = (stk : std.intptr) + (sz : std.intptr)
+
+ /* store the stack size */
+ tos -= sizeof(sys.size)
+ sz -= sizeof(sys.size)
+ szp = (tos : sys.size#)
+ szp# = Stacksz
+
+ /* store the function we call */
+ envsz = std.fnenvsz(fn)
+ tos -= (envsz : std.intptr)
+ sz -= (envsz : sys.size)
+ env = tos
+ tos -= sizeof((->void))
+ sz -= sizeof((->void))
+ f = (tos : (->void)#)
+ f# = std.fnbdup(fn, (env : byte#)[:envsz])
+ var repr = (&fn : int64[2]#)#
ret = sys.bsdthread_create( \
- (fn : void#), \
- envptr(&fn), \
- (sz : void#), \
- (0 : void#), \
- 0)
+ (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 == (-1 : void#)
-> `std.Err "couldn't spawn thread"
@@ -50,10 +76,24 @@ const spawnstk = {fn, sz
-> `std.Ok (ret : tid)
}
-const envptr = {fn
- var repr : std.intptr[2]
+const getstk = {sz
+ var p, m
- repr = (fn : std.intptr[2]#)#
- -> (repr[0] : void#)
+ std.put("allocating stack {x}\n", sz)
+ p = sys.mmap((0 : byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon, -1, 0)
+ if p == sys.Mapbad
+ -> p
+ ;;
+ m = (p : std.intptr)
+ -> (m : 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()
+}
diff --git a/lib/thread/start+osx-x64.s b/lib/thread/start+osx-x64.s
index bc62d08..bb497bb 100644
--- a/lib/thread/start+osx-x64.s
+++ b/lib/thread/start+osx-x64.s
@@ -1,22 +1,41 @@
-// The entry point for thread start, registered with bsdthread_register
-// %rdi: pthread (0, for us)
-// %rsi: mach thread port (ignored)
-// %rdx: func
-// %rcx: env
-// %r8: stack
-// %r9: flags (= 0)
-// %rsp: stack - C_64_REDZONE_LEN (= stack - 128)
+# The entry point for thread start, registered with bsdthread_register
+# %rdi: pthread (0, for us)
+# %rsi: mach thread port (ignored)
+# %rdx: func
+# %rcx: env
+# %r8: stack
+# %r9: flags (= 0)
+# %rsp: stack - C_64_REDZONE_LEN (= stack - 128)
.globl _thread$start
_thread$start:
/* call the function */
-# movq %r8, %rsp /* set up stack */
- movq %rcx, %rax /* set up env */
+ movq %r8, %rsp /* set up stack */
+ movq %rcx,%rdi
callq *%rdx /* call function */
+
+/*
+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 $0x2000049,%rax /* munmap */
+ movq -8(%rdi),%rsi /* size */
+ subq %rsi,%rdi /* move to base ptr */
+ syscall
/* exit the thread */
movq $0x2000169, %rax /* Sysbsdthread_terminate */
- movq %rsp, %rdi /* stack */
+ movq $0, %rdi /* stack */
movq $0, %rsi /* len */
movq $0, %rdx /* sem */
syscall
+