qemu_futex_timedwait() is equivalent to qemu_futex_wait(), except it has
an absolute timeout.
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
---
include/qemu/futex.h | 34 +++++++++++++++++++++++++++++-----
1 file changed, 29 insertions(+), 5 deletions(-)
diff --git a/include/qemu/futex.h b/include/qemu/futex.h
index 607613eec835..5b48f79bf329 100644
--- a/include/qemu/futex.h
+++ b/include/qemu/futex.h
@@ -24,13 +24,19 @@
#ifndef QEMU_FUTEX_H
#define QEMU_FUTEX_H
+#include "qemu/timer.h"
#define HAVE_FUTEX
#ifdef CONFIG_LINUX
#include <sys/syscall.h>
#include <linux/futex.h>
+#include <linux/time_types.h>
+#ifdef __NR_futex_time64
+#define qemu_futex(...) syscall(__NR_futex_time64, __VA_ARGS__)
+#else
#define qemu_futex(...) syscall(__NR_futex, __VA_ARGS__)
+#endif
static inline void qemu_futex_wake_all(void *f)
{
@@ -42,18 +48,28 @@ static inline void qemu_futex_wake_single(void *f)
qemu_futex(f, FUTEX_WAKE, 1, NULL, NULL, 0);
}
-static inline void qemu_futex_wait(void *f, unsigned val)
+static inline bool qemu_futex_timedwait(void *f, unsigned val, int64_t ns)
{
- while (qemu_futex(f, FUTEX_WAIT, (int) val, NULL, NULL, 0)) {
+ struct __kernel_timespec ts;
+ uint32_t bitset = FUTEX_BITSET_MATCH_ANY;
+
+ ts.tv_sec = ns / NANOSECONDS_PER_SECOND;
+ ts.tv_nsec = ns % NANOSECONDS_PER_SECOND;
+
+ while (qemu_futex(f, FUTEX_WAIT_BITSET, (int) val, &ts, NULL, bitset)) {
switch (errno) {
case EWOULDBLOCK:
- return;
+ return true;
case EINTR:
break; /* get out of switch and retry */
+ case ETIMEDOUT:
+ return false;
default:
abort();
}
}
+
+ return true;
}
#elif defined(CONFIG_WIN32)
#include <synchapi.h>
@@ -68,12 +84,20 @@ static inline void qemu_futex_wake_single(void *f)
WakeByAddressSingle(f);
}
-static inline void qemu_futex_wait(void *f, unsigned val)
+static inline bool qemu_futex_timedwait(void *f, unsigned val, int64_t ns)
{
- WaitOnAddress(f, &val, sizeof(val), INFINITE);
+ DWORD duration = MIN((ns - get_clock()) / SCALE_MS, INFINITE);
+ return WaitOnAddress(f, &val, sizeof(val), duration);
}
#else
#undef HAVE_FUTEX
#endif
+#ifdef HAVE_FUTEX
+static inline void qemu_futex_wait(void *f, unsigned val)
+{
+ qemu_futex_timedwait(f, val, INT64_MAX);
+}
+#endif
+
#endif /* QEMU_FUTEX_H */
--
2.52.0