From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60645) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UsdOG-0005w0-LO for qemu-devel@nongnu.org; Fri, 28 Jun 2013 14:27:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UsdOD-0000OU-Ko for qemu-devel@nongnu.org; Fri, 28 Jun 2013 14:27:24 -0400 Received: from mail-ea0-x232.google.com ([2a00:1450:4013:c01::232]:34954) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UsdOD-0000OM-Dm for qemu-devel@nongnu.org; Fri, 28 Jun 2013 14:27:21 -0400 Received: by mail-ea0-f178.google.com with SMTP id l15so1183117eak.23 for ; Fri, 28 Jun 2013 11:27:20 -0700 (PDT) Received: from playground.lan (net-37-116-217-184.cust.dsl.vodafone.it. [37.116.217.184]) by mx.google.com with ESMTPSA id o5sm12035344eef.5.2013.06.28.11.27.18 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 28 Jun 2013 11:27:19 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Fri, 28 Jun 2013 20:26:31 +0200 Message-Id: <1372444009-11544-13-git-send-email-pbonzini@redhat.com> In-Reply-To: <1372444009-11544-1-git-send-email-pbonzini@redhat.com> References: <1372444009-11544-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 12/30] rcu: allow nested calls to rcu_thread_offline/rcu_thread_online List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Signed-off-by: Paolo Bonzini --- docs/rcu.txt | 5 +++++ include/qemu/rcu.h | 21 +++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/docs/rcu.txt b/docs/rcu.txt index ca1c099..a3510b9 100644 --- a/docs/rcu.txt +++ b/docs/rcu.txt @@ -187,6 +187,11 @@ Marking quiescent states is done with the following three APIs: thread. +rcu_thread_offline() and rcu_thread_online() can be nested. The end of +the extended quiescent state will coincide with the outermost call to +rcu_thread_online(). + + The following APIs can be used to use RCU in a thread that is not created with qemu_thread_create(): diff --git a/include/qemu/rcu.h b/include/qemu/rcu.h index 1ed70bb..eff6d1e 100644 --- a/include/qemu/rcu.h +++ b/include/qemu/rcu.h @@ -78,6 +78,9 @@ struct rcu_reader_data { unsigned long ctr; bool waiting; + /* Data used by reader only */ + unsigned offline; + /* Data used for registry, protected by rcu_gp_lock */ QLIST_ENTRY(rcu_reader_data) node; }; @@ -100,9 +103,14 @@ static inline void rcu_read_unlock(void) static inline void rcu_quiescent_state(void) { struct rcu_reader_data *p_rcu_reader = tls_get_rcu_reader(); + unsigned ctr; + + if (p_rcu_reader->offline > 0) { + return; + } /* Reuses smp_rmb() in the last rcu_read_unlock(). */ - unsigned ctr = atomic_read(&rcu_gp_ctr); + ctr = atomic_read(&rcu_gp_ctr); atomic_xchg(&p_rcu_reader->ctr, ctr); if (atomic_read(&p_rcu_reader->waiting)) { atomic_set(&p_rcu_reader->waiting, false); @@ -114,6 +122,10 @@ static inline void rcu_thread_offline(void) { struct rcu_reader_data *p_rcu_reader = tls_get_rcu_reader(); + if (p_rcu_reader->offline++ > 0) { + return; + } + atomic_xchg(&p_rcu_reader->ctr, 0); if (atomic_read(&p_rcu_reader->waiting)) { atomic_set(&p_rcu_reader->waiting, false); @@ -123,7 +135,12 @@ static inline void rcu_thread_offline(void) static inline void rcu_thread_online(void) { - rcu_quiescent_state(); + struct rcu_reader_data *p_rcu_reader = tls_get_rcu_reader(); + + assert(p_rcu_reader->offline != 0); + if (--p_rcu_reader->offline == 0) { + rcu_quiescent_state(); + } } extern void synchronize_rcu(void); -- 1.8.1.4