Skip to content

Commit

Permalink
lib/ovs-atomic: Add atomic compare_exchange.
Browse files Browse the repository at this point in the history
Add support for atomic compare_exchange operations.

Signed-off-by: Jarno Rajahalme <[email protected]>
Acked-by: Ben Pfaff <[email protected]>
  • Loading branch information
Jarno Rajahalme committed Jul 7, 2014
1 parent 541bfad commit 25045d7
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 1 deletion.
14 changes: 14 additions & 0 deletions lib/ovs-atomic-clang.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down
23 changes: 23 additions & 0 deletions lib/ovs-atomic-gcc4+.h
Original file line number Diff line number Diff line change
Expand Up @@ -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); \
Expand Down
14 changes: 14 additions & 0 deletions lib/ovs-atomic-gcc4.7+.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down
11 changes: 11 additions & 0 deletions lib/ovs-atomic-locked.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 |=
Expand Down
10 changes: 10 additions & 0 deletions lib/ovs-atomic-pthreads.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
28 changes: 27 additions & 1 deletion lib/ovs-atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,40 @@
* 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);
*
* 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:
Expand Down

0 comments on commit 25045d7

Please sign in to comment.