ref: aa9e46aae152515edaf54c41c33b73eee550fec0
parent: 8e0443da2f98080d20efe818af4184b5ccb2ce73
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Jan 4 18:34:25 EST 2016
Implement freebsd condition variables.
--- a/lib/thread/bld.proj
+++ b/lib/thread/bld.proj
@@ -3,14 +3,15 @@
# linux impl of basic thread primitives
condvar+linux.myr
+ future+linux.myr
mutex+linux.myr
spawn+linux.myr
- future+linux.myr
exit+linux-x64.s
# freebsd impl of thread primitives
- spawn+freebsd.myr
+ condvar+freebsd.myr
mutex+freebsd.myr
+ spawn+freebsd.myr
exit+freebsd-x64.s
atomic-impl+x64.s
--- /dev/null
+++ b/lib/thread/condvar+freebsd.myr
@@ -1,0 +1,59 @@
+use std
+use sys
+
+use "atomic.use"
+use "common.use"
+use "mutex.use"
+
+pkg thread =
+ type cond = struct
+ _mtx : mutex#
+ _seq : uint32
+ ;;
+
+ const mkcond : (mtx : mutex# -> cond)
+ const condwait : (cond : cond# -> void)
+ const condsignal : (cond : cond# -> void)
+ const condbroadcast : (cond : cond# -> void)
+;;
+
+const mkcond = {mtx
+ -> [._mtx = mtx, ._seq = 0]
+}
+
+const condwait = {cond
+ var seq
+ var mtx
+
+ mtx = cond._mtx
+ seq = cond._seq
+
+ mtxunlock(mtx)
+ sys.umtx_op(&cond._seq castto(void#), \
+ sys.Umtxwaituintpriv, \
+ seq castto(uint64), \
+ Zptr, Zptr)
+
+ /*
+ We need to atomically set the mutex to contended. This allows us to
+ pass responsibility for waking up the potential other waiters on to the
+ unlocker of the mutex.
+ */
+ while xchg(&mtx._state, Contended) != Unlocked
+ sys.umtx_op(&mtx._state castto(void#), \
+ sys.Umtxwaituintpriv, \
+ Contended castto(uint64), \
+ Zptr, Zptr)
+ ;;
+}
+
+const condsignal = {cond : cond#
+ xadd(&cond._seq, 1)
+ sys.umtx_op(&cond._seq castto(void#), sys.Umtxwakepriv, 1, Zptr, Zptr)
+}
+
+const condbroadcast = {cond : cond#
+ xadd(&cond._seq, 1)
+ sys.umtx_op(&cond._seq castto(void#), sys.Umtxwakepriv, 0x7ffffff, Zptr, Zptr)
+}
+