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 | 29 ++++++++++++++++++++++++-----
1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/include/qemu/futex.h b/include/qemu/futex.h
index 607613eec835..e5e56603d117 100644
--- a/include/qemu/futex.h
+++ b/include/qemu/futex.h
@@ -24,6 +24,7 @@
#ifndef QEMU_FUTEX_H
#define QEMU_FUTEX_H
+#include "qemu/timer.h"
#define HAVE_FUTEX
#ifdef CONFIG_LINUX
@@ -42,18 +43,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 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 +79,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);
+ uint32_t duration = MIN((ns - get_clock()) / SCALE_MS, UINT32_MAX);
+ 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.51.0
Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> writes:
> 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>
Hmm this broke my compile, I guess a name clash:
FAILED: tests/qtest/stm32l4x5_usart-test.p/stm32l4x5_usart-test.c.o
cc -m64 -Itests/qtest/stm32l4x5_usart-test.p -Itests/qtest -I../../tests/qtest -I. -Iqapi -Itrace -Iui -Iui/shader -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/sysprof-6 -fdiagnostics-color=auto -Wall -Winvalid-pch -Werror -std=gnu11 -O2 -g -fstack-protector-strong -Wempty-body -Wendif-labels -Wexpansion-to-defined -Wformat-security -Wformat-y2k -Wignored-qualifiers -Wimplicit-fallthrough=2 -Winit-self -Wmissing-format-attribute -Wmissing-prototypes -Wnested-externs -Wold-style-declaration -Wold-style-definition -Wredundant-decls -Wshadow=local -Wstrict-prototypes -Wtype-limits -Wundef -Wvla -Wwrite-strings -Wno-missing-include-dirs -Wno-psabi -Wno-shift-negative-value -isystem /home/alex/lsrc/qemu.git/linux-headers -isystem linux-headers -iquote . -iquote /home/alex/lsrc/qemu.git -iquote /home/alex/lsrc/qemu.git/include -iquote /home/alex/lsrc/qemu.git/host/include/x86_64 -iquote /home/alex/lsrc/qemu.git/host/include/generic -iquote /home/alex/lsrc/qemu.git/tcg/i386 -pthread -mcx16 -msse2 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fno-strict-aliasing -fno-common -fwrapv -ftrivial-auto-var-init=zero -fzero-call-used-regs=used-gpr -fPIE -MD -MQ tests/qtest/stm32l4x5_usart-test.p/stm32l4x5_usart-test.c.o -MF tests/qtest/stm32l4x5_usart-test.p/stm32l4x5_usart-test.c.o.d -o tests/qtest/stm32l4x5_usart-test.p/stm32l4x5_usart-test.c.o -c ../../tests/qtest/stm32l4x5_usart-test.c
../../tests/qtest/stm32l4x5_usart-test.c:114:13: error: conflicting types for ‘init_clocks’; have ‘void(QTestState *)’
114 | static void init_clocks(QTestState *qts)
| ^~~~~~~~~~~
In file included from /home/alex/lsrc/qemu.git/include/qemu/futex.h:27,
from /home/alex/lsrc/qemu.git/include/qemu/thread.h:6,
from /home/alex/lsrc/qemu.git/include/qemu/rcu.h:27,
from /home/alex/lsrc/qemu.git/include/hw/qdev-core.h:7,
from /home/alex/lsrc/qemu.git/include/hw/sysbus.h:6,
from /home/alex/lsrc/qemu.git/include/hw/misc/stm32l4x5_rcc.h:21,
from /home/alex/lsrc/qemu.git/include/hw/misc/stm32l4x5_rcc_internals.h:22,
from ../../tests/qtest/stm32l4x5_usart-test.c:13:
/home/alex/lsrc/qemu.git/include/qemu/timer.h:793:6: note: previous declaration of ‘init_clocks’ with type ‘void(void (*)(void *, QEMUClockType))’
793 | void init_clocks(QEMUTimerListNotifyCB *notify_cb);
| ^~~~~~~~~~~
ninja: build stopped: cannot make progress due to previous errors.
make: *** [Makefile:168: run-ninja] Error 1
make: Target 'all' not remade because of errors.
make: Leaving directory '/home/alex/lsrc/qemu.git/builds/all'
> ---
> include/qemu/futex.h | 29 ++++++++++++++++++++++++-----
> 1 file changed, 24 insertions(+), 5 deletions(-)
>
> diff --git a/include/qemu/futex.h b/include/qemu/futex.h
> index 607613eec835..e5e56603d117 100644
> --- a/include/qemu/futex.h
> +++ b/include/qemu/futex.h
> @@ -24,6 +24,7 @@
> #ifndef QEMU_FUTEX_H
> #define QEMU_FUTEX_H
>
> +#include "qemu/timer.h"
> #define HAVE_FUTEX
>
> #ifdef CONFIG_LINUX
> @@ -42,18 +43,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 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 +79,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);
> + uint32_t duration = MIN((ns - get_clock()) / SCALE_MS, UINT32_MAX);
> + 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 */
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
© 2016 - 2025 Red Hat, Inc.