Eigenstate: myrddin-dev mailing list

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/4] Fix futex timeouts and handle futex error codes.


---
 lib/sys/sys+linux-x64.myr          |  6 ++-
 lib/thread/condvar+freebsd.myr     | 15 ++-----
 lib/thread/condvar+linux.myr       | 20 +++------
 lib/thread/condvar+openbsd:6.2.myr | 20 +++------
 lib/thread/condvar+osx.myr         | 15 ++-----
 lib/thread/condvar.myr             |  2 +-
 lib/thread/futex+freebsd.myr       | 54 ++++++++++++++--------
 lib/thread/futex+linux.myr         | 57 ++++++++++++++++++-----
 lib/thread/futex+openbsd:6.2.myr   | 64 +++++++++++++++++++++++---
 lib/thread/futex+osx.myr           | 72 +++++++++++++++++++-----------
 lib/thread/mutex+futex.myr         | 11 +++--
 lib/thread/mutex+plan9.myr         |  2 -
 lib/thread/mutex.myr               |  2 -
 lib/thread/sem+futex.myr           |  3 +-
 lib/thread/sem+plan9.myr           |  1 -
 lib/thread/waitgrp+futex.myr       |  3 +-
 16 files changed, 216 insertions(+), 131 deletions(-)

diff --git a/lib/sys/sys+linux-x64.myr b/lib/sys/sys+linux-x64.myr
index 1cebb123..83fdea53 100644
--- a/lib/sys/sys+linux-x64.myr
+++ b/lib/sys/sys+linux-x64.myr
@@ -562,6 +562,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.  */
@@ -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 002757ae..4e2b0c11 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,11 @@ 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)
-
-	/*
-	FIXME?: `ftxwait` can be interrupted but `condwait` should always be
-	done in a loop anyway.
-	*/
-	ftxwait(&cond._seq, seq, Zptr)
-
+	ftxwait(&cond._seq, seq, 0)
 	mtxlock(mtx)
 }
 
diff --git a/lib/thread/condvar+linux.myr b/lib/thread/condvar+linux.myr
index e1a9e100..69ab8704 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,18 +23,11 @@ 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)
-
-	/*
-	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)
+	ftxwait(&cond._seq, seq, 0)
 
 	/*
 	We need to atomically set the mutex to contended. This allows us to
@@ -45,7 +39,7 @@ const condwait = {cond
 
 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 +49,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 29dbb35f..35ad27b4 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,18 +23,11 @@ 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)
-
-	/*
-	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)
+	ftxwait(&cond._seq, seq, 0)
 
 	/*
 	We need to atomically set the mutex to contended. This allows us to
@@ -45,12 +39,12 @@ const condwait = {cond
 
 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 d74c321f..d18f4ccb 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,11 @@ 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)
-
-	/*
-	FIXME?: `ftxwait` can be interrupted but `condwait` should always be
-	done in a loop anyway.
-	*/
-	ftxwait(&cond._seq, seq, Zptr)
-
+	ftxwait(&cond._seq, seq, 0)
 	mtxlock(mtx)
 }
 
diff --git a/lib/thread/condvar.myr b/lib/thread/condvar.myr
index 4fde7073..8dedde15 100644
--- a/lib/thread/condvar.myr
+++ b/lib/thread/condvar.myr
@@ -20,7 +20,7 @@ pkg thread =
 
 /*
 The waitqueue is a doubly-linked list because we'll need to remove waiters from
-anywhere in the list when we add timeout support.
+anywhere in the list if we ever add timeout support.
 
 `cond._waitq.prev` is the tail of the queue.
 */
diff --git a/lib/thread/futex+freebsd.myr b/lib/thread/futex+freebsd.myr
index ea5f28d8..a9ad01ed 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,51 @@ 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 : uint32 -> 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 = 1 /* CLOCK_MONOTONIC. Not exported from sys. */
+		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.fatal("error: futex returned {}\n", err)
+	;;
 }
 
 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 c5dbf062..d20aca8b 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,58 @@ 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 : uint32 -> 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.fatal("error: futex returned {}\n", err)
+	;;
 }
 
 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 e3c9c413..cda80347 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,70 @@ 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 : uint32 -> 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
+		;;
+	;;
+
+	match rc
+	| 0: -> 0
+	| sys.Eagain: -> sys.Eagain
+	| sys.Etimedout: -> sys.Etimedout
+	| err: std.fatal("error: futex returned {}\n", err)
+	;;
 }
 
 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 17478703..c07e6b3e 100644
--- a/lib/thread/futex+osx.myr
+++ b/lib/thread/futex+osx.myr
@@ -8,49 +8,69 @@ 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 : uint32 -> 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
+		std.assert(sys.clock_gettime(`sys.Clockmonotonic, &start) == 0,
+			"error: clock_gettime returned -1\n")
+
+		while (rc = (sys.ulock_wait(sys.Ulockcompareandwait,
+				(uaddr : uint64#),
+				(val : uint64),
+				tmout) : sys.errno)) == sys.Eintr
+			var now
+			std.assert(sys.clock_gettime(`sys.Clockmonotonic, &now) == 0,
+				"error: clock_gettime returned -1\n")
+			var t = tmout - (((now.sec - start.sec) * 1_000_000) : uint32)
+			var nsec = now.nsec - start.nsec
+			if nsec >= 0
+				t -= (nsec / 1000 : uint32)
+			else
+				t -= ((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 t > tmout
+				-> sys.Etimedout
+			;;
+			tmout = t
+		;;
 	;;
 
-	if usec == 0
-		-> (std.Etimedout : int)
+	match rc
+	| 0: -> 0
+	| sys.Eagain: -> sys.Eagain
+	| sys.Etimedout: -> sys.Etimedout
+	| err:
+		if err > 0
+			-> 0
+		;;
+		std.fatal("error: ulock_wait returned {}\n", err)
 	;;
-	-> 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 a6453fa9..2a6137e7 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, 0)
 		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, 0)
 	;;
 }
diff --git a/lib/thread/mutex+plan9.myr b/lib/thread/mutex+plan9.myr
index e2e1207f..67c93bfb 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 5b905749..b37f2fb3 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 d79bd41b..434e195d 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, 0)
 	;;
 }
 
diff --git a/lib/thread/sem+plan9.myr b/lib/thread/sem+plan9.myr
index 221a8056..449d7ceb 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 7fbd5eb6..bd26d1ce 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, 0)
 	;;
 }
 
-- 
2.18.0


Follow-Ups:
Re: [PATCH 2/4] Fix futex timeouts and handle futex error codes.Ori Bernstein <ori@xxxxxxxxxxxxxx>