qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 2/3] rcu: use rcu_{dereference, assign_pointer} inst


From: Emilio G. Cota
Subject: [Qemu-devel] [PATCH 2/3] rcu: use rcu_{dereference, assign_pointer} instead of atomic_rcu_{read, set}
Date: Tue, 3 Feb 2015 17:08:18 -0500

This matches the semantics of liburcu.

Signed-off-by: Emilio G. Cota <address@hidden>
---
 docs/rcu.txt          | 33 +++++++++++++++------------------
 include/qemu/atomic.h | 35 ++++++++++++++++++-----------------
 memory.c              |  6 +++---
 tests/rcutorture.c    |  4 ++--
 4 files changed, 38 insertions(+), 40 deletions(-)

diff --git a/docs/rcu.txt b/docs/rcu.txt
index 575f563..154b18a 100644
--- a/docs/rcu.txt
+++ b/docs/rcu.txt
@@ -127,13 +127,13 @@ The core RCU API is small:
 
             call_rcu_first_elem(foo_reclaim, g_free, rcu);
 
-     typeof(*p) atomic_rcu_read(p);
+     typeof(p) rcu_dereference(p);
 
-        atomic_rcu_read() is similar to atomic_mb_read(), but it makes
+        rcu_dereference() is similar to atomic_mb_read(), but it makes
         some assumptions on the code that calls it.  This allows a more
         optimized implementation.
 
-        atomic_rcu_read assumes that whenever a single RCU critical
+        rcu_dereference assumes that whenever a single RCU critical
         section reads multiple shared data, these reads are either
         data-dependent or need no ordering.  This is almost always the
         case when using RCU, because read-side critical sections typically
@@ -141,7 +141,7 @@ The core RCU API is small:
         every update) until reaching a data structure of interest,
         and then read from there.
 
-        RCU read-side critical sections must use atomic_rcu_read() to
+        RCU read-side critical sections must use rcu_dereference() to
         read data, unless concurrent writes are presented by another
         synchronization mechanism.
 
@@ -149,18 +149,18 @@ The core RCU API is small:
         data structure in a single direction, opposite to the direction
         in which the updater initializes it.
 
-     void atomic_rcu_set(p, typeof(*p) v);
+     void rcu_assign_pointer(p, typeof(p) v);
 
-        atomic_rcu_set() is also similar to atomic_mb_set(), and it also
+        rcu_assign_pointer() is also similar to atomic_mb_set(), and it also
         makes assumptions on the code that calls it in order to allow a more
         optimized implementation.
 
-        In particular, atomic_rcu_set() suffices for synchronization
+        In particular, rcu_assign_pointer() suffices for synchronization
         with readers, if the updater never mutates a field within a
         data item that is already accessible to readers.  This is the
         case when initializing a new copy of the RCU-protected data
         structure; just ensure that initialization of *p is carried out
-        before atomic_rcu_set() makes the data item visible to readers.
+        before rcu_assign_pointer() makes the data item visible to readers.
         If this rule is observed, writes will happen in the opposite
         order as reads in the RCU read-side critical sections (or if
         there is just one update), and there will be no need for other
@@ -193,9 +193,6 @@ DIFFERENCES WITH LINUX
   programming; not allowing this would prevent upgrading an RCU read-side
   critical section to become an updater.
 
-- atomic_rcu_read and atomic_rcu_set replace rcu_dereference and
-  rcu_assign_pointer.  They take a _pointer_ to the variable being accessed.
-
 - call_rcu_first_elem is a macro that has an extra argument (the name of the
   first field in the struct, which must be a struct rcu_head), and expects the
   type of the callback's argument to be the type of the first argument.
@@ -237,7 +234,7 @@ may be used as a restricted reference-counting mechanism.  
For example,
 consider the following code fragment:
 
     rcu_read_lock();
-    p = atomic_rcu_read(&foo);
+    p = rcu_dereference(foo);
     /* do something with p. */
     rcu_read_unlock();
 
@@ -248,7 +245,7 @@ The write side looks simply like this (with appropriate 
locking):
 
     qemu_mutex_lock(&foo_mutex);
     old = foo;
-    atomic_rcu_set(&foo, new);
+    rcu_assign_pointer(foo, new);
     qemu_mutex_unlock(&foo_mutex);
     synchronize_rcu();
     free(old);
@@ -257,7 +254,7 @@ If the processing cannot be done purely within the critical 
section, it
 is possible to combine this idiom with a "real" reference count:
 
     rcu_read_lock();
-    p = atomic_rcu_read(&foo);
+    p = rcu_dereference(foo);
     foo_ref(p);
     rcu_read_unlock();
     /* do something with p. */
@@ -267,7 +264,7 @@ The write side can be like this:
 
     qemu_mutex_lock(&foo_mutex);
     old = foo;
-    atomic_rcu_set(&foo, new);
+    rcu_assign_pointer(foo, new);
     qemu_mutex_unlock(&foo_mutex);
     synchronize_rcu();
     foo_unref(old);
@@ -276,7 +273,7 @@ or with call_rcu:
 
     qemu_mutex_lock(&foo_mutex);
     old = foo;
-    atomic_rcu_set(&foo, new);
+    rcu_assign_pointer(foo, new);
     qemu_mutex_unlock(&foo_mutex);
     call_rcu(foo_unref, old, rcu);
 
@@ -355,7 +352,7 @@ Instead, we store the size of the array with the array 
itself:
 
     read side:
         rcu_read_lock();
-        struct arr *array = atomic_rcu_read(&global_array);
+        struct arr *array = rcu_dereference(global_array);
         x = i < array->size ? array->data[i] : -1;
         rcu_read_unlock();
         return x;
@@ -372,7 +369,7 @@ Instead, we store the size of the array with the array 
itself:
 
             /* Removal phase.  */
             old_array = global_array;
-            atomic_rcu_set(&new_array->data, new_array);
+            rcu_assign_pointer(new_array->data, new_array);
             synchronize_rcu();
 
             /* Reclamation phase.  */
diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h
index 98e05ca..4795e28 100644
--- a/include/qemu/atomic.h
+++ b/include/qemu/atomic.h
@@ -130,7 +130,7 @@
 #endif
 
 /**
- * atomic_rcu_read - reads a RCU-protected pointer to a local variable
+ * rcu_dereference - reads a RCU-protected pointer to a local variable
  * into a RCU read-side critical section. The pointer can later be safely
  * dereferenced within the critical section.
  *
@@ -140,25 +140,26 @@
  * Inserts memory barriers on architectures that require them (currently only
  * Alpha) and documents which pointers are protected by RCU.
  *
- * Unless the __ATOMIC_CONSUME memory order is available, atomic_rcu_read also
+ * Unless the __ATOMIC_CONSUME memory order is available, rcu_dereference also
  * includes a compiler barrier to ensure that value-speculative optimizations
  * (e.g. VSS: Value Speculation Scheduling) does not perform the data read
  * before the pointer read by speculating the value of the pointer.  On new
  * enough compilers, atomic_load takes care of such concern about
  * dependency-breaking optimizations.
  *
- * Should match atomic_rcu_set(), atomic_xchg(), atomic_cmpxchg().
+ * Should match rcu_assign_pointer(), atomic_xchg(), atomic_cmpxchg().
  */
-#ifndef atomic_rcu_read
+#ifndef rcu_dereference
+
 #ifdef __ATOMIC_CONSUME
-#define atomic_rcu_read(ptr)    ({                \
-    typeof(*ptr) _val;                            \
-     __atomic_load(ptr, &_val, __ATOMIC_CONSUME); \
+#define rcu_dereference(ptr)    ({                \
+    typeof(ptr) _val;                             \
+     __atomic_load(&ptr, &_val, __ATOMIC_CONSUME);\
     _val;                                         \
 })
 #else
-#define atomic_rcu_read(ptr)    ({                \
-    typeof(*ptr) _val = atomic_read(ptr);         \
+#define rcu_dereference(ptr)    ({                \
+    typeof(ptr) _val = atomic_read(&ptr);         \
     smp_read_barrier_depends();                   \
     _val;                                         \
 })
@@ -166,7 +167,7 @@
 #endif
 
 /**
- * atomic_rcu_set - assigns (publicizes) a pointer to a new data structure
+ * rcu_assign_pointer - assigns (publicizes) a pointer to a new data structure
  * meant to be read by RCU read-side critical sections.
  *
  * Documents which pointers will be dereferenced by RCU read-side critical
@@ -174,18 +175,18 @@
  * them. It also makes sure the compiler does not reorder code initializing the
  * data structure before its publication.
  *
- * Should match atomic_rcu_read().
+ * Should match rcu_dereference().
  */
-#ifndef atomic_rcu_set
+#ifndef rcu_assign_pointer
 #ifdef __ATOMIC_RELEASE
-#define atomic_rcu_set(ptr, i)  do {              \
-    typeof(*ptr) _val = (i);                      \
-    __atomic_store(ptr, &_val, __ATOMIC_RELEASE); \
+#define rcu_assign_pointer(ptr, i)  do {          \
+    typeof(ptr) _val = (i);                       \
+    __atomic_store(&ptr, &_val, __ATOMIC_RELEASE);\
 } while(0)
 #else
-#define atomic_rcu_set(ptr, i)  do {              \
+#define rcu_assign_pointer(ptr, i)  do {          \
     smp_wmb();                                    \
-    atomic_set(ptr, i);                           \
+    atomic_set(&ptr, i);                          \
 } while (0)
 #endif
 #endif
diff --git a/memory.c b/memory.c
index dc5e4e9..b950259 100644
--- a/memory.c
+++ b/memory.c
@@ -642,7 +642,7 @@ static FlatView *address_space_get_flatview(AddressSpace 
*as)
     FlatView *view;
 
     rcu_read_lock();
-    view = atomic_rcu_read(&as->current_map);
+    view = rcu_dereference(as->current_map);
     flatview_ref(view);
     rcu_read_unlock();
     return view;
@@ -754,7 +754,7 @@ static void address_space_update_topology(AddressSpace *as)
     address_space_update_topology_pass(as, old_view, new_view, true);
 
     /* Writes are protected by the BQL.  */
-    atomic_rcu_set(&as->current_map, new_view);
+    rcu_assign_pointer(as->current_map, new_view);
     call_rcu_first_elem(old_view, flatview_unref, rcu);
 
     /* Note that all the old MemoryRegions are still alive up to this
@@ -1829,7 +1829,7 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr,
     range = addrrange_make(int128_make64(addr), int128_make64(size));
 
     rcu_read_lock();
-    view = atomic_rcu_read(&as->current_map);
+    view = rcu_dereference(as->current_map);
     fr = flatview_lookup(view, range);
     if (!fr) {
         goto out;
diff --git a/tests/rcutorture.c b/tests/rcutorture.c
index 60a2ccf..2c10107 100644
--- a/tests/rcutorture.c
+++ b/tests/rcutorture.c
@@ -251,7 +251,7 @@ static void *rcu_read_stress_test(void *arg)
     }
     while (goflag == GOFLAG_RUN) {
         rcu_read_lock();
-        p = atomic_rcu_read(&rcu_stress_current);
+        p = rcu_dereference(rcu_stress_current);
         if (p->mbtest == 0) {
             n_mberror++;
         }
@@ -298,7 +298,7 @@ static void *rcu_update_stress_test(void *arg)
         smp_mb();
         p->pipe_count = 0;
         p->mbtest = 1;
-        atomic_rcu_set(&rcu_stress_current, p);
+        rcu_assign_pointer(rcu_stress_current, p);
         rcu_stress_idx = i;
         for (i = 0; i < RCU_STRESS_PIPE_LEN; i++) {
             if (i != rcu_stress_idx) {
-- 
1.8.3




reply via email to

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