summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/sys/sys+freebsd-x64.myr9
-rw-r--r--lib/sys/sys+linux-x64.myr6
-rw-r--r--lib/thread/condvar+freebsd.myr15
-rw-r--r--lib/thread/condvar+linux.myr27
-rw-r--r--lib/thread/condvar+openbsd:6.2.myr27
-rw-r--r--lib/thread/condvar+osx.myr15
-rw-r--r--lib/thread/condvar.myr36
-rw-r--r--lib/thread/futex+freebsd.myr56
-rw-r--r--lib/thread/futex+linux.myr59
-rw-r--r--lib/thread/futex+openbsd:6.2.myr72
-rw-r--r--lib/thread/futex+osx.myr75
-rw-r--r--lib/thread/mutex+futex.myr11
-rw-r--r--lib/thread/mutex+plan9.myr2
-rw-r--r--lib/thread/mutex.myr2
-rw-r--r--lib/thread/sem+futex.myr3
-rw-r--r--lib/thread/sem+plan9.myr1
-rw-r--r--lib/thread/waitgrp+futex.myr3
-rw-r--r--support/syscall-gen/specials+freebsd-x64.frag1
-rw-r--r--support/syscall-gen/specials+linux-x64.frag4
-rw-r--r--support/syscall-gen/types+freebsd-x64.frag7
-rw-r--r--support/syscall-gen/types+linux-x64.frag2
21 files changed, 274 insertions, 159 deletions
diff --git a/lib/sys/sys+freebsd-x64.myr b/lib/sys/sys+freebsd-x64.myr
index e1cfb69..b89e99b 100644
--- a/lib/sys/sys+freebsd-x64.myr
+++ b/lib/sys/sys+freebsd-x64.myr
@@ -582,10 +582,10 @@ pkg sys =
;;
const Umtxabstime = 1
- type _umtx_time = struct
- _timeout : timespec
- _flags : uint32
- _clockid : uint32
+ type umtx_time = struct
+ timeout : timespec
+ flags : uint32
+ clockid : uint32
;;
/* open options */
@@ -1192,6 +1192,7 @@ pkg sys =
const getsockopt : (sock : fd, lev : sockproto, opt : sockopt, val : void#, len : size# -> int)
const munmap : (addr:byte#, len:size -> int64)
const mmap : (addr:byte#, len:size, prot:mprot, flags:mopt, fd:fd, off:off -> byte#)
+ const clockid : (clk : clock -> uint64)
const clock_getres : (clk : clock, ts : timespec# -> int32)
const clock_gettime : (clk : clock, ts : timespec# -> int32)
const clock_settime : (clk : clock, ts : timespec# -> int32)
diff --git a/lib/sys/sys+linux-x64.myr b/lib/sys/sys+linux-x64.myr
index 1cebb12..61bb8b2 100644
--- a/lib/sys/sys+linux-x64.myr
+++ b/lib/sys/sys+linux-x64.myr
@@ -563,6 +563,8 @@ pkg sys =
const Futexpriv : futexop = 128
const Futexclockrt : futexop = 256
+ const Futexbitsetmatchany : int32 = -1
+
/* poll events : posix */
const Pollin : pollevt = 0x001 /* There is data to read. */
const Pollpri : pollevt = 0x002 /* There is urgent data to read. */
@@ -1273,7 +1275,7 @@ pkg sys =
const dup : (fd : fd -> fd)
const dup2 : (src : fd, dst : fd -> fd)
const futex : (uaddr : int32#, op : futexop, val : int32, \
- timeout : timespec#, uaddr2 : int32#, val3 : int32 -> int64)
+ timeout : timespec#, uaddr2 : int32#, val3 : int32 -> int)
const semctl : (semid : int, semnum : int, cmd : int, arg : void# -> int)
const epollcreate : (flg : epollflags -> fd) /* actually epoll_create1 */
const epollctl : (epfd : fd, op : int, fd : fd, evt : epollevt# -> int)
@@ -1692,7 +1694,7 @@ pkg sys =
/* threading */
const futex = {uaddr, op, val, timeout, uaddr2, val3
- -> syscall(Sysfutex, a(uaddr), a(op), a(val), a(timeout), a(uaddr2), a(val3))
+ -> (syscall(Sysfutex, a(uaddr), a(op), a(val), a(timeout), a(uaddr2), a(val3)) : int)
}
const semctl = {semid, semnum, cmd, arg
-> (syscall(Syssemctl, a(semnum), a(cmd), a(arg)) : int)
diff --git a/lib/thread/condvar+freebsd.myr b/lib/thread/condvar+freebsd.myr
index 002757a..7b2e77c 100644
--- a/lib/thread/condvar+freebsd.myr
+++ b/lib/thread/condvar+freebsd.myr
@@ -1,7 +1,6 @@
use std
use "atomic"
-use "common"
use "mutex"
use "futex"
@@ -22,19 +21,17 @@ const mkcond = {mtx
}
const condwait = {cond
- var seq
- var mtx
+ var mtx = cond._mtx
+ var seq = xget(&cond._seq)
- mtx = cond._mtx
- seq = cond._seq
mtxunlock(mtx)
+ ftxwait(&cond._seq, seq, -1)
/*
- FIXME?: `ftxwait` can be interrupted but `condwait` should always be
- done in a loop anyway.
+ In the event of a broadcast, we aren't requeueing waiters from the
+ condvar's futex to the mutex's futex so we can just reacquire the mutex
+ normally.
*/
- ftxwait(&cond._seq, seq, Zptr)
-
mtxlock(mtx)
}
diff --git a/lib/thread/condvar+linux.myr b/lib/thread/condvar+linux.myr
index e1a9e10..8d3f417 100644
--- a/lib/thread/condvar+linux.myr
+++ b/lib/thread/condvar+linux.myr
@@ -3,12 +3,13 @@ use sys
use "atomic"
use "common"
+use "futex"
use "mutex"
pkg thread =
type cond = struct
_mtx : mutex#
- _seq : int32
+ _seq : ftxtag
;;
const mkcond : (mtx : mutex# -> cond)
@@ -22,30 +23,24 @@ const mkcond = {mtx
}
const condwait = {cond
- var seq
- var mtx
+ var mtx = cond._mtx
+ var seq = xget(&cond._seq)
- mtx = cond._mtx
- seq = cond._seq
mtxunlock(mtx)
+ ftxwait(&cond._seq, seq, -1)
/*
- FIXME?: `futex` can be interrupted but `condwait` should always be done
- in a loop anyway.
- */
- sys.futex(&cond._seq, sys.Futexwait | sys.Futexpriv, seq, Zptr, Zptr, 0)
-
- /*
- We need to atomically set the mutex to contended. This allows us to
- pass responsibility for waking up the potential other waiters on to the
- unlocker of the mutex.
+ 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)
- sys.futex(&cond._seq, sys.Futexwake | sys.Futexpriv, 1, Zptr, Zptr, 0)
+ ftxwake(&cond._seq)
}
const condbroadcast = {cond : cond#
@@ -55,7 +50,7 @@ const condbroadcast = {cond : cond#
used for the number of threads to move, and is not ignored when
requeueing
*/
- sys.futex(&cond._seq, sys.Futexrequeue | sys.Futexpriv,
+ sys.futex((&cond._seq : int32#), sys.Futexrequeue | sys.Futexpriv,
1, (0x7fffffff : sys.timespec#),
(&cond._mtx._state : int32#), 0)
}
diff --git a/lib/thread/condvar+openbsd:6.2.myr b/lib/thread/condvar+openbsd:6.2.myr
index 29dbb35..345a3b1 100644
--- a/lib/thread/condvar+openbsd:6.2.myr
+++ b/lib/thread/condvar+openbsd:6.2.myr
@@ -3,12 +3,13 @@ use sys
use "atomic"
use "common"
+use "futex"
use "mutex"
pkg thread =
type cond = struct
_mtx : mutex#
- _seq : uint32
+ _seq : ftxtag
;;
const mkcond : (mtx : mutex# -> cond)
@@ -22,35 +23,29 @@ const mkcond = {mtx
}
const condwait = {cond
- var seq : uint32
- var mtx
+ var mtx = cond._mtx
+ var seq = xget(&cond._seq)
- mtx = cond._mtx
- seq = cond._seq
mtxunlock(mtx)
+ ftxwait(&cond._seq, seq, -1)
/*
- FIXME?: `futex` can be interrupted but `condwait` should always be done
- in a loop anyway.
- */
- sys.futex(&cond._seq, sys.Futexwait, (seq : int), Zptr, Zptr)
-
- /*
- We need to atomically set the mutex to contended. This allows us to
- pass responsibility for waking up the potential other waiters on to the
- unlocker of the mutex.
+ 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)
- sys.futex(&cond._seq, sys.Futexwake, 1, Zptr, Zptr)
+ ftxwake(&cond._seq)
}
const condbroadcast = {cond : cond#
xadd(&cond._seq, 1)
- sys.futex(&cond._seq, sys.Futexrequeue, 1,
+ sys.futex((&cond._seq : uint32#), sys.Futexrequeue, 1,
(0x7fffffff : sys.timespec#),
(&cond._mtx._state : uint32#))
}
diff --git a/lib/thread/condvar+osx.myr b/lib/thread/condvar+osx.myr
index d74c321..0f1b1ff 100644
--- a/lib/thread/condvar+osx.myr
+++ b/lib/thread/condvar+osx.myr
@@ -1,7 +1,6 @@
use std
use "atomic"
-use "common"
use "mutex"
use "futex"
@@ -22,19 +21,17 @@ const mkcond = {mtx
}
const condwait = {cond
- var seq
- var mtx
+ var mtx = cond._mtx
+ var seq = xget(&cond._seq)
- mtx = cond._mtx
- seq = cond._seq
mtxunlock(mtx)
+ ftxwait(&cond._seq, seq, -1)
/*
- FIXME?: `ftxwait` can be interrupted but `condwait` should always be
- done in a loop anyway.
+ In the event of a broadcast, we aren't requeueing waiters from the
+ condvar's futex to the mutex's futex so we can just reacquire the mutex
+ normally.
*/
- ftxwait(&cond._seq, seq, Zptr)
-
mtxlock(mtx)
}
diff --git a/lib/thread/condvar.myr b/lib/thread/condvar.myr
index 4fde707..f843f84 100644
--- a/lib/thread/condvar.myr
+++ b/lib/thread/condvar.myr
@@ -8,7 +8,8 @@ use "sem"
pkg thread =
type cond = struct
_mtx : mutex#
- _waitq : condwaiter#
+ _head : condwaiter#
+ _tail : condwaiter#
_lock : mutex
;;
@@ -18,15 +19,8 @@ pkg thread =
const condbroadcast : (cond : cond# -> void)
;;
-/*
-The waitqueue is a doubly-linked list because we'll need to remove waiters from
-anywhere in the list when we add timeout support.
-
-`cond._waitq.prev` is the tail of the queue.
-*/
type condwaiter = struct
next : condwaiter#
- prev : condwaiter#
sem : sem
;;
@@ -40,14 +34,9 @@ const condwait = {cond
var waiter = std.mk([.sem = mksem(0)])
mtxlock(lock)
- match cond._waitq
- | Zptr:
- waiter.prev = waiter
- cond._waitq = waiter
- | q:
- waiter.prev = q.prev
- waiter.prev.next = waiter
- q.prev = waiter
+ match cond._tail
+ | Zptr: cond._head = cond._tail = waiter
+ | tail: cond._tail = tail.next = waiter
;;
mtxunlock(lock)
@@ -61,13 +50,13 @@ const condsignal = {cond
var lock = &cond._lock
mtxlock(lock)
- var head = cond._waitq
+ var head = cond._head
if head != Zptr
- if head.next != Zptr
- head.next.prev = head.prev
- ;;
- cond._waitq = head.next
+ cond._head = head.next
sempost(&head.sem)
+ if cond._head == Zptr
+ cond._tail = Zptr
+ ;;
;;
mtxunlock(lock)
}
@@ -81,9 +70,10 @@ const condbroadcast = {cond
var head = Zptr
mtxlock(lock)
- while (head = cond._waitq) != Zptr
- cond._waitq = head.next
+ while (head = cond._head) != Zptr
+ cond._head = head.next
sempost(&head.sem)
;;
+ cond._tail = Zptr
mtxunlock(lock)
}
diff --git a/lib/thread/futex+freebsd.myr b/lib/thread/futex+freebsd.myr
index ea5f28d..c011bf9 100644
--- a/lib/thread/futex+freebsd.myr
+++ b/lib/thread/futex+freebsd.myr
@@ -1,3 +1,4 @@
+use std
use sys
use "atomic"
@@ -7,34 +8,53 @@ pkg thread =
type ftxtag = uint32
impl atomic ftxtag
- const ftxwait : (uaddr : ftxtag#, val : ftxtag, timeout : sys.timespec# -> int)
- const ftxwake : (uaddr : ftxtag# -> int)
- const ftxwakeall : (uaddr : ftxtag# -> int)
+ 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, timeout
- if timeout == Zptr
- -> sys.umtx_op((uaddr : void#), sys.Umtxwaituintpriv, (val : uint64), Zptr, Zptr)
+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
;;
- var ut : sys._umtx_time = [
- ._timeout = timeout#,
- ._flags = (sys.Umtxabstime : uint32),
- ._clockid = 1, /* CLOCK_MONOTONIC. Not exported from sys. */
- ]
- -> sys.umtx_op((uaddr : void#),
- sys.Umtxwaituintpriv,
- (val : uint64),
- (sizeof(sys._umtx_time) : void#),
- (&ut : void#))
+ 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)
+ sys.umtx_op((uaddr : void#), sys.Umtxwakepriv, 1, Zptr, Zptr)
}
const ftxwakeall = {uaddr
- -> sys.umtx_op((uaddr : void#), sys.Umtxwakepriv, 0x7fffffff, Zptr, Zptr)
+ sys.umtx_op((uaddr : void#), sys.Umtxwakepriv, 0x7fffffff, Zptr, Zptr)
}
impl atomic ftxtag =
diff --git a/lib/thread/futex+linux.myr b/lib/thread/futex+linux.myr
index c5dbf06..c182644 100644
--- a/lib/thread/futex+linux.myr
+++ b/lib/thread/futex+linux.myr
@@ -1,3 +1,4 @@
+use std
use sys
use "atomic"
@@ -7,26 +8,60 @@ pkg thread =
type ftxtag = uint32
impl atomic ftxtag
- const ftxwait : (uaddr : ftxtag#, val : ftxtag, timeout : sys.timespec# -> int)
- const ftxwake : (uaddr : ftxtag# -> int)
- const ftxwakeall : (uaddr : ftxtag# -> int)
+ 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, timeout
- -> (sys.futex((uaddr : int32#),
- sys.Futexwait | sys.Futexpriv,
- (val : int32),
- timeout,
- Zptr,
- 0) : int)
+const ftxwait = {uaddr, val, tmout
+ var rc
+
+ if tmout < 0
+ while (rc = (sys.futex((uaddr : int32#),
+ sys.Futexwait | sys.Futexpriv,
+ (val : int32),
+ Zptr,
+ Zptr,
+ 0) : sys.errno)) == sys.Eintr
+ ;;
+ else
+ var t = (tmout : int64)
+ var ts
+ std.assert(sys.clock_gettime(`sys.Clockmonotonic, &ts) == 0,
+ "error: clock_gettime returned -1\n")
+ ts.nsec += (t % 1_000_000) * 1000
+ ts.sec += (ts.nsec / 1_000_000_000) + (t / 1_000_000)
+ ts.nsec %= 1_000_000_000
+
+ /*
+ Futexwaitbitset + Futexbitsetmatchany causes the timeout to be
+ treated as absolute rather than relative.
+ */
+ while (rc = (sys.futex((uaddr : int32#),
+ sys.Futexwaitbitset | sys.Futexpriv,
+ (val : int32),
+ &ts,
+ Zptr,
+ sys.Futexbitsetmatchany) : sys.errno)) == sys.Eintr
+ ;;
+ ;;
+
+ match rc
+ | 0: -> 0
+ | sys.Eagain: -> sys.Eagain
+ | sys.Etimedout: -> sys.Etimedout
+ | err:
+ std.fput(2, "error: futex returned {}\n", err)
+ std.suicide()
+ ;;
}
const ftxwake = {uaddr
- -> (sys.futex((uaddr : int32#), sys.Futexwake | sys.Futexpriv, 1, Zptr, Zptr, 0) : int)
+ sys.futex((uaddr : int32#), sys.Futexwake | sys.Futexpriv, 1, Zptr, Zptr, 0)
}
const ftxwakeall = {uaddr
- -> (sys.futex((uaddr : int32#), sys.Futexwake | sys.Futexpriv, 0x7fffffff, Zptr, Zptr, 0) : int)
+ sys.futex((uaddr : int32#), sys.Futexwake | sys.Futexpriv, 0x7fffffff, Zptr, Zptr, 0)
}
impl atomic ftxtag =
diff --git a/lib/thread/futex+openbsd:6.2.myr b/lib/thread/futex+openbsd:6.2.myr
index e3c9c41..ab89241 100644
--- a/lib/thread/futex+openbsd:6.2.myr
+++ b/lib/thread/futex+openbsd:6.2.myr
@@ -1,3 +1,4 @@
+use std
use sys
use "atomic"
@@ -7,21 +8,78 @@ pkg thread =
type ftxtag = uint32
impl atomic ftxtag
- const ftxwait : (uaddr : ftxtag#, val : ftxtag, timeout : sys.timespec# -> int)
- const ftxwake : (uaddr : ftxtag# -> int)
- const ftxwakeall : (uaddr : ftxtag# -> int)
+ 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, timeout
- -> sys.futex((uaddr : uint32#), sys.Futexwait, (val : int), timeout, Zptr)
+const ftxwait = {uaddr, val, tmout
+ var rc
+
+ if tmout < 0
+ while (rc = (sys.futex((uaddr : uint32#),
+ sys.Futexwait,
+ (val : int),
+ Zptr,
+ Zptr) : sys.errno)) == sys.Eintr
+ ;;
+ else
+ var t = (tmout : int64)
+ var start
+ std.assert(sys.clock_gettime(`sys.Clockmonotonic, &start) == 0,
+ "error: clock_gettime returned -1\n")
+ var ts = [
+ .sec = t / 1_000_000,
+ .nsec = (t % 1_000_000) * 1000,
+ ]
+
+ while (rc = (sys.futex((uaddr : uint32#),
+ sys.Futexwait,
+ (val : int),
+ &ts,
+ Zptr) : sys.errno)) == sys.Eintr
+ var now
+ std.assert(sys.clock_gettime(`sys.Clockmonotonic, &now) == 0,
+ "error: clock_gettime returned -1\n")
+ var t1 = t - ((now.sec - start.sec) * 1_000_000)
+ var nsec = now.nsec - start.nsec
+ if nsec >= 0
+ t1 -= nsec / 1000
+ else
+ t1 -= (1_000_000_000 + nsec) / 1000
+ ;;
+
+ if t1 > t
+ -> sys.Etimedout
+ ;;
+ ts.sec = t1 / 1_000_000
+ ts.nsec = (t1 % 1_000_000) * 1000
+ t = t1
+ ;;
+ ;;
+
+ /*
+ * Since Myrddin uses the convention that negative
+ * values flag an error, but futexes just return a
+ * positive, non-errno value, we need to match against
+ * the positive value.
+ */
+ match rc
+ | 0: -> 0
+ | -sys.Eagain: -> sys.Eagain
+ | -sys.Etimedout: -> sys.Etimedout
+ | err:
+ std.fput(2, "error: futex returned {}\n", err)
+ std.suicide()
+ ;;
}
const ftxwake = {uaddr
- -> sys.futex((uaddr : uint32#), sys.Futexwake, 1, Zptr, Zptr)
+ sys.futex((uaddr : uint32#), sys.Futexwake, 1, Zptr, Zptr)
}
const ftxwakeall = {uaddr
- -> sys.futex((uaddr : uint32#), sys.Futexwake, 0x7fffffff, Zptr, Zptr)
+ sys.futex((uaddr : uint32#), sys.Futexwake, 0x7fffffff, Zptr, Zptr)
}
impl atomic ftxtag =
diff --git a/lib/thread/futex+osx.myr b/lib/thread/futex+osx.myr
index 1747870..ea93fda 100644
--- a/lib/thread/futex+osx.myr
+++ b/lib/thread/futex+osx.myr
@@ -8,49 +8,72 @@ 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)
+ const ftxwait : (uaddr : ftxtag#, val : ftxtag, tmout : std.time -> sys.errno)
+ const ftxwake : (uaddr : ftxtag# -> void)
+ const ftxwakeall : (uaddr : ftxtag# -> void)
;;
/*
* 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)
- ;;
+const ftxwait = {uaddr, val, tmout
+ var rc
- 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)
- ;;
+ if tmout < 0
+ while (rc = (sys.ulock_wait(sys.Ulockcompareandwait,
+ (uaddr : uint64#),
+ (val : uint64),
+ 0) : sys.errno)) == sys.Eintr
+ ;;
+ else
+ var start, t
+ std.assert(tmout <= 0xffffffff, "error: maximum os x futex timeout exceeded\n")
+ std.assert(sys.clock_gettime(`sys.Clockmonotonic, &start) == 0,
+ "error: clock_gettime returned -1\n")
+ t = (tmout : uint32)
+
+ while (rc = (sys.ulock_wait(sys.Ulockcompareandwait,
+ (uaddr : uint64#),
+ (val : uint64),
+ t) : sys.errno)) == sys.Eintr
+ var now
+ std.assert(sys.clock_gettime(`sys.Clockmonotonic, &now) == 0,
+ "error: clock_gettime returned -1\n")
+ var t1 = t - (((now.sec - start.sec) * 1_000_000) : uint32)
+ var nsec = now.nsec - start.nsec
+ if nsec >= 0
+ t1 -= (nsec / 1000 : uint32)
+ else
+ t1 -= ((1_000_000_000 + nsec) / 1000 : uint32)
+ ;;
- 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 t1 > t
+ -> sys.Etimedout
+ ;;
+ t = t1
+ ;;
;;
- if usec == 0
- -> (std.Etimedout : int)
+ match rc
+ | 0: -> 0
+ | sys.Eagain: -> sys.Eagain
+ | sys.Etimedout: -> sys.Etimedout
+ | err:
+ if err > 0
+ -> 0
+ ;;
+ std.fput(2, "error: ulock_wait returned {}\n", err)
+ std.suicide()
;;
- -> sys.ulock_wait(sys.Ulockcompareandwait, (uaddr : uint64#), (val : uint64), usec)
}
const ftxwake = {uaddr
- -> sys.ulock_wake(sys.Ulockcompareandwait, (uaddr : uint64#), 0)
+ sys.ulock_wake(sys.Ulockcompareandwait, (uaddr : uint64#), 0)
}
const ftxwakeall = {uaddr
- -> sys.ulock_wake(sys.Ulockcompareandwait | sys.Ulockulfwakeall, (uaddr : uint64#), 0)
+ sys.ulock_wake(sys.Ulockcompareandwait | sys.Ulockulfwakeall, (uaddr : uint64#), 0)
}
impl atomic ftxtag =
diff --git a/lib/thread/mutex+futex.myr b/lib/thread/mutex+futex.myr
index a6453fa..50e8406 100644
--- a/lib/thread/mutex+futex.myr
+++ b/lib/thread/mutex+futex.myr
@@ -1,5 +1,4 @@
use "atomic"
-use "common"
use "futex"
pkg thread =
@@ -28,12 +27,12 @@ const mkmtx = {
const mtxlock = {mtx
var c
- /*
+ /*
Uncontended case: we get an unlocked mutex, and we lock it.
*/
- c = Locked
+ c = Locked
for var i = 0; i < nspin; i++
- c = xcas(&mtx._state, Unlocked, Locked)
+ c = xcas(&mtx._state, Unlocked, Locked)
if c == Unlocked
-> void
;;
@@ -49,7 +48,7 @@ const mtxlock = {mtx
;;
while c != Unlocked
- ftxwait(&mtx._state, Contended, Zptr)
+ ftxwait(&mtx._state, Contended, -1)
c = xchg(&mtx._state, Contended)
;;
}
@@ -74,6 +73,6 @@ const mtxunlock = {mtx
const mtxcontended = {mtx
while xchg(&mtx._state, Contended) != Unlocked
- ftxwait(&mtx._state, Contended, Zptr)
+ ftxwait(&mtx._state, Contended, -1)
;;
}
diff --git a/lib/thread/mutex+plan9.myr b/lib/thread/mutex+plan9.myr
index e2e1207..67c93bf 100644
--- a/lib/thread/mutex+plan9.myr
+++ b/lib/thread/mutex+plan9.myr
@@ -1,9 +1,7 @@
use std
use sys
-
use "atomic"
-use "common"
pkg thread =
type mutex = struct
diff --git a/lib/thread/mutex.myr b/lib/thread/mutex.myr
index 5b90574..b37f2fb 100644
--- a/lib/thread/mutex.myr
+++ b/lib/thread/mutex.myr
@@ -1,9 +1,7 @@
use std
use sys
-
use "atomic"
-use "common"
pkg thread =
type mutex = struct
diff --git a/lib/thread/sem+futex.myr b/lib/thread/sem+futex.myr
index d79bd41..542586b 100644
--- a/lib/thread/sem+futex.myr
+++ b/lib/thread/sem+futex.myr
@@ -1,7 +1,6 @@
use std
use "atomic"
-use "common"
use "futex"
pkg thread =
@@ -28,7 +27,7 @@ const semwait = {s
-> void
;;
;;
- ftxwait(&s._val, v, Zptr)
+ ftxwait(&s._val, v, -1)
;;
}
diff --git a/lib/thread/sem+plan9.myr b/lib/thread/sem+plan9.myr
index 221a805..449d7ce 100644
--- a/lib/thread/sem+plan9.myr
+++ b/lib/thread/sem+plan9.myr
@@ -2,7 +2,6 @@ use std
use sys
use "atomic"
-use "common"
pkg thread =
type sem = struct
diff --git a/lib/thread/waitgrp+futex.myr b/lib/thread/waitgrp+futex.myr
index 7fbd5eb..701d8f0 100644
--- a/lib/thread/waitgrp+futex.myr
+++ b/lib/thread/waitgrp+futex.myr
@@ -1,7 +1,6 @@
use std
use "atomic"
-use "common"
use "futex"
pkg thread =
@@ -22,7 +21,7 @@ const wgwait = {w
var v = 0
while (v = xget(&w._val)) != 0
- ftxwait(&w._val, v, Zptr)
+ ftxwait(&w._val, v, -1)
;;
}
diff --git a/support/syscall-gen/specials+freebsd-x64.frag b/support/syscall-gen/specials+freebsd-x64.frag
index 82b3c31..de5cfa4 100644
--- a/support/syscall-gen/specials+freebsd-x64.frag
+++ b/support/syscall-gen/specials+freebsd-x64.frag
@@ -65,6 +65,7 @@
const mmap : (addr:byte#, len:size, prot:mprot, flags:mopt, fd:fd, off:off -> byte#)
/* time - doublecheck if this is right */
+ const clockid : (clk : clock -> uint64)
const clock_getres : (clk : clock, ts : timespec# -> int32)
const clock_gettime : (clk : clock, ts : timespec# -> int32)
const clock_settime : (clk : clock, ts : timespec# -> int32)
diff --git a/support/syscall-gen/specials+linux-x64.frag b/support/syscall-gen/specials+linux-x64.frag
index de2ce27..6f8b806 100644
--- a/support/syscall-gen/specials+linux-x64.frag
+++ b/support/syscall-gen/specials+linux-x64.frag
@@ -62,7 +62,7 @@ const dup2 : (src : fd, dst : fd -> fd)
/* threading */
const futex : (uaddr : int32#, op : futexop, val : int32, \
- timeout : timespec#, uaddr2 : int32#, val3 : int32 -> int64)
+ timeout : timespec#, uaddr2 : int32#, val3 : int32 -> int)
const semctl : (semid : int, semnum : int, cmd : int, arg : void# -> int)
/* polling */
@@ -205,7 +205,7 @@ const sigprocmask = {sig, act, oact; -> (syscall(Sysrt_sigprocmask, a(sig), a(ac
/* threading */
const futex = {uaddr, op, val, timeout, uaddr2, val3
- -> syscall(Sysfutex, a(uaddr), a(op), a(val), a(timeout), a(uaddr2), a(val3))
+ -> (syscall(Sysfutex, a(uaddr), a(op), a(val), a(timeout), a(uaddr2), a(val3)) : int)
}
const semctl = {semid, semnum, cmd, arg
-> (syscall(Syssemctl, a(semnum), a(cmd), a(arg)) : int)
diff --git a/support/syscall-gen/types+freebsd-x64.frag b/support/syscall-gen/types+freebsd-x64.frag
index 9bae305..f899053 100644
--- a/support/syscall-gen/types+freebsd-x64.frag
+++ b/support/syscall-gen/types+freebsd-x64.frag
@@ -575,6 +575,13 @@ type uuid = struct
node : uint8[_Uuidnodesz];
;;
+const Umtxabstime = 1
+type umtx_time = struct
+ timeout : timespec
+ flags : uint32
+ clockid : uint32
+;;
+
/* open options */
const Ordonly : fdopt = 0x0
const Owronly : fdopt = 0x1
diff --git a/support/syscall-gen/types+linux-x64.frag b/support/syscall-gen/types+linux-x64.frag
index 13d95aa..9e90a5a 100644
--- a/support/syscall-gen/types+linux-x64.frag
+++ b/support/syscall-gen/types+linux-x64.frag
@@ -556,6 +556,8 @@ const Futexcmprequeuepi : futexop = 12
const Futexpriv : futexop = 128
const Futexclockrt : futexop = 256
+const Futexbitsetmatchany : int32 = -1
+
/* poll events : posix */
const Pollin : pollevt = 0x001 /* There is data to read. */
const Pollpri : pollevt = 0x002 /* There is urgent data to read. */