shithub: mc

Download patch

ref: d2a28cc46d5101760733f1b831287f6b9fcf1be1
parent: c08505fb46fd8cdfee6b6f425709e5bc536f6a75
author: Ori Bernstein <[email protected]>
date: Mon May 9 04:53:59 EDT 2016

Add support for OpenBSD thread spawning.

--- a/lib/sys/sys+openbsd-x64.myr
+++ b/lib/sys/sys+openbsd-x64.myr
@@ -61,6 +61,12 @@
 		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 @@
 	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)
--- a/lib/sys/syscall+linux-x64.s
+++ b/lib/sys/syscall+linux-x64.s
@@ -33,10 +33,13 @@
 	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 @@
 	movq $0, %rdi   /* arg: 0 */
 	syscall
 
-parent:
+.doneparent:
 	popq %r15
 	ret
+
--- a/lib/sys/syscall+openbsd-x64.s
+++ b/lib/sys/syscall+openbsd-x64.s
@@ -22,3 +22,31 @@
 
 .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
--- a/lib/thread/bld.sub
+++ b/lib/thread/bld.sub
@@ -27,6 +27,7 @@
 
 	# openbsd impl of thread primitives
 	spawn+openbsd.myr
+	exit+openbsd-x64.s
 
 
 	atomic-impl+x64.s
--- a/lib/thread/spawn+linux.myr
+++ b/lib/thread/spawn+linux.myr
@@ -42,7 +42,6 @@
 		&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
--- 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 @@
 	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()
 }