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