qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 07/12] rcu: allow nested calls to rcu_thread_offline


From: Paolo Bonzini
Subject: [Qemu-devel] [PATCH 07/12] rcu: allow nested calls to rcu_thread_offline/rcu_thread_online
Date: Wed, 15 May 2013 17:48:52 +0200

Signed-off-by: Paolo Bonzini <address@hidden>
---
 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.1.4





reply via email to

[Prev in Thread] Current Thread [Next in Thread]