From patchwork Wed Jul 3 08:58:14 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Izumi Tsutsui X-Patchwork-Id: 256564 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 9C9C82C007E for ; Wed, 3 Jul 2013 18:59:01 +1000 (EST) Received: from localhost ([::1]:39158 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UuItv-0000FA-Hn for incoming@patchwork.ozlabs.org; Wed, 03 Jul 2013 04:58:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34746) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UuIte-0000Ch-Q0 for qemu-devel@nongnu.org; Wed, 03 Jul 2013 04:58:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UuItZ-0004gB-Vd for qemu-devel@nongnu.org; Wed, 03 Jul 2013 04:58:42 -0400 Received: from vsmtp03.dti.ne.jp ([202.216.231.138]:52025) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UuItZ-0004fv-HR for qemu-devel@nongnu.org; Wed, 03 Jul 2013 04:58:37 -0400 Received: from mirage.localdomain (PPPpm453.hyogo-ip.dti.ne.jp [210.170.227.203]) by vsmtp03.dti.ne.jp (3.11v) with ESMTP AUTH id r638wYbN029780; Wed, 3 Jul 2013 17:58:35 +0900 (JST) Received: from mirage.ceres.dti.ne.jp (localhost [127.0.0.1]) by mirage.localdomain (8.14.4/8.14.4) with ESMTP id r638wXfZ015493; Wed, 3 Jul 2013 17:58:34 +0900 (JST) From: Izumi Tsutsui To: qemu-devel@nongnu.org Date: Wed, 3 Jul 2013 17:58:14 +0900 Message-Id: <1372841894-10634-1-git-send-email-tsutsui@ceres.dti.ne.jp> X-Mailer: git-send-email 1.8.0.1 X-detected-operating-system: by eggs.gnu.org: Windows NT kernel [generic] [fuzzy] X-Received-From: 202.216.231.138 Cc: Izumi Tsutsui , lersek@redhat.com Subject: [Qemu-devel] [PATCH v3] semaphore: fix a hangup problem under load on NetBSD hosts. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 Reviewed-by: Laszlo Ersek --- v3: - fix a missed assignment and actually check a retval of pthread_cond_wait() v2: - make QemuSemaphore.count unsigned (it won't be negative) - also eliminate checks for negative count values - check a return value of in pthread_cond_wait() in qemu_sem_wait() include/qemu/thread-posix.h | 2 +- util/qemu-thread-posix.c | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/include/qemu/thread-posix.h b/include/qemu/thread-posix.h index 0f30dcc..361566a 100644 --- a/include/qemu/thread-posix.h +++ b/include/qemu/thread-posix.h @@ -15,7 +15,7 @@ struct QemuSemaphore { #if defined(__APPLE__) || defined(__NetBSD__) pthread_mutex_t lock; pthread_cond_t cond; - int count; + unsigned int count; #else sem_t sem; #endif diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c index 4489abf..4de133e 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);