add rcu_cmpxchg_pointer
authorMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Tue, 22 Sep 2009 23:01:10 +0000 (19:01 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Tue, 22 Sep 2009 23:01:10 +0000 (19:01 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
urcu-qsbr-static.h
urcu-qsbr.c
urcu-qsbr.h
urcu-static.h
urcu.c
urcu.h

index 22a93b2..c0467cd 100644 (file)
@@ -244,6 +244,22 @@ static inline void _rcu_thread_online(void)
                STORE_SHARED(p, v);                     \
        })
 
+/**
+ * _rcu_cmpxchg_pointer - same as rcu_assign_pointer, but tests if the pointer
+ * is as expected by "old". If succeeds, returns the previous pointer to the
+ * data structure, which can be safely freed after waiting for a quiescent state
+ * using synchronize_rcu(). If fails (unexpected value), returns old (which
+ * should not be freed !).
+ */
+
+#define _rcu_cmpxchg_pointer(p, old, _new)             \
+       ({                                              \
+               if (!__builtin_constant_p(_new) ||      \
+                   ((_new) != NULL))                   \
+                       wmb();                          \
+               cmpxchg(p, old, _new);                  \
+       })
+
 /**
  * _rcu_xchg_pointer - same as rcu_assign_pointer, but returns the previous
  * pointer to the data structure, which can be safely freed after waiting for a
index f681c05..5c6eaa0 100644 (file)
@@ -255,6 +255,12 @@ void *rcu_assign_pointer_sym(void **p, void *v)
        return STORE_SHARED(p, v);
 }
 
+void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new)
+{
+       wmb();
+       return cmpxchg(p, old, _new);
+}
+
 void *rcu_xchg_pointer_sym(void **p, void *v)
 {
        wmb();
index 9a2c82f..346f906 100644 (file)
@@ -103,6 +103,10 @@ extern void *rcu_assign_pointer_sym(void **p, void *v);
 #define rcu_assign_pointer(p, v)                       \
        rcu_assign_pointer_sym((void **)(p), (v))
 
+extern void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new);
+#define rcu_cmpxchg_pointer(p, old, _new)              \
+       rcu_cmpxchg_pointer_sym((void **)(p), (old), (_new))
+
 extern void *rcu_xchg_pointer_sym(void **p, void *v);
 #define rcu_xchg_pointer(p, v)                         \
        rcu_xchg_pointer_sym((void **)(p), (v))
index 0c6891e..f819e6f 100644 (file)
@@ -276,6 +276,22 @@ static inline void _rcu_read_unlock(void)
                STORE_SHARED(p, v);                     \
        })
 
+/**
+ * _rcu_cmpxchg_pointer - same as rcu_assign_pointer, but tests if the pointer
+ * is as expected by "old". If succeeds, returns the previous pointer to the
+ * data structure, which can be safely freed after waiting for a quiescent state
+ * using synchronize_rcu(). If fails (unexpected value), returns old (which
+ * should not be freed !).
+ */
+
+#define _rcu_cmpxchg_pointer(p, old, _new)             \
+       ({                                              \
+               if (!__builtin_constant_p(_new) ||      \
+                   ((_new) != NULL))                   \
+                       wmb();                          \
+               cmpxchg(p, old, _new);                  \
+       })
+
 /**
  * _rcu_xchg_pointer - same as rcu_assign_pointer, but returns the previous
  * pointer to the data structure, which can be safely freed after waiting for a
diff --git a/urcu.c b/urcu.c
index d474fc8..a8f85c6 100644 (file)
--- a/urcu.c
+++ b/urcu.c
@@ -347,6 +347,12 @@ void *rcu_xchg_pointer_sym(void **p, void *v)
        return xchg(p, v);
 }
 
+void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new)
+{
+       wmb();
+       return cmpxchg(p, old, _new);
+}
+
 void *rcu_publish_content_sym(void **p, void *v)
 {
        void *oldptr;
diff --git a/urcu.h b/urcu.h
index af7d75c..5d92aa7 100644 (file)
--- a/urcu.h
+++ b/urcu.h
@@ -75,6 +75,10 @@ extern void *rcu_assign_pointer_sym(void **p, void *v);
 #define rcu_assign_pointer(p, v)                       \
        rcu_assign_pointer_sym((void **)(p), (v))
 
+extern void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new);
+#define rcu_cmpxchg_pointer(p, old, _new)              \
+       rcu_cmpxchg_pointer_sym((void **)(p), (old), (_new))
+
 extern void *rcu_xchg_pointer_sym(void **p, void *v);
 #define rcu_xchg_pointer(p, v)                         \
        rcu_xchg_pointer_sym((void **)(p), (v))
This page took 0.035374 seconds and 4 git commands to generate.