summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2016-05-09 08:53:59 +1200
committerOri Bernstein <ori@eigenstate.org>2016-05-09 08:55:15 +1200
commitd2a28cc46d5101760733f1b831287f6b9fcf1be1 (patch)
tree7828a69856bca119d4240916c30c7de8695c865b
parentc08505fb46fd8cdfee6b6f425709e5bc536f6a75 (diff)
downloadmc-d2a28cc46d5101760733f1b831287f6b9fcf1be1.tar.gz
Add support for OpenBSD thread spawning.
-rw-r--r--lib/sys/sys+openbsd-x64.myr7
-rw-r--r--lib/sys/syscall+linux-x64.s8
-rw-r--r--lib/sys/syscall+openbsd-x64.s28
-rw-r--r--lib/thread/bld.sub1
-rw-r--r--lib/thread/spawn+linux.myr1
-rw-r--r--lib/thread/spawn+openbsd.myr55
6 files changed, 95 insertions, 5 deletions
diff --git a/lib/sys/sys+openbsd-x64.myr b/lib/sys/sys+openbsd-x64.myr
index a9244e8..bdf7f26 100644
--- a/lib/sys/sys+openbsd-x64.myr
+++ b/lib/sys/sys+openbsd-x64.myr
@@ -61,6 +61,12 @@ pkg sys =
nivcsw : uint64 /* involuntary context switches */
;;
+ type tforkparams = struct
+ tcb : void#
+ tid : pid#
+ stk : byte#
+ ;;
+
type statbuf = struct
mode : filemode
dev : uint32
@@ -472,6 +478,7 @@ pkg sys =
const execve : (cmd : byte[:], args : byte[:][:], env : byte[:][:] -> int64)
/* wrappers to extract wait status */
const waitstatus : (st : int32 -> waitstatus)
+ extern const __tfork_thread : (tfp : tforkparams#, sz : size, fn : void#, arg : void# -> pid)
/* fd manipulation */
const open : (path:byte[:], opts:fdopt -> fd)
diff --git a/lib/sys/syscall+linux-x64.s b/lib/sys/syscall+linux-x64.s
index 53291cb..7dc7843 100644
--- a/lib/sys/syscall+linux-x64.s
+++ b/lib/sys/syscall+linux-x64.s
@@ -33,10 +33,13 @@ sys$fnclone:
movq $56,%rax /* syscall num */
movq %rcx,%r10 /* tls */
syscall
+ cmpq $0,%rax
+ jb .doneparent
+
/* fn() */
testl %eax,%eax
- jnz parent
+ jnz .doneparent
call *%r15
/* exit(0) */
@@ -44,6 +47,7 @@ sys$fnclone:
movq $0, %rdi /* arg: 0 */
syscall
-parent:
+.doneparent:
popq %r15
ret
+
diff --git a/lib/sys/syscall+openbsd-x64.s b/lib/sys/syscall+openbsd-x64.s
index 827f25c..ea4a9b7 100644
--- a/lib/sys/syscall+openbsd-x64.s
+++ b/lib/sys/syscall+openbsd-x64.s
@@ -22,3 +22,31 @@ sys$syscall:
.success:
ret
+
+/* __tfork_thread(tfp : tforkparams#, sz : size, fn : void#, arg : void#-> tid) */
+.globl sys$__tfork_thread
+sys$__tfork_thread:
+ /* syscall */
+ movq %rdx, %r8
+ movq %rcx, %r9
+ movq $8, %rax
+ syscall
+ jb .failparent
+
+ /* are we in the parent? */
+ cmpq $0,%rax
+ jnz .doneparent
+
+ /* call the function and __threxit */
+ movq %r9, %rdi
+ callq *%r8
+
+ movq $302,%rax
+ xorq %rdi,%rdi
+ syscall
+
+.failparent:
+ negq %rax
+
+.doneparent:
+ ret
diff --git a/lib/thread/bld.sub b/lib/thread/bld.sub
index 3d0ce27..35cc5a6 100644
--- a/lib/thread/bld.sub
+++ b/lib/thread/bld.sub
@@ -27,6 +27,7 @@ lib thread =
# openbsd impl of thread primitives
spawn+openbsd.myr
+ exit+openbsd-x64.s
atomic-impl+x64.s
diff --git a/lib/thread/spawn+linux.myr b/lib/thread/spawn+linux.myr
index 21ab654..a144374 100644
--- a/lib/thread/spawn+linux.myr
+++ b/lib/thread/spawn+linux.myr
@@ -42,7 +42,6 @@ const spawnstk = {fn, sz
&ctid, 0 castto(byte#), \
startthread castto(void#)) castto(tid)
if ret < 0
- std.put("errno={}\n", -ret)
-> `std.Fail "couldn't spawn thread"
;;
-> `std.Ok ret
diff --git a/lib/thread/spawn+openbsd.myr b/lib/thread/spawn+openbsd.myr
index 92cca94..d330b56 100644
--- a/lib/thread/spawn+openbsd.myr
+++ b/lib/thread/spawn+openbsd.myr
@@ -1,4 +1,5 @@
use std
+use sys
pkg thread =
type tid = uint64
@@ -6,7 +7,57 @@ pkg thread =
const spawn : (fn : (-> void) -> std.result(tid, byte[:]))
;;
+const Stacksz = 8*std.MiB
+extern const exit : (-> void)
+
const spawn = {fn;
- std.die("threads not supported yet on openbsd\n")
- -> `std.Fail "not supported"
+ -> spawnstk(fn, Stacksz)
+}
+
+const spawnstk = {fn, sz
+ var stk, szp, fp, tos, tfp
+ var ret
+
+ stk = getstk(sz)
+ if stk == sys.Mapbad
+ -> `std.Fail "couldn't get stack"
+ ;;
+ /* store size */
+ tos = stk castto(std.intptr)
+ tos -= sizeof(int64)
+ szp = tos castto(sys.size#)
+ szp# = Stacksz
+
+ /* store func */
+ tos -= sizeof((->void))
+ fp = tos castto((->void)#)
+ fp# = fn
+
+ tfp = [
+ .tcb = 0 castto(void#),
+ .tid = &ret,
+ .stk = tos castto(byte#),
+ ]
+ if sys.__tfork_thread(&tfp, sizeof(sys.tforkparams), startthread castto(void#), 0 castto(void#)) < 0
+ -> `std.Fail "couldn't spawn thread"
+ ;;
+ -> `std.Ok (ret castto(tid))
+}
+
+const getstk = {sz
+ var p, m
+
+ p = sys.mmap(0 castto(byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon, -1, 0)
+ if p == sys.Mapbad
+ -> p
+ ;;
+ /* stack starts at the top of memory and grows down. */
+ m = p castto(std.intptr)
+ m += sz castto(std.intptr)
+ -> m castto(byte#)
+}
+
+const startthread = {fn : (-> void)
+ fn()
+ exit()
}