From nobody Fri Nov 14 18:26:43 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=reject dis=none) header.from=rsg.ci.i.u-tokyo.ac.jp Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1761718468843524.2439748690349; Tue, 28 Oct 2025 23:14:28 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vDzR7-0000aD-Fn; Wed, 29 Oct 2025 02:13:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vDzQv-0000Wx-3K for qemu-devel@nongnu.org; Wed, 29 Oct 2025 02:13:23 -0400 Received: from www3579.sakura.ne.jp ([49.212.243.89]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vDzQq-0006q8-EE for qemu-devel@nongnu.org; Wed, 29 Oct 2025 02:13:20 -0400 Received: from h205.csg.ci.i.u-tokyo.ac.jp (h205.csg.ci.i.u-tokyo.ac.jp [133.11.54.205]) (authenticated bits=0) by www3579.sakura.ne.jp (8.16.1/8.16.1) with ESMTPSA id 59T6CsDQ077258 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 29 Oct 2025 15:13:03 +0900 (JST) (envelope-from odaki@rsg.ci.i.u-tokyo.ac.jp) DKIM-Signature: a=rsa-sha256; bh=ObGDg58GkO+t0cgNXUb4j1Xn/JeawhbGtLdiRBdfBHQ=; c=relaxed/relaxed; d=rsg.ci.i.u-tokyo.ac.jp; h=From:Date:Subject:Message-Id:To; s=rs20250326; t=1761718383; v=1; b=pRXAAtGfPA9dzIG3iya0Jxlb6kacZ42OPxetCwRv/uHjiIxEKxx1CEwg0gKjOex3 z9qWHDbPmlFM5lzDtU3v+7b6999VbIu8TtlDPVBDz3BHdvVaDT3W7bPXxLX46CQ4 PIn7EeECtlY9O3f2Y2eIdYszU/NVMQvx08d7OI83krnecKPiq5aU/7omSD0DRQ8e F9MrmUBclHUCvY1xWgyCiwrpVqqrk0sonbOV72SaOAvot741rt+MAO413gGEXgw9 bG/zfrCAGSREHsYgGUb1vJbU1mc9wIiwR43+/uxYGKerLqfJsFOqNpIP5auuT2B6 3/N0s2wqjsLnwt0IXHriOA== From: Akihiko Odaki Date: Wed, 29 Oct 2025 15:12:45 +0900 Subject: [PATCH 1/5] futex: Add qemu_futex_timedwait() MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251029-force_rcu-v1-1-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> References: <20251029-force_rcu-v1-0-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> In-Reply-To: <20251029-force_rcu-v1-0-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> To: qemu-devel@nongnu.org, Dmitry Osipenko Cc: Paolo Bonzini , "Michael S. Tsirkin" , =?utf-8?q?Alex_Benn=C3=A9e?= , Akihiko Odaki X-Mailer: b4 0.15-dev-179e8 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=49.212.243.89; envelope-from=odaki@rsg.ci.i.u-tokyo.ac.jp; helo=www3579.sakura.ne.jp X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1761718470308158500 qemu_futex_timedwait() is equivalent to qemu_futex_wait(), except it has an absolute timeout. Signed-off-by: Akihiko Odaki --- include/qemu/futex.h | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/include/qemu/futex.h b/include/qemu/futex.h index 607613eec835..e5e56603d117 100644 --- a/include/qemu/futex.h +++ b/include/qemu/futex.h @@ -24,6 +24,7 @@ #ifndef QEMU_FUTEX_H #define QEMU_FUTEX_H =20 +#include "qemu/timer.h" #define HAVE_FUTEX =20 #ifdef CONFIG_LINUX @@ -42,18 +43,28 @@ static inline void qemu_futex_wake_single(void *f) qemu_futex(f, FUTEX_WAKE, 1, NULL, NULL, 0); } =20 -static inline void qemu_futex_wait(void *f, unsigned val) +static inline bool qemu_futex_timedwait(void *f, unsigned val, int64_t ns) { - while (qemu_futex(f, FUTEX_WAIT, (int) val, NULL, NULL, 0)) { + struct timespec ts; + uint32_t bitset =3D FUTEX_BITSET_MATCH_ANY; + + ts.tv_sec =3D ns / NANOSECONDS_PER_SECOND; + ts.tv_nsec =3D ns % NANOSECONDS_PER_SECOND; + + while (qemu_futex(f, FUTEX_WAIT_BITSET, (int) val, &ts, NULL, bitset))= { switch (errno) { case EWOULDBLOCK: - return; + return true; case EINTR: break; /* get out of switch and retry */ + case ETIMEDOUT: + return false; default: abort(); } } + + return true; } #elif defined(CONFIG_WIN32) #include @@ -68,12 +79,20 @@ static inline void qemu_futex_wake_single(void *f) WakeByAddressSingle(f); } =20 -static inline void qemu_futex_wait(void *f, unsigned val) +static inline bool qemu_futex_timedwait(void *f, unsigned val, int64_t ns) { - WaitOnAddress(f, &val, sizeof(val), INFINITE); + uint32_t duration =3D MIN((ns - get_clock()) / SCALE_MS, UINT32_MAX); + return WaitOnAddress(f, &val, sizeof(val), duration); } #else #undef HAVE_FUTEX #endif =20 +#ifdef HAVE_FUTEX +static inline void qemu_futex_wait(void *f, unsigned val) +{ + qemu_futex_timedwait(f, val, INT64_MAX); +} +#endif + #endif /* QEMU_FUTEX_H */ --=20 2.51.0 From nobody Fri Nov 14 18:26:43 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=reject dis=none) header.from=rsg.ci.i.u-tokyo.ac.jp Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1761718496812915.5486757858503; Tue, 28 Oct 2025 23:14:56 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vDzRA-0000di-R6; Wed, 29 Oct 2025 02:13:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vDzQw-0000XG-5M for qemu-devel@nongnu.org; Wed, 29 Oct 2025 02:13:23 -0400 Received: from www3579.sakura.ne.jp ([49.212.243.89]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vDzQr-0006qA-0I for qemu-devel@nongnu.org; Wed, 29 Oct 2025 02:13:21 -0400 Received: from h205.csg.ci.i.u-tokyo.ac.jp (h205.csg.ci.i.u-tokyo.ac.jp [133.11.54.205]) (authenticated bits=0) by www3579.sakura.ne.jp (8.16.1/8.16.1) with ESMTPSA id 59T6CsDR077258 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 29 Oct 2025 15:13:03 +0900 (JST) (envelope-from odaki@rsg.ci.i.u-tokyo.ac.jp) DKIM-Signature: a=rsa-sha256; bh=cD58OELSBPZUPtc2Nwde7FP/zTv4pAILKDqDTCL+hEQ=; c=relaxed/relaxed; d=rsg.ci.i.u-tokyo.ac.jp; h=From:Date:Subject:Message-Id:To; s=rs20250326; t=1761718383; v=1; b=WH8j/Nr1gpcF+g0IFGg9aCPaYw1p+a0979QqA3hVHqvPh3hotouucROt2b87wv6U 91K7X5j0Ij2Fi6rTBR4x7W2S/pokkY+iKlEkY2I4MCNDxhuy3yUFIvLJ0VLips8/ BtFxwYCl7463XdK+Dq+zqpsifI22Aay8evXaipiOqRkMvJa5Kz66tUoKU5VBdT5h XmGyqyTmb0e2+En/OudYVKVlTWIh6XZ5bnthbOrdNaFJe5uz3WafwJDHNFfoxW/d 2qWZ7tLdo6q7vKxL9CYPUmCdhSM64corzJnGUegJYgRs0HeHHPE3KMDuDpt5FqIh QmDmjMzv0lRzOSnBptCsoQ== From: Akihiko Odaki Date: Wed, 29 Oct 2025 15:12:46 +0900 Subject: [PATCH 2/5] qemu-thread: Add qemu_event_timedwait() MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251029-force_rcu-v1-2-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> References: <20251029-force_rcu-v1-0-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> In-Reply-To: <20251029-force_rcu-v1-0-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> To: qemu-devel@nongnu.org, Dmitry Osipenko Cc: Paolo Bonzini , "Michael S. Tsirkin" , =?utf-8?q?Alex_Benn=C3=A9e?= , Akihiko Odaki X-Mailer: b4 0.15-dev-179e8 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=49.212.243.89; envelope-from=odaki@rsg.ci.i.u-tokyo.ac.jp; helo=www3579.sakura.ne.jp X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1761718498139158500 qemu_event_timedwait() is equivalent to qemu_event_wait(), except it has a relative timeout. Signed-off-by: Akihiko Odaki --- 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; }; =20 +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); =20 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 =20 ev->value =3D (init ? EV_SET : EV_FREE); @@ -121,15 +129,17 @@ void qemu_event_reset(QemuEvent *ev) #endif } =20 -void qemu_event_wait(QemuEvent *ev) +bool qemu_event_timedwait(QemuEvent *ev, int ms) { assert(ev->initialized); =20 #ifdef HAVE_FUTEX + int64_t deadline =3D 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 =3D 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) !=3D EV_SET) { - pthread_cond_wait(&ev->cond, &ev->lock); + failed =3D 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(); } =20 -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 +=3D (ms % 1000) * 1000000; --=20 2.51.0 From nobody Fri Nov 14 18:26:43 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=reject dis=none) header.from=rsg.ci.i.u-tokyo.ac.jp Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1761718496817622.7788916798543; Tue, 28 Oct 2025 23:14:56 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vDzRC-0000fE-EL; Wed, 29 Oct 2025 02:13:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vDzQz-0000Yv-ND for qemu-devel@nongnu.org; Wed, 29 Oct 2025 02:13:26 -0400 Received: from www3579.sakura.ne.jp ([49.212.243.89]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vDzQr-0006q6-D3 for qemu-devel@nongnu.org; Wed, 29 Oct 2025 02:13:24 -0400 Received: from h205.csg.ci.i.u-tokyo.ac.jp (h205.csg.ci.i.u-tokyo.ac.jp [133.11.54.205]) (authenticated bits=0) by www3579.sakura.ne.jp (8.16.1/8.16.1) with ESMTPSA id 59T6CsDS077258 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 29 Oct 2025 15:13:03 +0900 (JST) (envelope-from odaki@rsg.ci.i.u-tokyo.ac.jp) DKIM-Signature: a=rsa-sha256; bh=Y0z8Leh5RjHBxYsvXtHQahS9nXSybZI1c+I/pM8VVN4=; c=relaxed/relaxed; d=rsg.ci.i.u-tokyo.ac.jp; h=From:Date:Subject:Message-Id:To; s=rs20250326; t=1761718383; v=1; b=ED43PdhD7lt0TAm3zaamAXjOokX9+OLX8T3SFUeXEuEuavw8V/M/bk9w3jqOLKyN B/YNjYg+c+OV5Iz80kWfLTup2LaNZQTl1UdDUuEaVMwUCoe8zXCo2SNiPGvmFf0j rMJH/EdiozF7+HuI4NhxoUS7slAWhtfQmAozj50aTo8VlvEQy6+A+OzQSiwCLErA iQD45IZS6U2o60sQOWK1KvOnvdzn5IjvPUip2WS8qSufmmF/pDfg6Aq6DKtpYZfb gVa4nNMrq176GMp3F+NE52kUMvxsD7c9ECQcy3gRgon2WhpadhLBdZoO+p7Y3UiA PkXUkCHTHFh8TOKolJ/xAw== From: Akihiko Odaki Date: Wed, 29 Oct 2025 15:12:47 +0900 Subject: [PATCH 3/5] rcu: Use call_rcu() in synchronize_rcu() MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251029-force_rcu-v1-3-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> References: <20251029-force_rcu-v1-0-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> In-Reply-To: <20251029-force_rcu-v1-0-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> To: qemu-devel@nongnu.org, Dmitry Osipenko Cc: Paolo Bonzini , "Michael S. Tsirkin" , =?utf-8?q?Alex_Benn=C3=A9e?= , Akihiko Odaki X-Mailer: b4 0.15-dev-179e8 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=49.212.243.89; envelope-from=odaki@rsg.ci.i.u-tokyo.ac.jp; helo=www3579.sakura.ne.jp X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1761718497746154100 Previously, synchronize_rcu() was a single-threaded implementation that is protected with a mutex. It was used only in the RCU thread and tests, and real users instead use call_rcu(), which relies on the RCU thread. The usage of synchronize_rcu() in tests did not accurately represent real use cases because it caused locking with the mutex, which never happened in real use cases, and it did not exercise the logic in the RCU thread. Add a new implementation of synchronize_rcu() which uses call_rcu() to represent real use cases in tests. The old synchronize_rcu() is now renamed to enter_qs() and only used in the RCU thread, making the mutex unnecessary. Signed-off-by: Akihiko Odaki --- util/rcu.c | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/util/rcu.c b/util/rcu.c index acac9446ea98..3c4af9d213c8 100644 --- a/util/rcu.c +++ b/util/rcu.c @@ -38,7 +38,7 @@ =20 /* * Global grace period counter. Bit 0 is always one in rcu_gp_ctr. - * Bits 1 and above are defined in synchronize_rcu. + * Bits 1 and above are defined in enter_qs(). */ #define RCU_GP_LOCKED (1UL << 0) #define RCU_GP_CTR (1UL << 1) @@ -52,7 +52,6 @@ QemuEvent rcu_gp_event; static int in_drain_call_rcu; static int rcu_call_count; static QemuMutex rcu_registry_lock; -static QemuMutex rcu_sync_lock; =20 /* * Check whether a quiescent state was crossed between the beginning of @@ -111,7 +110,7 @@ static void wait_for_readers(void) * * If this is the last iteration, this barrier also prevents * frees from seeping upwards, and orders the two wait phases - * on architectures with 32-bit longs; see synchronize_rcu(). + * on architectures with 32-bit longs; see enter_qs(). */ smp_mb_global(); =20 @@ -137,9 +136,9 @@ static void wait_for_readers(void) * wait too much time. * * rcu_register_thread() may add nodes to ®istry; it will not - * wake up synchronize_rcu, but that is okay because at least anot= her + * wake up enter_qs(), but that is okay because at least another * thread must exit its RCU read-side critical section before - * synchronize_rcu is done. The next iteration of the loop will + * enter_qs() is done. The next iteration of the loop will * move the new thread's rcu_reader from ®istry to &qsreaders, * because rcu_gp_ongoing() will return false. * @@ -171,10 +170,8 @@ static void wait_for_readers(void) QLIST_SWAP(®istry, &qsreaders, node); } =20 -void synchronize_rcu(void) +static void enter_qs(void) { - QEMU_LOCK_GUARD(&rcu_sync_lock); - /* Write RCU-protected pointers before reading p_rcu_reader->ctr. * Pairs with smp_mb_placeholder() in rcu_read_lock(). * @@ -289,7 +286,7 @@ static void *call_rcu_thread(void *opaque) =20 /* * Fetch rcu_call_count now, we only must process elements that we= re - * added before synchronize_rcu() starts. + * added before enter_qs() starts. */ for (;;) { qemu_event_reset(&rcu_call_ready_event); @@ -304,7 +301,7 @@ static void *call_rcu_thread(void *opaque) qemu_event_wait(&rcu_call_ready_event); } =20 - synchronize_rcu(); + enter_qs(); qatomic_sub(&rcu_call_count, n); bql_lock(); while (n > 0) { @@ -337,15 +334,24 @@ void call_rcu1(struct rcu_head *node, void (*func)(st= ruct rcu_head *node)) } =20 =20 -struct rcu_drain { +typedef struct Sync { struct rcu_head rcu; - QemuEvent drain_complete_event; -}; + QemuEvent complete_event; +} Sync; =20 -static void drain_rcu_callback(struct rcu_head *node) +static void sync_rcu_callback(Sync *sync) { - struct rcu_drain *event =3D (struct rcu_drain *)node; - qemu_event_set(&event->drain_complete_event); + qemu_event_set(&sync->complete_event); +} + +void synchronize_rcu(void) +{ + Sync sync; + + qemu_event_init(&sync.complete_event, false); + call_rcu(&sync, sync_rcu_callback, rcu); + qemu_event_wait(&sync.complete_event); + qemu_event_destroy(&sync.complete_event); } =20 /* @@ -359,11 +365,11 @@ static void drain_rcu_callback(struct rcu_head *node) =20 void drain_call_rcu(void) { - struct rcu_drain rcu_drain; + Sync sync; bool locked =3D bql_locked(); =20 - memset(&rcu_drain, 0, sizeof(struct rcu_drain)); - qemu_event_init(&rcu_drain.drain_complete_event, false); + memset(&sync, 0, sizeof(sync)); + qemu_event_init(&sync.complete_event, false); =20 if (locked) { bql_unlock(); @@ -383,8 +389,8 @@ void drain_call_rcu(void) */ =20 qatomic_inc(&in_drain_call_rcu); - call_rcu1(&rcu_drain.rcu, drain_rcu_callback); - qemu_event_wait(&rcu_drain.drain_complete_event); + call_rcu(&sync, sync_rcu_callback, rcu); + qemu_event_wait(&sync.complete_event); qatomic_dec(&in_drain_call_rcu); =20 if (locked) { @@ -427,7 +433,6 @@ static void rcu_init_complete(void) QemuThread thread; =20 qemu_mutex_init(&rcu_registry_lock); - qemu_mutex_init(&rcu_sync_lock); qemu_event_init(&rcu_gp_event, true); =20 qemu_event_init(&rcu_call_ready_event, false); @@ -460,7 +465,6 @@ static void rcu_init_lock(void) return; } =20 - qemu_mutex_lock(&rcu_sync_lock); qemu_mutex_lock(&rcu_registry_lock); } =20 @@ -471,7 +475,6 @@ static void rcu_init_unlock(void) } =20 qemu_mutex_unlock(&rcu_registry_lock); - qemu_mutex_unlock(&rcu_sync_lock); } =20 static void rcu_init_child(void) --=20 2.51.0 From nobody Fri Nov 14 18:26:43 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=reject dis=none) header.from=rsg.ci.i.u-tokyo.ac.jp Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1761718454789896.3394713517956; Tue, 28 Oct 2025 23:14:14 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vDzR7-0000cj-PD; Wed, 29 Oct 2025 02:13:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vDzQx-0000XX-2m for qemu-devel@nongnu.org; Wed, 29 Oct 2025 02:13:23 -0400 Received: from www3579.sakura.ne.jp ([49.212.243.89]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vDzQq-0006qS-LB for qemu-devel@nongnu.org; Wed, 29 Oct 2025 02:13:22 -0400 Received: from h205.csg.ci.i.u-tokyo.ac.jp (h205.csg.ci.i.u-tokyo.ac.jp [133.11.54.205]) (authenticated bits=0) by www3579.sakura.ne.jp (8.16.1/8.16.1) with ESMTPSA id 59T6CsDT077258 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 29 Oct 2025 15:13:03 +0900 (JST) (envelope-from odaki@rsg.ci.i.u-tokyo.ac.jp) DKIM-Signature: a=rsa-sha256; bh=bGlduYgcucjSk4FKxFx6sIJI3Wl9Ysaw1yBUbvVkCek=; c=relaxed/relaxed; d=rsg.ci.i.u-tokyo.ac.jp; h=From:Date:Subject:Message-Id:To; s=rs20250326; t=1761718383; v=1; b=wD+pPedr9AV6xpvmNW1kr+zvTWhBqUCjtasQOkMRlA4L3G7iZCnt+Wfi0Jd+RJ6G EghrMqgZ+0hlARmH5tQuYXpP1klnBK237THdIosYS8hcubnYQPfseRb61Vfsb6Vx ImjCIDGJH/ovUz0GsgQbjoCeNaJqawGR5Eq/ZHOEKgY59VC5+dXaqTYoqvdW49jU dYnGOQTj6/l2qY+jXPDunox4dpxVbrguNs7nEIrACRDVGRK4q76uk1W+rAuowlzh Y3EB1szSXi8+8XZBNXn0kcu/ZF4MqvDnBzZvEVCwnTzCirviGy+/ukgiEyBJeieV fRkKCK3IprwRGknvJ2BriA== From: Akihiko Odaki Date: Wed, 29 Oct 2025 15:12:48 +0900 Subject: [PATCH 4/5] rcu: Wake the RCU thread when draining MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251029-force_rcu-v1-4-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> References: <20251029-force_rcu-v1-0-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> In-Reply-To: <20251029-force_rcu-v1-0-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> To: qemu-devel@nongnu.org, Dmitry Osipenko Cc: Paolo Bonzini , "Michael S. Tsirkin" , =?utf-8?q?Alex_Benn=C3=A9e?= , Akihiko Odaki X-Mailer: b4 0.15-dev-179e8 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=49.212.243.89; envelope-from=odaki@rsg.ci.i.u-tokyo.ac.jp; helo=www3579.sakura.ne.jp X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1761718457183154100 drain_call_rcu() triggers the force quiescent state, but it can be delayed if the RCU thread is sleeping. Ensure the force quiescent state is immediately triggered by waking the RCU thread up. The logic to trigger the force quiescent state is decoupled as force_rcu() so that it can be used independently. Signed-off-by: Akihiko Odaki --- include/qemu/rcu.h | 1 + util/rcu.c | 106 ++++++++++++++++++++++++++++++++-----------------= ---- 2 files changed, 65 insertions(+), 42 deletions(-) diff --git a/include/qemu/rcu.h b/include/qemu/rcu.h index 020dbe4d8b77..d6aa4e5854d3 100644 --- a/include/qemu/rcu.h +++ b/include/qemu/rcu.h @@ -118,6 +118,7 @@ static inline void rcu_read_unlock(void) } } =20 +void force_rcu(void); void synchronize_rcu(void); =20 /* diff --git a/util/rcu.c b/util/rcu.c index 3c4af9d213c8..85f9333f5dff 100644 --- a/util/rcu.c +++ b/util/rcu.c @@ -49,10 +49,13 @@ unsigned long rcu_gp_ctr =3D RCU_GP_LOCKED; =20 QemuEvent rcu_gp_event; -static int in_drain_call_rcu; +static bool forced; static int rcu_call_count; static QemuMutex rcu_registry_lock; =20 +/* Set when the forced variable is set or rcu_call_count becomes non-zero.= */ +static QemuEvent sync_event; + /* * Check whether a quiescent state was crossed between the beginning of * update_counter_and_wait and now. @@ -74,36 +77,21 @@ QEMU_DEFINE_CO_TLS(struct rcu_reader_data, rcu_reader) typedef QLIST_HEAD(, rcu_reader_data) ThreadList; static ThreadList registry =3D QLIST_HEAD_INITIALIZER(registry); =20 +void force_rcu(void) +{ + qatomic_set(&forced, true); + qemu_event_set(&sync_event); +} + /* Wait for previous parity/grace period to be empty of readers. */ -static void wait_for_readers(void) +static void wait_for_readers(bool sleep) { ThreadList qsreaders =3D QLIST_HEAD_INITIALIZER(qsreaders); struct rcu_reader_data *index, *tmp; - int sleeps =3D 0; - bool forced =3D false; + int sleeps =3D sleep ? 5 : 0; + bool waiting =3D false; =20 for (;;) { - /* - * Force the grace period to end and wait for it if any of the - * following heuristical conditions are satisfied: - * - A decent number of callbacks piled up. - * - It timed out. - * - It is in a drain_call_rcu() call. - * - * Otherwise, periodically poll the grace period, hoping it ends - * promptly. - */ - if (!forced && - (qatomic_read(&rcu_call_count) >=3D RCU_CALL_MIN_SIZE || - sleeps >=3D 5 || qatomic_read(&in_drain_call_rcu))) { - forced =3D true; - - QLIST_FOREACH(index, ®istry, node) { - notifier_list_notify(&index->force_rcu, NULL); - qatomic_set(&index->waiting, true); - } - } - /* Here, order the stores to index->waiting before the loads of * index->ctr. Pairs with smp_mb_placeholder() in rcu_read_unlock= (), * ensuring that the loads of index->ctr are sequentially consiste= nt. @@ -150,7 +138,8 @@ static void wait_for_readers(void) */ qemu_mutex_unlock(&rcu_registry_lock); =20 - if (forced) { + if (waiting) { + /* Wait for the forced quiescent state. */ qemu_event_wait(&rcu_gp_event); =20 /* @@ -158,9 +147,25 @@ static void wait_for_readers(void) * while we walk the list. */ qemu_event_reset(&rcu_gp_event); + } else if (qatomic_read(&rcu_call_count) >=3D RCU_CALL_MIN_SIZE || + !sleeps || qemu_event_timedwait(&sync_event, 10)) { + /* + * Now one of the following heuristical conditions is satisfie= d: + * - A decent number of callbacks piled up. + * - It timed out. + * - force_rcu() was called. + * + * Force a quiescent state. + */ + waiting =3D true; + + QLIST_FOREACH(index, ®istry, node) { + notifier_list_notify(&index->force_rcu, NULL); + qatomic_set(&index->waiting, true); + } } else { - g_usleep(10000); - sleeps++; + /* Try again. */ + sleeps--; } =20 qemu_mutex_lock(&rcu_registry_lock); @@ -170,7 +175,7 @@ static void wait_for_readers(void) QLIST_SWAP(®istry, &qsreaders, node); } =20 -static void enter_qs(void) +static void enter_qs(bool sleep) { /* Write RCU-protected pointers before reading p_rcu_reader->ctr. * Pairs with smp_mb_placeholder() in rcu_read_lock(). @@ -189,14 +194,14 @@ static void enter_qs(void) * Switch parity: 0 -> 1, 1 -> 0. */ qatomic_set(&rcu_gp_ctr, rcu_gp_ctr ^ RCU_GP_CTR); - wait_for_readers(); + wait_for_readers(sleep); qatomic_set(&rcu_gp_ctr, rcu_gp_ctr ^ RCU_GP_CTR); } else { /* Increment current grace period. */ qatomic_set(&rcu_gp_ctr, rcu_gp_ctr + RCU_GP_CTR); } =20 - wait_for_readers(); + wait_for_readers(sleep); } } =20 @@ -205,7 +210,6 @@ static void enter_qs(void) */ static struct rcu_head dummy; static struct rcu_head *head =3D &dummy, **tail =3D &dummy.next; -static QemuEvent rcu_call_ready_event; =20 static void enqueue(struct rcu_head *node) { @@ -282,6 +286,7 @@ static void *call_rcu_thread(void *opaque) rcu_register_thread(); =20 for (;;) { + bool sleep =3D true; int n; =20 /* @@ -289,7 +294,7 @@ static void *call_rcu_thread(void *opaque) * added before enter_qs() starts. */ for (;;) { - qemu_event_reset(&rcu_call_ready_event); + qemu_event_reset(&sync_event); n =3D qatomic_read(&rcu_call_count); if (n) { break; @@ -298,20 +303,36 @@ static void *call_rcu_thread(void *opaque) #if defined(CONFIG_MALLOC_TRIM) malloc_trim(4 * 1024 * 1024); #endif - qemu_event_wait(&rcu_call_ready_event); + qemu_event_wait(&sync_event); + } + + /* + * Ensure that an event for a rcu_call_count change will not inter= rupt + * wait_for_readers(). + */ + qemu_event_reset(&sync_event); + + /* + * Ensure that the forced variable has not been set after fetching + * rcu_call_count; otherwise we may get confused by a force quiesc= ent + * state request for an element later than n. + */ + while (qatomic_xchg(&forced, false)) { + sleep =3D false; + n =3D qatomic_read(&rcu_call_count); } =20 - enter_qs(); + enter_qs(sleep); qatomic_sub(&rcu_call_count, n); bql_lock(); while (n > 0) { node =3D try_dequeue(); while (!node) { bql_unlock(); - qemu_event_reset(&rcu_call_ready_event); + qemu_event_reset(&sync_event); node =3D try_dequeue(); if (!node) { - qemu_event_wait(&rcu_call_ready_event); + qemu_event_wait(&sync_event); node =3D try_dequeue(); } bql_lock(); @@ -329,8 +350,10 @@ void call_rcu1(struct rcu_head *node, void (*func)(str= uct rcu_head *node)) { node->func =3D func; enqueue(node); - qatomic_inc(&rcu_call_count); - qemu_event_set(&rcu_call_ready_event); + + if (!qatomic_fetch_inc(&rcu_call_count)) { + qemu_event_set(&sync_event); + } } =20 =20 @@ -388,10 +411,9 @@ void drain_call_rcu(void) * assumed. */ =20 - qatomic_inc(&in_drain_call_rcu); call_rcu(&sync, sync_rcu_callback, rcu); + force_rcu(); qemu_event_wait(&sync.complete_event); - qatomic_dec(&in_drain_call_rcu); =20 if (locked) { bql_lock(); @@ -435,7 +457,7 @@ static void rcu_init_complete(void) qemu_mutex_init(&rcu_registry_lock); qemu_event_init(&rcu_gp_event, true); =20 - qemu_event_init(&rcu_call_ready_event, false); + qemu_event_init(&sync_event, false); =20 /* The caller is assumed to have BQL, so the call_rcu thread * must have been quiescent even after forking, just recreate it. --=20 2.51.0 From nobody Fri Nov 14 18:26:43 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=reject dis=none) header.from=rsg.ci.i.u-tokyo.ac.jp Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1761718453412356.77596805222583; Tue, 28 Oct 2025 23:14:13 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vDzR9-0000eE-ME; Wed, 29 Oct 2025 02:13:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vDzQz-0000Yw-Nw for qemu-devel@nongnu.org; Wed, 29 Oct 2025 02:13:26 -0400 Received: from www3579.sakura.ne.jp ([49.212.243.89]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vDzQr-0006q7-0J for qemu-devel@nongnu.org; Wed, 29 Oct 2025 02:13:24 -0400 Received: from h205.csg.ci.i.u-tokyo.ac.jp (h205.csg.ci.i.u-tokyo.ac.jp [133.11.54.205]) (authenticated bits=0) by www3579.sakura.ne.jp (8.16.1/8.16.1) with ESMTPSA id 59T6CsDU077258 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 29 Oct 2025 15:13:03 +0900 (JST) (envelope-from odaki@rsg.ci.i.u-tokyo.ac.jp) DKIM-Signature: a=rsa-sha256; bh=tIt956zL/G9YcAqkI1Zxo7iDKVwcFbMfxHwZMsjOBfY=; c=relaxed/relaxed; d=rsg.ci.i.u-tokyo.ac.jp; h=From:Date:Subject:Message-Id:To; s=rs20250326; t=1761718383; v=1; b=wXdzSBFwJZ9k/fvodBj2R16u5W/FqFDAcOeVdJ8g5TxVrSGI9rvyFdtrez2kuPHL 2osp27TuHkpoEBTnZlEIoMlNbhhRlJMLt43/t7TSgZv+z+k4f5Xnnr8mmZhe3JJT 1JBRYevZYd/iio6aObtJOwe0fNpx943iMlWitJvTecpKNRzNINzRi0krRqL8/EUL VQAHXttCZWCQjXB0J7fUrwLjWIUywTTqQnhaQJN4Gw5GMkIooo+l5O2cNOkvQ8hQ /CmQmTe0ioAad0EqgQZGXPMvr1+8rtxPq84JZfTpYL/J3zblRinbkrV4v6rw1s+C aqyK7kVa4RiWIqeoDrSy+w== From: Akihiko Odaki Date: Wed, 29 Oct 2025 15:12:49 +0900 Subject: [PATCH 5/5] virtio-gpu: Force RCU when unmapping blob MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251029-force_rcu-v1-5-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> References: <20251029-force_rcu-v1-0-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> In-Reply-To: <20251029-force_rcu-v1-0-bf860a6277a6@rsg.ci.i.u-tokyo.ac.jp> To: qemu-devel@nongnu.org, Dmitry Osipenko Cc: Paolo Bonzini , "Michael S. Tsirkin" , =?utf-8?q?Alex_Benn=C3=A9e?= , Akihiko Odaki X-Mailer: b4 0.15-dev-179e8 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=49.212.243.89; envelope-from=odaki@rsg.ci.i.u-tokyo.ac.jp; helo=www3579.sakura.ne.jp X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1761718455449154100 Unmapping a blob changes the memory map, which is protected with RCU. RCU is designed to minimize the read-side overhead at the cost of reclamation delay. While this design usually makes sense, it is problematic when unmapping a blob because the operation blocks all virtio-gpu commands and causes perceivable disruption. Minimize such the disruption with force_rcu(), which minimizes the reclamation delay at the cost of a read-side overhead. Signed-off-by: Akihiko Odaki Tested-by: Dmitry Osipenko --- hw/display/virtio-gpu-virgl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c index 07f6355ad62e..71cde671c193 100644 --- a/hw/display/virtio-gpu-virgl.c +++ b/hw/display/virtio-gpu-virgl.c @@ -187,6 +187,7 @@ virtio_gpu_virgl_unmap_resource_blob(VirtIOGPU *g, memory_region_set_enabled(mr, false); memory_region_del_subregion(&b->hostmem, mr); object_unparent(OBJECT(mr)); + force_rcu(); } =20 return 0; --=20 2.51.0