From a0d45db85496c195ab5f3f2ced742fc93d9709c2 Mon Sep 17 00:00:00 2001 From: "Longpeng(Mike)" Date: Tue, 22 Feb 2022 17:05:06 +0800 Subject: [PATCH] thread-posix: implement Semaphore with QemuCond and QemuMutex Now that QemuSemaphore is implemented through pthread_cond_t only, we can use QemuCond and QemuMutex to make the code smaller. Features such as mutex tracing and CLOCK_MONOTONIC timedwait are supported in qemu-sem naturally. Signed-off-by: Longpeng(Mike) Message-Id: <20220222090507.2028-4-longpeng2@huawei.com> Signed-off-by: Paolo Bonzini --- include/qemu/thread-posix.h | 5 +- util/qemu-thread-posix.c | 105 +++++++++++------------------------- 2 files changed, 34 insertions(+), 76 deletions(-) diff --git a/include/qemu/thread-posix.h b/include/qemu/thread-posix.h index 5466608d7c..5f2f3d1386 100644 --- a/include/qemu/thread-posix.h +++ b/include/qemu/thread-posix.h @@ -27,10 +27,9 @@ struct QemuCond { }; struct QemuSemaphore { - pthread_mutex_t lock; - pthread_cond_t cond; + QemuMutex mutex; + QemuCond cond; unsigned int count; - bool initialized; }; struct QemuEvent { diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c index f6a34eed2f..8505d8c60f 100644 --- a/util/qemu-thread-posix.c +++ b/util/qemu-thread-posix.c @@ -222,16 +222,15 @@ void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, const char *file, con error_exit(err, __func__); } -bool qemu_cond_timedwait_impl(QemuCond *cond, QemuMutex *mutex, int ms, - const char *file, const int line) +static bool +qemu_cond_timedwait_ts(QemuCond *cond, QemuMutex *mutex, struct timespec *ts, + const char *file, const int line) { int err; - struct timespec ts; assert(cond->initialized); trace_qemu_mutex_unlock(mutex, file, line); - compute_abs_deadline(&ts, ms); - err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts); + err = pthread_cond_timedwait(&cond->cond, &mutex->lock, ts); trace_qemu_mutex_locked(mutex, file, line); if (err && err != ETIMEDOUT) { error_exit(err, __func__); @@ -239,113 +238,73 @@ bool qemu_cond_timedwait_impl(QemuCond *cond, QemuMutex *mutex, int ms, return err != ETIMEDOUT; } +bool qemu_cond_timedwait_impl(QemuCond *cond, QemuMutex *mutex, int ms, + const char *file, const int line) +{ + struct timespec ts; + + compute_abs_deadline(&ts, ms); + return qemu_cond_timedwait_ts(cond, mutex, &ts, file, line); +} + void qemu_sem_init(QemuSemaphore *sem, int init) { - pthread_condattr_t attr; - int rc; + qemu_mutex_init(&sem->mutex); + qemu_cond_init(&sem->cond); - rc = pthread_mutex_init(&sem->lock, NULL); - if (rc != 0) { - error_exit(rc, __func__); - } - rc = pthread_condattr_init(&attr); - if (rc != 0) { - error_exit(rc, __func__); - } -#ifdef CONFIG_PTHREAD_CONDATTR_SETCLOCK - rc = pthread_condattr_setclock(&attr, qemu_timedwait_clockid()); - if (rc != 0) { - error_exit(rc, __func__); - } -#endif - rc = pthread_cond_init(&sem->cond, &attr); - if (rc != 0) { - error_exit(rc, __func__); - } - rc = pthread_condattr_destroy(&attr); - if (rc < 0) { - error_exit(rc, __func__); - } if (init < 0) { error_exit(EINVAL, __func__); } sem->count = init; - sem->initialized = true; } void qemu_sem_destroy(QemuSemaphore *sem) { - int rc; - - assert(sem->initialized); - sem->initialized = false; - rc = pthread_cond_destroy(&sem->cond); - if (rc < 0) { - error_exit(rc, __func__); - } - rc = pthread_mutex_destroy(&sem->lock); - if (rc < 0) { - error_exit(rc, __func__); - } + qemu_cond_destroy(&sem->cond); + qemu_mutex_destroy(&sem->mutex); } void qemu_sem_post(QemuSemaphore *sem) { - int rc; - - assert(sem->initialized); - pthread_mutex_lock(&sem->lock); + qemu_mutex_lock(&sem->mutex); if (sem->count == UINT_MAX) { - rc = EINVAL; + error_exit(EINVAL, __func__); } else { sem->count++; - rc = pthread_cond_signal(&sem->cond); - } - pthread_mutex_unlock(&sem->lock); - if (rc != 0) { - error_exit(rc, __func__); + qemu_cond_signal(&sem->cond); } + qemu_mutex_unlock(&sem->mutex); } int qemu_sem_timedwait(QemuSemaphore *sem, int ms) { - int rc; + bool rc = true; struct timespec ts; - assert(sem->initialized); - rc = 0; compute_abs_deadline(&ts, ms); - pthread_mutex_lock(&sem->lock); + qemu_mutex_lock(&sem->mutex); while (sem->count == 0) { - rc = pthread_cond_timedwait(&sem->cond, &sem->lock, &ts); - if (rc == ETIMEDOUT) { + rc = qemu_cond_timedwait_ts(&sem->cond, &sem->mutex, &ts, + __FILE__, __LINE__); + if (!rc) { /* timeout */ break; } - if (rc != 0) { - error_exit(rc, __func__); - } } - if (rc != ETIMEDOUT) { + if (rc) { --sem->count; } - pthread_mutex_unlock(&sem->lock); - return (rc == ETIMEDOUT ? -1 : 0); + qemu_mutex_unlock(&sem->mutex); + return (rc ? 0 : -1); } void qemu_sem_wait(QemuSemaphore *sem) { - int rc; - - assert(sem->initialized); - pthread_mutex_lock(&sem->lock); + qemu_mutex_lock(&sem->mutex); while (sem->count == 0) { - rc = pthread_cond_wait(&sem->cond, &sem->lock); - if (rc != 0) { - error_exit(rc, __func__); - } + qemu_cond_wait(&sem->cond, &sem->mutex); } --sem->count; - pthread_mutex_unlock(&sem->lock); + qemu_mutex_unlock(&sem->mutex); } #ifdef __linux__