ref: a68e92f1e80f262e04d6e6c1d27af80199afbdc0
dir: /lib/thread/futex+freebsd.myr/
use std
use sys
use "atomic"
use "common"
pkg thread =
type ftxtag = uint32
impl atomic ftxtag
const ftxwait : (uaddr : ftxtag#, val : ftxtag, tmout : std.time -> sys.errno)
const ftxwake : (uaddr : ftxtag# -> void)
const ftxwakeall : (uaddr : ftxtag# -> void)
;;
const ftxwait = {uaddr, val, tmout
var ut : sys.umtx_time, utp, utsize, rc
if tmout < 0
utp = Zptr
utsize = Zptr
else
var t = (tmout : int64)
std.assert(sys.clock_gettime(`sys.Clockmonotonic, &ut.timeout) == 0,
"error: clock_gettime returned -1\n")
ut.timeout.nsec += (t % 1_000_000) * 1000
ut.timeout.sec += (ut.timeout.nsec / 1_000_000_000) + (t / 1_000_000)
ut.timeout.nsec %= 1_000_000_000
ut.flags = (sys.Umtxabstime : uint32)
ut.clockid = (sys.clockid(`sys.Clockmonotonic) : uint32)
utp = (&ut : void#)
utsize = (sizeof(sys.umtx_time) : void#)
;;
while (rc = (sys.umtx_op((uaddr : void#),
sys.Umtxwaituintpriv,
(val : uint64),
utsize,
utp) : sys.errno)) == sys.Eintr
;;
match rc
| 0: -> 0
| sys.Eagain: -> sys.Eagain
| sys.Etimedout: -> sys.Etimedout
| err:
std.fput(2, "error: umtx_op returned {}\n", err)
std.suicide()
;;
}
const ftxwake = {uaddr
sys.umtx_op((uaddr : void#), sys.Umtxwakepriv, 1, Zptr, Zptr)
}
const ftxwakeall = {uaddr
sys.umtx_op((uaddr : void#), sys.Umtxwakepriv, 0x7fffffff, Zptr, Zptr)
}
impl atomic ftxtag =
xget = {p; -> (xget32((p : uint32#)) : ftxtag)}
xset = {p, v; xset32((p : uint32#), (v : uint32))}
xadd = {p, v; -> (xadd32((p : uint32#), (v : uint32)) : ftxtag)}
xcas = {p, old, new; -> (xcas32((p : uint32#), (old : uint32), (new : uint32)) : ftxtag)}
xchg = {p, v; -> (xchg32((p : uint32#), (v : uint32)) : ftxtag)}
;;