shithub: mc

Download patch

ref: 566ae48232e80b003d88d21a8e42f3371367143c
parent: ed37a0edd2a9c2f992d1f50c38203de7457e2a62
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Sep 9 17:45:56 EDT 2017

Move to custom stack on OSX. System-allocated just doesn't do it for us.

--- a/lib/thread/spawn+osx.myr
+++ b/lib/thread/spawn+osx.myr
@@ -34,15 +34,41 @@
 }
 
 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 @@
 	-> `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()
+}
--- 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
 	
+