shithub: mc

Download patch

ref: ab327dfacd49c61feb0311e064c79bee7e8aec27
parent: 1753ea7ecead5f56f50b13dfc85118f9a0d54f56
author: Ori Bernstein <ori@eigenstate.org>
date: Wed Sep 16 19:17:31 EDT 2015

Add first crack at condvars.

--- a/lib/thread/bld.proj
+++ b/lib/thread/bld.proj
@@ -1,6 +1,11 @@
 lib thread =
+	future.myr
+
+	# linux impl of basic thread primitives
+	condvar+linux.myr
 	mutex+linux.myr
 	spawn+linux.myr
+
 	atomic-impl+x64.s
 	atomic.myr
 ;;
--- /dev/null
+++ b/lib/thread/condvar+linux.myr
@@ -1,0 +1,67 @@
+use std
+use sys
+
+use "atomic.use"
+use "mutex.use"
+
+pkg thread =
+	type cond = struct
+		_mtx	: mutex#
+		_seq	: int32
+	;;
+
+	const mkcond	: (-> cond)
+	const condwait	: (cond : cond#, mtx : mutex# -> void)
+	const condsignal	: (cond : cond# -> void)
+	const condbroadcast	: (cond : cond# -> void)
+;;
+
+generic Zptr = 0 castto(@a#)
+const Zmtx = 0 castto(mutex#)
+
+const mkcond = {
+	-> [._mtx = Zmtx, ._seq = 0]
+}
+
+const condwait = {cond, mtx
+	var seq
+
+	seq = cond._seq
+	if cond._mtx != mtx
+		if cond._mtx != Zmtx
+			std.die("multiple mutexes used with cond var")
+		;;
+		mtxcas(&cond._mtx, Zmtx, mtx)
+		if cond._mtx != Zmtx
+			std.die("multiple mutexes used with cond var")
+		;;
+	;;
+	mtxunlock(cond._mtx)
+	sys.futex(&cond._seq, sys.Futexwait | sys.Futexpriv, seq, Zptr, Zptr, 0)
+
+	while xchg(&mtx._state, Contended) != Unlocked
+		sys.futex(&mtx._state, sys.Futexwait | sys.Futexpriv, Contended, Zptr, Zptr, 0)
+	;;
+}
+
+const condsig = {cond : cond#
+	xadd(&cond._seq, 1)
+	sys.futex(&cond._seq, sys.Futexwake | sys.Futexpriv, 1, Zptr, Zptr, 0)
+}
+
+const condbroadcast = {cond : cond#
+	var m
+
+	m = cond._mtx
+	if m != Zmtx
+		xadd(&cond._seq, 1)
+		sys.futex(&cond._seq, sys.Futexrequeue | sys.Futexpriv, 1, Zptr, &m._state, 0)
+	;;
+}
+
+const mtxcas = {mtxp, old, new
+	-> xcas(mtxp castto(std.intptr#), \
+		old castto(std.intptr), \
+		new castto(std.intptr)) castto(mutex#)
+}
+