diff options
author | Ori Bernstein <ori@eigenstate.org> | 2015-11-28 00:44:14 -0800 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2015-11-28 00:44:14 -0800 |
commit | fe9e325f966ff11bb7311e51330ff812362cb41a (patch) | |
tree | fe3f125967b7c8ea32450233838e8203f0a5a137 /lib/thread | |
parent | b92c74cab80c4c1fa912d76422d5c83fcad308de (diff) | |
download | mc-fe9e325f966ff11bb7311e51330ff812362cb41a.tar.gz |
Correctly handle spawning and exiting threads.
We now unmap the stack correctly on exit. We still
have no good thread.exit() all.
Diffstat (limited to 'lib/thread')
-rw-r--r-- | lib/thread/bld.proj | 1 | ||||
-rw-r--r-- | lib/thread/exit+linux-x64.s | 22 | ||||
-rw-r--r-- | lib/thread/spawn+linux.myr | 24 | ||||
-rw-r--r-- | lib/thread/test/future.myr | 1 | ||||
-rw-r--r-- | lib/thread/test/spawn.myr | 24 |
5 files changed, 69 insertions, 3 deletions
diff --git a/lib/thread/bld.proj b/lib/thread/bld.proj index 2fd110b..61fd68f 100644 --- a/lib/thread/bld.proj +++ b/lib/thread/bld.proj @@ -6,6 +6,7 @@ lib thread = mutex+linux.myr spawn+linux.myr future+linux.myr + exit+linux-x64.s atomic-impl+x64.s atomic.myr diff --git a/lib/thread/exit+linux-x64.s b/lib/thread/exit+linux-x64.s new file mode 100644 index 0000000..38e4fa3 --- /dev/null +++ b/lib/thread/exit+linux-x64.s @@ -0,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 + diff --git a/lib/thread/spawn+linux.myr b/lib/thread/spawn+linux.myr index 680f899..21ab654 100644 --- a/lib/thread/spawn+linux.myr +++ b/lib/thread/spawn+linux.myr @@ -7,6 +7,8 @@ pkg thread = 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 spawn = {fn } 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 @@ const getstk = {sz m += sz castto(std.intptr) -> m castto(byte#) } + +const startthread = {fn : (-> void) + fn() + exit() +} + diff --git a/lib/thread/test/future.myr b/lib/thread/test/future.myr index 76710c7..63969a4 100644 --- a/lib/thread/test/future.myr +++ b/lib/thread/test/future.myr @@ -22,7 +22,6 @@ const main = { 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") diff --git a/lib/thread/test/spawn.myr b/lib/thread/test/spawn.myr new file mode 100644 index 0000000..6032ff0 --- /dev/null +++ b/lib/thread/test/spawn.myr @@ -0,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") +} + |