ref: f6eb57283f625cbd20d5bb423331e88ddc82c8f1
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)} ;;