ref: 63f4ce6387dea9f943ecc9c9f9b7af147560839d
dir: /lib/thread/condvar+linux.myr/
use std
use sys
use "atomic"
use "common"
use "futex"
use "mutex"
pkg thread =
type cond = struct
_mtx : mutex#
_seq : ftxtag
;;
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 mtx = cond._mtx
var seq = xget(&cond._seq)
mtxunlock(mtx)
ftxwait(&cond._seq, seq, -1)
/*
In the event of a broadcast, we need to atomically set the mutex to
contended. This allows us to pass responsibility for waking up the
potential other waiters from the requeue operation on to the unlocker
of the mutex.
*/
mtxcontended(mtx)
}
const condsignal = {cond : cond#
xadd(&cond._seq, 1)
ftxwake(&cond._seq)
}
const condbroadcast = {cond : cond#
xadd(&cond._seq, 1)
/*
The futex docs seem to be broken -- the timeout parameter seems to be
used for the number of threads to move, and is not ignored when
requeueing
*/
sys.futex((&cond._seq : int32#), sys.Futexrequeue | sys.Futexpriv,
1, (0x7fffffff : sys.timespec#),
(&cond._mtx._state : int32#), 0)
}