[ovs-dev] [PATCH v2 2/5] lib/ovs-atomic: Add atomic compare_exchange.

Jarno Rajahalme jrajahalme at nicira.com
Fri Jul 4 14:21:16 UTC 2014


Add support for atomic compare_exchange operations.

Signed-off-by: Jarno Rajahalme <jrajahalme at nicira.com>
---
v2: Split to a separate patch, no change.

 lib/ovs-atomic-clang.h    |   14 ++++++++++++++
 lib/ovs-atomic-gcc4+.h    |   23 +++++++++++++++++++++++
 lib/ovs-atomic-gcc4.7+.h  |   14 ++++++++++++++
 lib/ovs-atomic-locked.h   |   11 +++++++++++
 lib/ovs-atomic-pthreads.h |   10 ++++++++++
 lib/ovs-atomic.h          |   28 +++++++++++++++++++++++++++-
 6 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/lib/ovs-atomic-clang.h b/lib/ovs-atomic-clang.h
index c83afab..34cc2fa 100644
--- a/lib/ovs-atomic-clang.h
+++ b/lib/ovs-atomic-clang.h
@@ -53,6 +53,20 @@ typedef enum {
     (*(DST) = __c11_atomic_load(SRC, ORDER), \
      (void) 0)
 
+#define atomic_compare_exchange_strong(DST, EXP, SRC)                   \
+    atomic_compare_exchange_strong_explicit(DST, EXP, SRC,              \
+                                            memory_order_seq_cst,       \
+                                            memory_order_seq_cst)
+#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \
+    __c11_atomic_compare_exchange_strong(DST, EXP, SRC, ORD1, ORD2)
+
+#define atomic_compare_exchange_weak(DST, EXP, SRC)              \
+    atomic_compare_exchange_weak_explicit(DST, EXP, SRC,         \
+                                          memory_order_seq_cst,  \
+                                          memory_order_seq_cst)
+#define atomic_compare_exchange_weak_explicit(DST, EXP, SRC, ORD1, ORD2) \
+    __c11_atomic_compare_exchange_weak(DST, EXP, SRC, ORD1, ORD2)
+
 #define atomic_add(RMW, ARG, ORIG) \
     atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst)
 #define atomic_sub(RMW, ARG, ORIG) \
diff --git a/lib/ovs-atomic-gcc4+.h b/lib/ovs-atomic-gcc4+.h
index 2a1b278..e3dd68e 100644
--- a/lib/ovs-atomic-gcc4+.h
+++ b/lib/ovs-atomic-gcc4+.h
@@ -108,6 +108,29 @@ atomic_signal_fence(memory_order order OVS_UNUSED)
         (void) 0;                                       \
     })
 
+#define atomic_compare_exchange_strong(DST, EXP, SRC)   \
+    ({                                                  \
+        typeof(DST) dst__ = (DST);                      \
+        typeof(EXP) expp__ = (EXP);                     \
+        typeof(SRC) src__ = (SRC);                      \
+        typeof(SRC) exp__ = *expp__;                    \
+        typeof(SRC) ret__;                              \
+                                                        \
+        ret__ = __sync_val_compare_and_swap(dst__, exp__, src__); \
+        if (ret__ != exp__) {                                     \
+            *expp__ = ret__;                                      \
+        }                                                         \
+        ret__ == exp__;                                           \
+    })
+#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \
+    ((void) (ORD1), (void) (ORD2), \
+     atomic_compare_exchange_strong(DST, EXP, SRC))
+#define atomic_compare_exchange_weak            \
+    atomic_compare_exchange_strong
+#define atomic_compare_exchange_weak_explicit   \
+    atomic_compare_exchange_strong_explicit
+
+
 #define atomic_op__(RMW, OP, ARG, ORIG)                     \
     ({                                                      \
         typeof(RMW) rmw__ = (RMW);                          \
diff --git a/lib/ovs-atomic-gcc4.7+.h b/lib/ovs-atomic-gcc4.7+.h
index f465e51..4c197eb 100644
--- a/lib/ovs-atomic-gcc4.7+.h
+++ b/lib/ovs-atomic-gcc4.7+.h
@@ -47,6 +47,20 @@ typedef enum {
     (*(DST) = __atomic_load_n(SRC, ORDER),      \
      (void) 0)
 
+#define atomic_compare_exchange_strong(DST, EXP, SRC)              \
+    atomic_compare_exchange_strong_explicit(DST, EXP, SRC,         \
+                                            memory_order_seq_cst,  \
+                                            memory_order_seq_cst)
+#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \
+    __atomic_compare_exchange_n(DST, EXP, SRC, false, ORD1, ORD2)
+
+#define atomic_compare_exchange_weak(DST, EXP, SRC)              \
+    atomic_compare_exchange_weak_explicit(DST, EXP, SRC,         \
+                                          memory_order_seq_cst,  \
+                                          memory_order_seq_cst)
+#define atomic_compare_exchange_weak_explicit(DST, EXP, SRC, ORD1, ORD2) \
+    __atomic_compare_exchange_n(DST, EXP, SRC, true, ORD1, ORD2)
+
 #define atomic_add(RMW, OPERAND, ORIG) \
         atomic_add_explicit(RMW, OPERAND, ORIG, memory_order_seq_cst)
 #define atomic_sub(RMW, OPERAND, ORIG) \
diff --git a/lib/ovs-atomic-locked.h b/lib/ovs-atomic-locked.h
index 438e78c..f8f0ba2 100644
--- a/lib/ovs-atomic-locked.h
+++ b/lib/ovs-atomic-locked.h
@@ -20,6 +20,17 @@ void atomic_unlock__(void *);
      atomic_unlock__(SRC),                      \
      (void) 0)
 
+/* XXX: Evaluates EXP multiple times. */
+#define atomic_compare_exchange_locked(DST, EXP, SRC)   \
+    (atomic_lock__(DST),                                \
+     (*(DST) == *(EXP)                                  \
+      ? (*(DST) = (SRC),                                \
+         atomic_unlock__(DST),                          \
+         true)                                          \
+      : (*(EXP) = *(DST),                               \
+         atomic_unlock__(DST),                          \
+         false)))
+
 #define atomic_op_locked_add +=
 #define atomic_op_locked_sub -=
 #define atomic_op_locked_or  |=
diff --git a/lib/ovs-atomic-pthreads.h b/lib/ovs-atomic-pthreads.h
index 33270c6..12234e7 100644
--- a/lib/ovs-atomic-pthreads.h
+++ b/lib/ovs-atomic-pthreads.h
@@ -67,6 +67,16 @@ atomic_signal_fence(memory_order order OVS_UNUSED)
 #define atomic_read_explicit(SRC, DST, ORDER)   \
     ((void) (ORDER), atomic_read(SRC, DST))
 
+#define atomic_compare_exchange_strong(DST, EXP, SRC)   \
+    atomic_compare_exchange_locked(DST, EXP, SRC)
+#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \
+    ((void) (ORD1), (void) (ORD2),                                      \
+     atomic_compare_exchange_strong(DST, EXP, SRC))
+#define atomic_compare_exchange_weak            \
+    atomic_compare_exchange_strong
+#define atomic_compare_exchange_weak_explicit   \
+    atomic_compare_exchange_strong_explicit
+
 #define atomic_add(RMW, ARG, ORIG) atomic_op_locked(RMW, add, ARG, ORIG)
 #define atomic_sub(RMW, ARG, ORIG) atomic_op_locked(RMW, sub, ARG, ORIG)
 #define atomic_or( RMW, ARG, ORIG) atomic_op_locked(RMW, or, ARG, ORIG)
diff --git a/lib/ovs-atomic.h b/lib/ovs-atomic.h
index c1d9fcf..95142f5 100644
--- a/lib/ovs-atomic.h
+++ b/lib/ovs-atomic.h
@@ -161,7 +161,7 @@
  * In this section, A is an atomic type and C is the corresponding non-atomic
  * type.
  *
- * The "store" primitives match C11:
+ * The "store" and "compare_exchange" primitives match C11:
  *
  *     void atomic_store(A *object, C value);
  *     void atomic_store_explicit(A *object, C value, memory_order);
@@ -169,6 +169,32 @@
  *         Atomically stores 'value' into '*object', respecting the given
  *         memory order (or memory_order_seq_cst for atomic_store()).
  *
+ *     bool atomic_compare_exchange_strong(A *object, C *expected, C desired);
+ *     bool atomic_compare_exchange_weak(A *object, C *expected, C desired);
+ *     bool atomic_compare_exchange_strong_explicit(A *object, C *expected,
+ *                                                  C desired,
+ *                                                  memory_order success,
+ *                                                  memory_order failure);
+ *     bool atomic_compare_exchange_weak_explicit(A *object, C *expected,
+ *                                                  C desired,
+ *                                                  memory_order success,
+ *                                                  memory_order failure);
+ *
+ *         Atomically loads '*object' and compares it with '*expected' and if
+ *         equal, stores 'desired' into '*object' (an atomic read-modify-write
+ *         operation) and returns true, and if non-equal, stores the actual
+ *         value of '*object' into '*expected' (an atomic load operation) and
+ *         returns false.  The memory order for the successful case (atomic
+ *         read-modify-write operation) is 'success', and for the unsuccessful
+ *         case (atomic load operation) 'failure'.  'failure' may not be
+ *         stronger than 'success'.
+ *
+ *         The weak forms may fail (returning false) also when '*object' equals
+ *         '*expected'.  The strong form can be implemented by the weak form in
+ *         a loop.  Some platforms can implement the weak form more
+ *         efficiently, so it should be used if the application will need to
+ *         loop anyway.
+ *
  * The following primitives differ from the C11 ones (and have different names)
  * because there does not appear to be a way to implement the standard
  * primitives in standard C:
-- 
1.7.10.4




More information about the dev mailing list