ref: 09e7cfb56388b1ea79ee7e100e52cb5b34e6017c
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)
;;
/*
* 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)
}
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)}
;;