ref: 3d4d7c4ca9eb30d468d71c26f4b4588c800c9d1c
dir: /lib/thread/futex+osx.myr/
use std use sys use "atomic" use "common" pkg thread = type ftxtag = uint64 impl atomic ftxtag const ftxwait : (uaddr : ftxtag#, val : ftxtag, timeout : sys.timespec# -> int) const ftxwake : (uaddr : ftxtag# -> int) const ftxwakeall : (uaddr : ftxtag# -> int) ;; /* * The ulock_ functions are undocumented but the relevant source can be found at * https://github.com/apple/darwin-xnu/blob/0a798f6738bc1db01281fc08ae024145e84df927/bsd/kern/sys_ulock.c */ const ftxwait = {uaddr, val, timeout if timeout == Zptr -> sys.ulock_wait(sys.Ulockcompareandwait, (uaddr : uint64#), (val : uint64), 0) ;; var ts var err = sys.clock_gettime(`sys.Clockmonotonic, &ts) std.assert(err == 0, "error: clock_gettime returned {}\n", err) if timeout.sec < ts.sec -> (std.Etimedout : int) ;; var usec = 0 var sec = (timeout.sec - ts.sec) * 1000 std.assert(sec <= 0xffffffff, "error: maximum futex timeout exceeded\n") usec = (sec : uint32) if timeout.nsec > ts.nsec var nsec = (timeout.nsec - ts.nsec) / 1000 std.assert(usec + nsec > usec, "error: maximum futex timeout exceeded\n") usec += nsec ;; if usec == 0 -> (std.Etimedout : int) ;; -> sys.ulock_wait(sys.Ulockcompareandwait, (uaddr : uint64#), (val : uint64), usec) } const ftxwake = {uaddr -> sys.ulock_wake(sys.Ulockcompareandwait, (uaddr : uint64#), 0) } const ftxwakeall = {uaddr -> sys.ulock_wake(sys.Ulockcompareandwait | sys.Ulockulfwakeall, (uaddr : uint64#), 0) } impl atomic ftxtag = xget = {p; -> (xget64((p : uint64#)) : ftxtag)} xset = {p, v; xset64((p : uint64#), (v : uint64))} xadd = {p, v; -> (xadd64((p : uint64#), (v : uint64)) : ftxtag)} xcas = {p, old, new; -> (xcas64((p : uint64#), (old : uint64), (new : uint64)) : ftxtag)} xchg = {p, v; -> (xchg64((p : uint64#), (v : uint64)) : ftxtag)} ;;