From nobody Tue Feb 10 15:01:06 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1512730776490494.9338458457818; Fri, 8 Dec 2017 02:59:36 -0800 (PST) Received: from localhost ([::1]:36557 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eNGNN-0003dL-Tt for importer@patchew.org; Fri, 08 Dec 2017 05:59:29 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47567) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eNGK8-00011H-08 for qemu-devel@nongnu.org; Fri, 08 Dec 2017 05:56:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eNGK6-0001mA-KT for qemu-devel@nongnu.org; Fri, 08 Dec 2017 05:56:08 -0500 Received: from mail-wm0-x243.google.com ([2a00:1450:400c:c09::243]:39291) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eNGK6-0001lx-BA for qemu-devel@nongnu.org; Fri, 08 Dec 2017 05:56:06 -0500 Received: by mail-wm0-x243.google.com with SMTP id i11so2546206wmf.4 for ; Fri, 08 Dec 2017 02:56:06 -0800 (PST) Received: from donizetti.lan (dynamic-adsl-78-12-251-125.clienti.tiscali.it. [78.12.251.125]) by smtp.gmail.com with ESMTPSA id v195sm1325461wmf.25.2017.12.08.02.56.03 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 08 Dec 2017 02:56:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=rarMQ9gYFtK7kuq7jsxlAKo847BemotRT/G5+dGpzoU=; b=de/z6SuH4qysrrOLMYOE0hqfJdVy/esBbWOVB7U+lajoEdvGQuzitHmvEqS1SBK4RH U7uOXJcgl+FReMwIVXY5eRXJe2aImzkvVYae4oa1LgHuYxeKq1OScBHmw9kPxQlaxhwg yEL99ECMNpeKiJ0YeTCRkjkXfv+dRs8AywP+QfJYAjgpO02S9IcQBbdA2sOGgWZP4fz3 rHpBLQK9KKzoQgH115mBqJT9B74gJE7WAgSHS+xbnmr76opHjAfsQXw57rSuRquiKiCR oXIwMhMIqXU2yIvtsaDhC6s1NAg+O8BYdxKeUK0HcMufsy1YoCJ8U5xesuMOtZyIxd3P hteg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=rarMQ9gYFtK7kuq7jsxlAKo847BemotRT/G5+dGpzoU=; b=gOiEocJ4bkwK///KfewXrG0NvwRy99ywKs45eWrL8UeJ3o/5YoYoKnoQxNDYuyHT70 5BrZysWO63HVe1K4hiRmzLng18UNQMfHVpBui0RcL+oiE1HBtBUbEnGrA811MHvPfDsM XWx3Dhg5Rc5qXUiqWUnB30LTMsiKGuSX11UHM0Yh4zcAg18XclRSr6jkr9AMlG1TZe2f d3oTorLT37/SHGlPkqaF5E+AsrrD0J6GTbh2c40xYzG/ySc691IVLKLWo9CHFmxs6pAN wHG+YoQsOYxGreJudTPkQmdV339v3cw36vmg8Iuj8pipE05jNrm4zv8ryU2ZZUjKa3cO 5OeQ== X-Gm-Message-State: AKGB3mKH1Z9L9dTmKaGtW4NckBRD8QkrjqcuC6d84a8ZrxF1YrQa+Vii h9u1txIIrAIX4ageGcB3o0qK9bhD X-Google-Smtp-Source: AGs4zMZwlmC+S3qKJ4kRL8ISeKkwS2ttIgpG2lKUhPx2d/F+GPKECo8otcZlv+VZD7VfV+cEXOo89g== X-Received: by 10.28.27.206 with SMTP id b197mr3845565wmb.96.1512730564794; Fri, 08 Dec 2017 02:56:04 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Fri, 8 Dec 2017 11:55:50 +0100 Message-Id: <20171208105553.12249-3-pbonzini@redhat.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20171208105553.12249-1-pbonzini@redhat.com> References: <20171208105553.12249-1-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c09::243 Subject: [Qemu-devel] [PATCH 2/5] lock-guard: add scoped lock implementation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "Emilio G . Cota" , Fam Zheng , Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Paolo Bonzini --- include/qemu/coroutine.h | 4 ++ include/qemu/lock-guard.h | 99 +++++++++++++++++++++++++++++++++++++++++++= ++++ include/qemu/thread.h | 7 ++++ util/Makefile.objs | 1 + util/qemu-thread.c | 17 ++++++++ 5 files changed, 128 insertions(+) create mode 100644 include/qemu/lock-guard.h create mode 100644 util/qemu-thread.c diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h index 9aff9a735e..8b48803fa8 100644 --- a/include/qemu/coroutine.h +++ b/include/qemu/coroutine.h @@ -17,6 +17,7 @@ =20 #include "qemu/queue.h" #include "qemu/timer.h" +#include "qemu/lock-guard.h" =20 /** * Coroutines are a mechanism for stack switching and can be used for @@ -162,6 +163,9 @@ void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex); */ void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex); =20 +#define QEMU_LOCK_GUARD_FUNCS_CoMutex \ + QEMU_INIT_LOCK_GUARD(CoMutex, qemu_co_mutex_lock, qemu_co_mutex_unlock) + =20 /** * CoQueues are a mechanism to queue coroutines in order to continue execu= ting diff --git a/include/qemu/lock-guard.h b/include/qemu/lock-guard.h new file mode 100644 index 0000000000..e6a83bf9ee --- /dev/null +++ b/include/qemu/lock-guard.h @@ -0,0 +1,103 @@ +#ifndef QEMU_LOCK_GUARD_H +#define QEMU_LOCK_GUARD_H 1 + +typedef void QemuLockGuardFunc(void *); +typedef struct QemuLockGuard { + QemuLockGuardFunc *p_lock_fn, *p_unlock_fn; + void *lock; + int locked; +} QemuLockGuard; + +static inline void qemu_lock_guard_lock(QemuLockGuard *lock_guard) +{ + assert(!lock_guard->locked); + lock_guard->p_lock_fn(lock_guard->lock); + lock_guard->locked =3D true; +} + +static inline void qemu_lock_guard_unlock(QemuLockGuard *lock_guard) +{ + assert(lock_guard->locked); + lock_guard->locked =3D false; + lock_guard->p_unlock_fn(lock_guard->lock); +} + +static inline bool qemu_lock_guard_is_taken(QemuLockGuard *lock_guard) +{ + return lock_guard->locked; +} + +static inline void qemu_lock_guard_release(QemuLockGuard *lock_guard) +{ + lock_guard->lock =3D NULL; + lock_guard->locked =3D false; +} + +inline void qemu_lock_guard_pass(void *ptr) +{ + QemuLockGuard *lock_guard =3D ptr; + assert(lock_guard->locked || !lock_guard->lock); +} + +inline void qemu_lock_guard_cleanup(void *ptr) +{ + QemuLockGuard *lock_guard =3D ptr; + if (likely(lock_guard->locked)) { + lock_guard->p_unlock_fn(lock_guard->lock); + } +} + +static inline QemuLockGuard qemu_lock_guard_init(QemuLockGuard lock_guard) +{ + qemu_lock_guard_lock(&lock_guard); + return lock_guard; +} + +#define QEMU_INIT_LOCK_GUARD(type, lock_fn, unlock_fn) = \ + .p_lock_fn =3D (QemuLockGuardFunc *) (void (*) (type *)) lock_fn, = \ + .p_unlock_fn =3D (QemuLockGuardFunc *) (void (*) (type *)) unlock_fn + +#define QEMU_LOCK_GUARD_(type, lock, locked) = \ + (QemuLockGuard) { = \ + QEMU_LOCK_GUARD_FUNCS_##type, = \ + lock + type_check(typeof(*lock), type), = \ + locked = \ + } + +/* Take a lock that will be unlocked on returning */ +#define QEMU_LOCK_GUARD(type, name, lock) = \ + QemuLockGuard __attribute__((cleanup(qemu_lock_guard_cleanup))) name = =3D \ + qemu_lock_guard_init(QEMU_LOCK_GUARD_(type, lock, false)) + +#define QEMU_WITH_LOCK(type, name, lock) = \ + for (QEMU_LOCK_GUARD(type, name, lock); = \ + qemu_lock_guard_is_taken(&name); = \ + qemu_lock_guard_unlock(&name)) + +/* Create a QemuLockGuard for a lock that is taken and will be unlocked on + * returning + */ +#define QEMU_ADOPT_LOCK(type, name, lock) = \ + QemuLockGuard __attribute__((cleanup(qemu_lock_guard_cleanup))) name = =3D \ + QEMU_LOCK_GUARD_(type, lock, true) + +#define QEMU_WITH_ADOPTED_LOCK(type, name, lock) = \ + for (QEMU_ADOPT_LOCK(type, name, lock); = \ + qemu_lock_guard_is_taken(&name); = \ + qemu_lock_guard_unlock(&name)) + +/* Take a lock and create a QemuLockGuard for it, asserting that it will + * be locked when returning. + */ +#define QEMU_RETURN_LOCK(type, name, lock) = \ + QemuLockGuard __attribute__((cleanup(qemu_lock_guard_pass))) name =3D = \ + qemu_lock_guard_init(QEMU_LOCK_GUARD_(type, lock, false)) + +/* Create a QemuLockGuard for a lock that is taken and must be locked + * when returning + */ +#define QEMU_TAKEN_LOCK(type, name, lock) = \ + QemuLockGuard __attribute__((cleanup(qemu_lock_guard_pass))) name =3D = \ + QEMU_LOCK_GUARD_(type, lock, true) + +#endif diff --git a/include/qemu/thread.h b/include/qemu/thread.h index 9910f49b3a..4066702d0c 100644 --- a/include/qemu/thread.h +++ b/include/qemu/thread.h @@ -3,6 +3,7 @@ =20 #include "qemu/processor.h" #include "qemu/atomic.h" +#include "qemu/lock-guard.h" =20 typedef struct QemuMutex QemuMutex; typedef struct QemuCond QemuCond; @@ -26,6 +27,9 @@ void qemu_mutex_lock(QemuMutex *mutex); int qemu_mutex_trylock(QemuMutex *mutex); void qemu_mutex_unlock(QemuMutex *mutex); =20 +#define QEMU_LOCK_GUARD_FUNCS_QemuMutex \ + QEMU_INIT_LOCK_GUARD(QemuMutex, qemu_mutex_lock, qemu_mutex_unlock) + /* Prototypes for other functions are in thread-posix.h/thread-win32.h. */ void qemu_rec_mutex_init(QemuRecMutex *mutex); =20 @@ -99,6 +103,9 @@ static inline void qemu_spin_unlock(QemuSpin *spin) __sync_lock_release(&spin->value); } =20 +#define QEMU_LOCK_GUARD_FUNCS_QemuSpin \ + QEMU_INIT_LOCK_GUARD(QemuSpin, qemu_spin_lock, qemu_spin_lock) + struct QemuLockCnt { #ifndef CONFIG_LINUX QemuMutex mutex; diff --git a/util/Makefile.objs b/util/Makefile.objs index 2973b0a323..cb0591f750 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -3,6 +3,7 @@ util-obj-y +=3D bufferiszero.o util-obj-y +=3D lockcnt.o util-obj-y +=3D aiocb.o async.o thread-pool.o qemu-timer.o util-obj-y +=3D main-loop.o iohandler.o +util-obj-y +=3D qemu-thread.o util-obj-$(CONFIG_POSIX) +=3D aio-posix.o util-obj-$(CONFIG_POSIX) +=3D compatfd.o util-obj-$(CONFIG_POSIX) +=3D event_notifier-posix.o diff --git a/util/qemu-thread.c b/util/qemu-thread.c new file mode 100644 index 0000000000..bb06b5f58b --- /dev/null +++ b/util/qemu-thread.c @@ -0,0 +1,17 @@ +/* + * Extern inline functions for QemuLockGuard. + * + * Copyright Red Hat, Inc. 2017 + * + * Author: + * Paolo Bonzini + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + * + */ +#include "qemu/osdep.h" +#include "qemu/thread.h" + +QEMU_EXTERN_INLINE(qemu_lock_guard_cleanup) +QEMU_EXTERN_INLINE(qemu_lock_guard_pass) --=20 2.14.3