qemu_event_timedwait() is equivalent to qemu_event_wait(), except it has a relative timeout.
Signed-off-by: Akihiko Odaki <[email protected]> --- include/qemu/thread-posix.h | 11 +++++++++++ include/qemu/thread.h | 8 +++++++- util/event.c | 34 +++++++++++++++++++++++++++++----- util/qemu-thread-posix.c | 11 +---------- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/include/qemu/thread-posix.h b/include/qemu/thread-posix.h index 758808b705e4..11193b1580f8 100644 --- a/include/qemu/thread-posix.h +++ b/include/qemu/thread-posix.h @@ -36,4 +36,15 @@ struct QemuThread { pthread_t thread; }; +static inline clockid_t qemu_timedwait_clockid(void) +{ +#ifdef CONFIG_PTHREAD_CONDATTR_SETCLOCK + return CLOCK_MONOTONIC; +#else + return CLOCK_REALTIME; +#endif +} + +void compute_abs_deadline(struct timespec *ts, int ms); + #endif diff --git a/include/qemu/thread.h b/include/qemu/thread.h index f0302ed01fdb..3030458bb666 100644 --- a/include/qemu/thread.h +++ b/include/qemu/thread.h @@ -201,7 +201,13 @@ void qemu_sem_destroy(QemuSemaphore *sem); void qemu_event_init(QemuEvent *ev, bool init); void qemu_event_set(QemuEvent *ev); void qemu_event_reset(QemuEvent *ev); -void qemu_event_wait(QemuEvent *ev); +bool qemu_event_timedwait(QemuEvent *ev, int ms); + +static inline void qemu_event_wait(QemuEvent *ev) +{ + qemu_event_timedwait(ev, INT_MAX); +} + void qemu_event_destroy(QemuEvent *ev); void qemu_thread_create(QemuThread *thread, const char *name, diff --git a/util/event.c b/util/event.c index 5a8141cd0e46..e22cc08a629b 100644 --- a/util/event.c +++ b/util/event.c @@ -33,7 +33,15 @@ void qemu_event_init(QemuEvent *ev, bool init) { #ifndef HAVE_FUTEX pthread_mutex_init(&ev->lock, NULL); +#ifdef CONFIG_PTHREAD_CONDATTR_SETCLOCK + pthread_condattr_t attr; + pthread_condattr_init(&attr); + pthread_condattr_setclock(&attr, qemu_timedwait_clockid()); + pthread_cond_init(&ev->cond, &attr); + pthread_condattr_destroy(&attr); +#else pthread_cond_init(&ev->cond, NULL); +#endif #endif ev->value = (init ? EV_SET : EV_FREE); @@ -121,15 +129,17 @@ void qemu_event_reset(QemuEvent *ev) #endif } -void qemu_event_wait(QemuEvent *ev) +bool qemu_event_timedwait(QemuEvent *ev, int ms) { assert(ev->initialized); #ifdef HAVE_FUTEX + int64_t deadline = get_clock() + (int64_t)ms * SCALE_MS; + while (true) { /* - * qemu_event_wait must synchronize with qemu_event_set even if it does - * not go down the slow path, so this load-acquire is needed that + * qemu_event_timedwait must synchronize with qemu_event_set even if it + * does not go down the slow path, so this load-acquire is needed that * synchronizes with the first memory barrier in qemu_event_set(). */ unsigned value = qatomic_load_acquire(&ev->value); @@ -159,13 +169,27 @@ void qemu_event_wait(QemuEvent *ev) * a smp_mb() pairing with the second barrier of qemu_event_set(). * The barrier is inside the FUTEX_WAIT system call. */ - qemu_futex_wait(ev, EV_BUSY); + if (!qemu_futex_timedwait(ev, EV_BUSY, deadline)) { + return false; + } } + + return true; #else + bool failed; + struct timespec ts; + + compute_abs_deadline(&ts, ms); + pthread_mutex_lock(&ev->lock); while (qatomic_read(&ev->value) != EV_SET) { - pthread_cond_wait(&ev->cond, &ev->lock); + failed = pthread_cond_timedwait(&ev->cond, &ev->lock, &ts); + if (failed) { + break; + } } pthread_mutex_unlock(&ev->lock); + + return !failed; #endif } diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c index ba725444ba63..f649bfa00015 100644 --- a/util/qemu-thread-posix.c +++ b/util/qemu-thread-posix.c @@ -44,16 +44,7 @@ static void error_exit(int err, const char *msg) abort(); } -static inline clockid_t qemu_timedwait_clockid(void) -{ -#ifdef CONFIG_PTHREAD_CONDATTR_SETCLOCK - return CLOCK_MONOTONIC; -#else - return CLOCK_REALTIME; -#endif -} - -static void compute_abs_deadline(struct timespec *ts, int ms) +void compute_abs_deadline(struct timespec *ts, int ms) { clock_gettime(qemu_timedwait_clockid(), ts); ts->tv_nsec += (ms % 1000) * 1000000; -- 2.51.0
