shithub: mc

Download patch

ref: fe9e325f966ff11bb7311e51330ff812362cb41a
parent: b92c74cab80c4c1fa912d76422d5c83fcad308de
author: Ori Bernstein <ori@eigenstate.org>
date: Fri Nov 27 19:44:14 EST 2015

Correctly handle spawning and exiting threads.

	We now unmap the stack correctly on exit. We still
	have no good thread.exit() all.

--- a/lib/thread/bld.proj
+++ b/lib/thread/bld.proj
@@ -6,6 +6,7 @@
 	mutex+linux.myr
 	spawn+linux.myr
 	future+linux.myr
+	exit+linux-x64.s
 
 	atomic-impl+x64.s
 	atomic.myr
--- /dev/null
+++ b/lib/thread/exit+linux-x64.s
@@ -1,0 +1,22 @@
+/*
+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
+
+	/* syscall args */
+	movq	$11,%rax	/* munmap */
+	movq	-8(%rdi),%rsi	/* size */
+	subq	%rsi,%rdi	/* move to base ptr */
+	syscall
+
+	movq	$60,%rax	/* exit */
+	xorq	%rdi,%rdi	/* 0 */
+	syscall
+	
--- a/lib/thread/spawn+linux.myr
+++ b/lib/thread/spawn+linux.myr
@@ -7,6 +7,8 @@
 	const spawn : (fn : (-> void) -> std.result(tid, byte[:]))
 ;;
 
+extern const exit : (-> void)
+
 /* Holy shit flag mania. */
 const Thrflag = sys.Clonevm | sys.Clonefs | sys.Clonefiles  | \
 	sys.Clonesighand | sys.Clonethread |sys.Clonesysvsem | \
@@ -19,14 +21,26 @@
 }
 
 const spawnstk = {fn, sz
-	var stk, tid, ctid, ret
+	var stk : byte#, tid, ctid, ret
+	var szp, fp, tos
 
 	stk = getstk(sz)
 	if stk == sys.Mapbad
 		-> `std.Fail "couldn't get stack"
 	;;
+	tos = stk castto(std.intptr)
+	tos -= sizeof(int64)
+	szp = tos castto(sys.size#)
+	szp# = Stacksz
+	tos -= sizeof((->void))
+	fp = tos castto((->void)#)
+	fp# = fn
 
-	ret = sys.fnclone(Thrflag, stk, &tid, 0 castto(byte#), &ctid, 0 castto(byte#), fn) castto(tid)
+	ret = sys.fnclone(Thrflag, \
+		tos castto(byte#),\
+		&tid, 0 castto(byte#), \
+		&ctid, 0 castto(byte#), \
+		startthread castto(void#)) castto(tid)
 	if ret < 0
 		std.put("errno={}\n", -ret)
 		-> `std.Fail "couldn't spawn thread"
@@ -46,3 +60,9 @@
 	m += sz castto(std.intptr)
 	-> m castto(byte#)
 }
+
+const startthread = {fn : (-> void)
+	fn()
+	exit()
+}
+
--- a/lib/thread/test/future.myr
+++ b/lib/thread/test/future.myr
@@ -22,7 +22,6 @@
 	thread.futset(&fut, 666)
 	std.assert(thread.futset(&fut, 1) == false, "double set future\n")
 	while ndone != 100
-		std.put("ndone: {}\n", ndone)
 		/* spin */
 	;;
 	std.put("double set future ok")
--- /dev/null
+++ b/lib/thread/test/spawn.myr
@@ -1,0 +1,24 @@
+use std
+use thread
+
+var done : int32
+
+const main = {
+	var capture, ptr
+
+	capture = 666
+	ptr = &capture
+	thread.spawn({
+		std.assert(capture==666, "wrong captured value\n")
+		std.assert(ptr#==666, "wrong captured ptr value\n")
+		ptr# = 333
+		thread.xadd(&done, 1)
+	})
+
+	while done == 0
+		/* nothing */
+	;;
+
+	std.assert(capture == 333, "capture wasn't written to correctly\n")
+}
+