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")
+}
+