ovs-atomic: Use raw types, not structs, when locks are required.
Until now, the GCC 4+ and pthreads implementations of atomics have used
struct wrappers for their atomic types. This had the advantage of allowing
a mutex to be wrapped in, in some cases, and of better type-checking by
preventing stray uses of atomic variables other than through one of the
atomic_*() functions or macros. However, the mutex meant that an
atomic_destroy() function-like macro needed to be used. The struct wrapper
also made it impossible to define new atomic types that were compatible
with each other without using a typedef. For example, one could not simply
define a macro like
#define ATOMIC(TYPE) struct { TYPE value; }
and then have two declarations like:
ATOMIC(void *) x;
ATOMIC(void *) y;
and do anything with these objects that require type-compatibility, even
"&x == &y", because the two structs are not compatible. One can do it
through a typedef:
typedef ATOMIC(void *) atomic_voidp;
atomic_voidp x, y;
but that is inconvenient, especially because of the need to invent a name
for the type.
This commit aims to ease the problem by getting rid of the wrapper structs
in the cases where the atomic library used them. It gets rid of the
mutexes, in the cases where they are still needed, by using a global
array of mutexes instead.
This commit also defines the ATOMIC macro described above and documents
its use in ovs-atomic.h.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Andy Zhou <azhou@nicira.com>
2014-03-11 12:46:29 -07:00
|
|
|
/* This header implements atomic operation locking helpers. */
|
|
|
|
|
#ifndef IN_OVS_ATOMIC_H
|
|
|
|
|
#error "This header should only be included indirectly via ovs-atomic.h."
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define OVS_ATOMIC_LOCKED_IMPL 1
|
|
|
|
|
|
|
|
|
|
void atomic_lock__(void *);
|
|
|
|
|
void atomic_unlock__(void *);
|
|
|
|
|
|
|
|
|
|
#define atomic_store_locked(DST, SRC) \
|
|
|
|
|
(atomic_lock__(DST), \
|
|
|
|
|
*(DST) = (SRC), \
|
|
|
|
|
atomic_unlock__(DST), \
|
|
|
|
|
(void) 0)
|
|
|
|
|
|
|
|
|
|
#define atomic_read_locked(SRC, DST) \
|
|
|
|
|
(atomic_lock__(SRC), \
|
|
|
|
|
*(DST) = *(SRC), \
|
|
|
|
|
atomic_unlock__(SRC), \
|
|
|
|
|
(void) 0)
|
|
|
|
|
|
2014-07-07 13:18:46 -07:00
|
|
|
/* 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)))
|
|
|
|
|
|
ovs-atomic: Use raw types, not structs, when locks are required.
Until now, the GCC 4+ and pthreads implementations of atomics have used
struct wrappers for their atomic types. This had the advantage of allowing
a mutex to be wrapped in, in some cases, and of better type-checking by
preventing stray uses of atomic variables other than through one of the
atomic_*() functions or macros. However, the mutex meant that an
atomic_destroy() function-like macro needed to be used. The struct wrapper
also made it impossible to define new atomic types that were compatible
with each other without using a typedef. For example, one could not simply
define a macro like
#define ATOMIC(TYPE) struct { TYPE value; }
and then have two declarations like:
ATOMIC(void *) x;
ATOMIC(void *) y;
and do anything with these objects that require type-compatibility, even
"&x == &y", because the two structs are not compatible. One can do it
through a typedef:
typedef ATOMIC(void *) atomic_voidp;
atomic_voidp x, y;
but that is inconvenient, especially because of the need to invent a name
for the type.
This commit aims to ease the problem by getting rid of the wrapper structs
in the cases where the atomic library used them. It gets rid of the
mutexes, in the cases where they are still needed, by using a global
array of mutexes instead.
This commit also defines the ATOMIC macro described above and documents
its use in ovs-atomic.h.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Andy Zhou <azhou@nicira.com>
2014-03-11 12:46:29 -07:00
|
|
|
#define atomic_op_locked_add +=
|
|
|
|
|
#define atomic_op_locked_sub -=
|
|
|
|
|
#define atomic_op_locked_or |=
|
|
|
|
|
#define atomic_op_locked_xor ^=
|
|
|
|
|
#define atomic_op_locked_and &=
|
|
|
|
|
#define atomic_op_locked(RMW, OP, OPERAND, ORIG) \
|
|
|
|
|
(atomic_lock__(RMW), \
|
|
|
|
|
*(ORIG) = *(RMW), \
|
|
|
|
|
*(RMW) atomic_op_locked_##OP (OPERAND), \
|
|
|
|
|
atomic_unlock__(RMW))
|