From 79761c6681f0d1cc1c027116fcb4382d41ed3ece Mon Sep 17 00:00:00 2001 From: Izumi Tsutsui Date: Wed, 3 Jul 2013 17:58:14 +0900 Subject: semaphore: fix a hangup problem under load on NetBSD hosts. Fix following bugs in "fallback implementation of counting semaphores with mutex+condvar" added in c166cb72f1676855816340666c3b618beef4b976: - waiting threads are not restarted properly if more than one threads are waiting unblock signals in qemu_sem_timedwait() - possible missing pthread_cond_signal(3) calls when waiting threads are returned by ETIMEDOUT - fix an uninitialized variable The problem is analyzed by and fix is provided by Noriyuki Soda. Also put additional cleanup suggested by Laszlo Ersek: - make QemuSemaphore.count unsigned (it won't be negative) - check a return value of in pthread_cond_wait() in qemu_sem_wait() Signed-off-by: Izumi Tsutsui Reviewed-by: Laszlo Ersek Message-id: 1372841894-10634-1-git-send-email-tsutsui@ceres.dti.ne.jp Signed-off-by: Anthony Liguori --- util/qemu-thread-posix.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'util/qemu-thread-posix.c') diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c index 4489abf1d8..4de133e7b2 100644 --- a/util/qemu-thread-posix.c +++ b/util/qemu-thread-posix.c @@ -170,12 +170,11 @@ void qemu_sem_post(QemuSemaphore *sem) #if defined(__APPLE__) || defined(__NetBSD__) pthread_mutex_lock(&sem->lock); - if (sem->count == INT_MAX) { + if (sem->count == UINT_MAX) { rc = EINVAL; - } else if (sem->count++ < 0) { - rc = pthread_cond_signal(&sem->cond); } else { - rc = 0; + sem->count++; + rc = pthread_cond_signal(&sem->cond); } pthread_mutex_unlock(&sem->lock); if (rc != 0) { @@ -207,19 +206,21 @@ int qemu_sem_timedwait(QemuSemaphore *sem, int ms) struct timespec ts; #if defined(__APPLE__) || defined(__NetBSD__) + rc = 0; compute_abs_deadline(&ts, ms); pthread_mutex_lock(&sem->lock); - --sem->count; - while (sem->count < 0) { + while (sem->count == 0) { rc = pthread_cond_timedwait(&sem->cond, &sem->lock, &ts); if (rc == ETIMEDOUT) { - ++sem->count; break; } if (rc != 0) { error_exit(rc, __func__); } } + if (rc != ETIMEDOUT) { + --sem->count; + } pthread_mutex_unlock(&sem->lock); return (rc == ETIMEDOUT ? -1 : 0); #else @@ -249,16 +250,19 @@ int qemu_sem_timedwait(QemuSemaphore *sem, int ms) void qemu_sem_wait(QemuSemaphore *sem) { + int rc; + #if defined(__APPLE__) || defined(__NetBSD__) pthread_mutex_lock(&sem->lock); - --sem->count; - while (sem->count < 0) { - pthread_cond_wait(&sem->cond, &sem->lock); + while (sem->count == 0) { + rc = pthread_cond_wait(&sem->cond, &sem->lock); + if (rc != 0) { + error_exit(rc, __func__); + } } + --sem->count; pthread_mutex_unlock(&sem->lock); #else - int rc; - do { rc = sem_wait(&sem->sem); } while (rc == -1 && errno == EINTR); -- cgit v1.2.3