From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55715) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V9dMR-0007Qb-0d for qemu-devel@nongnu.org; Wed, 14 Aug 2013 11:51:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V9dMK-0007ud-AQ for qemu-devel@nongnu.org; Wed, 14 Aug 2013 11:51:46 -0400 Received: from mail-qa0-f51.google.com ([209.85.216.51]:47345) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V9dMK-0007uY-6B for qemu-devel@nongnu.org; Wed, 14 Aug 2013 11:51:40 -0400 Received: by mail-qa0-f51.google.com with SMTP id f11so1148175qae.3 for ; Wed, 14 Aug 2013 08:51:39 -0700 (PDT) From: Mike Day Date: Wed, 14 Aug 2013 11:50:43 -0400 Message-Id: <1376495450-5133-8-git-send-email-ncmike@ncultra.org> In-Reply-To: <1376495450-5133-1-git-send-email-ncmike@ncultra.org> References: <1376495450-5133-1-git-send-email-ncmike@ncultra.org> Subject: [Qemu-devel] [RFC PATCH 07/14] 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 Cc: Paolo Bonzini From: Paolo Bonzini Signed-off-by: Paolo Bonzini Reviewed-by: Mike Day --- 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 d7c4f0b..4e7cde3 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 e43b912..3a55045 100644 --- a/include/qemu/rcu.h +++ b/include/qemu/rcu.h @@ -77,6 +77,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; }; @@ -127,9 +130,14 @@ static inline void rcu_read_unlock(void) static inline void rcu_quiescent_state(void) { struct rcu_reader_data *p_rcu_reader = 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); @@ -141,6 +149,10 @@ static inline void rcu_thread_offline(void) { struct rcu_reader_data *p_rcu_reader = 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); @@ -150,7 +162,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 = 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.3.1