summaryrefslogtreecommitdiff
path: root/lib/thread
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-09-16 23:17:31 -0700
committerOri Bernstein <ori@eigenstate.org>2015-09-16 23:17:31 -0700
commitab327dfacd49c61feb0311e064c79bee7e8aec27 (patch)
tree041416314a8773e82b24de62e82766e8a79e6b33 /lib/thread
parent1753ea7ecead5f56f50b13dfc85118f9a0d54f56 (diff)
downloadmc-ab327dfacd49c61feb0311e064c79bee7e8aec27.tar.gz
Add first crack at condvars.
Diffstat (limited to 'lib/thread')
-rw-r--r--lib/thread/bld.proj5
-rw-r--r--lib/thread/condvar+linux.myr67
2 files changed, 72 insertions, 0 deletions
diff --git a/lib/thread/bld.proj b/lib/thread/bld.proj
index 2b770c8..3e9e3b1 100644
--- 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
;;
diff --git a/lib/thread/condvar+linux.myr b/lib/thread/condvar+linux.myr
new file mode 100644
index 0000000..072e450
--- /dev/null
+++ b/lib/thread/condvar+linux.myr
@@ -0,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#)
+}
+