2013-06-28 15:54:40 -07:00
|
|
|
|
/*
|
2014-03-11 13:37:27 -07:00
|
|
|
|
* Copyright (c) 2013, 2014 Nicira, Inc.
|
2013-06-28 15:54:40 -07:00
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at:
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* This header implements atomic operation primitives using pthreads. */
|
|
|
|
|
#ifndef IN_OVS_ATOMIC_H
|
|
|
|
|
#error "This header should only be included indirectly via ovs-atomic.h."
|
|
|
|
|
#endif
|
|
|
|
|
|
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
|
|
|
|
#include "ovs-atomic-locked.h"
|
|
|
|
|
|
2013-06-28 15:54:40 -07:00
|
|
|
|
#define OVS_ATOMIC_PTHREADS_IMPL 1
|
|
|
|
|
|
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(TYPE) TYPE
|
2013-06-28 15:54:40 -07:00
|
|
|
|
|
|
|
|
|
#define ATOMIC_BOOL_LOCK_FREE 0
|
|
|
|
|
#define ATOMIC_CHAR_LOCK_FREE 0
|
|
|
|
|
#define ATOMIC_SHORT_LOCK_FREE 0
|
|
|
|
|
#define ATOMIC_INT_LOCK_FREE 0
|
|
|
|
|
#define ATOMIC_LONG_LOCK_FREE 0
|
|
|
|
|
#define ATOMIC_LLONG_LOCK_FREE 0
|
|
|
|
|
#define ATOMIC_POINTER_LOCK_FREE 0
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
|
memory_order_relaxed,
|
|
|
|
|
memory_order_consume,
|
|
|
|
|
memory_order_acquire,
|
|
|
|
|
memory_order_release,
|
|
|
|
|
memory_order_acq_rel,
|
|
|
|
|
memory_order_seq_cst
|
|
|
|
|
} memory_order;
|
|
|
|
|
|
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_init(OBJECT, VALUE) (*(OBJECT) = (VALUE), (void) 0)
|
2013-06-28 15:54:40 -07:00
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
atomic_thread_fence(memory_order order OVS_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
/* Nothing to do. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
atomic_signal_fence(memory_order order OVS_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
/* Nothing to do. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define atomic_is_lock_free(OBJ) 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_store(DST, SRC) atomic_store_locked(DST, SRC)
|
2013-06-28 15:54:40 -07:00
|
|
|
|
#define atomic_store_explicit(DST, SRC, ORDER) \
|
|
|
|
|
((void) (ORDER), atomic_store(DST, SRC))
|
|
|
|
|
|
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_read(SRC, DST) atomic_read_locked(SRC, DST)
|
2013-06-28 15:54:40 -07:00
|
|
|
|
#define atomic_read_explicit(SRC, DST, ORDER) \
|
|
|
|
|
((void) (ORDER), atomic_read(SRC, DST))
|
|
|
|
|
|
2014-07-07 13:18:46 -07:00
|
|
|
|
#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
|
|
|
|
|
|
2021-09-08 11:47:35 +02:00
|
|
|
|
#define atomic_exchange(DST, SRC) \
|
|
|
|
|
atomic_exchange_locked(DST, SRC)
|
|
|
|
|
#define atomic_exchange_explicit(DST, SRC, ORDER) \
|
|
|
|
|
((void) (ORDER), atomic_exchange(DST, SRC))
|
|
|
|
|
|
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_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)
|
|
|
|
|
#define atomic_xor(RMW, ARG, ORIG) atomic_op_locked(RMW, xor, ARG, ORIG)
|
|
|
|
|
#define atomic_and(RMW, ARG, ORIG) atomic_op_locked(RMW, and, ARG, ORIG)
|
|
|
|
|
|
|
|
|
|
#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \
|
|
|
|
|
((void) (ORDER), atomic_add(RMW, ARG, ORIG))
|
|
|
|
|
#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \
|
|
|
|
|
((void) (ORDER), atomic_sub(RMW, ARG, ORIG))
|
|
|
|
|
#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \
|
|
|
|
|
((void) (ORDER), atomic_or(RMW, ARG, ORIG))
|
|
|
|
|
#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \
|
|
|
|
|
((void) (ORDER), atomic_xor(RMW, ARG, ORIG))
|
|
|
|
|
#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \
|
|
|
|
|
((void) (ORDER), atomic_and(RMW, ARG, ORIG))
|
2013-06-28 15:54:40 -07:00
|
|
|
|
|
|
|
|
|
/* atomic_flag */
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
bool b;
|
|
|
|
|
} atomic_flag;
|
2014-03-11 12:57:02 -07:00
|
|
|
|
#define ATOMIC_FLAG_INIT { false }
|
2013-06-28 15:54:40 -07:00
|
|
|
|
|
2014-03-11 12:57:02 -07:00
|
|
|
|
static inline bool
|
|
|
|
|
atomic_flag_test_and_set(volatile atomic_flag *flag_)
|
|
|
|
|
{
|
|
|
|
|
atomic_flag *flag = CONST_CAST(atomic_flag *, flag_);
|
|
|
|
|
bool old_value;
|
|
|
|
|
|
|
|
|
|
atomic_lock__(flag);
|
|
|
|
|
old_value = flag->b;
|
|
|
|
|
flag->b = true;
|
|
|
|
|
atomic_unlock__(flag);
|
2014-01-08 17:13:28 -08:00
|
|
|
|
|
2014-03-11 12:57:02 -07:00
|
|
|
|
return old_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
|
atomic_flag_test_and_set_explicit(volatile atomic_flag *flag,
|
|
|
|
|
memory_order order OVS_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
return atomic_flag_test_and_set(flag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
atomic_flag_clear(volatile atomic_flag *flag_)
|
|
|
|
|
{
|
|
|
|
|
atomic_flag *flag = CONST_CAST(atomic_flag *, flag_);
|
|
|
|
|
|
|
|
|
|
atomic_lock__(flag);
|
|
|
|
|
flag->b = false;
|
|
|
|
|
atomic_unlock__(flag);
|
|
|
|
|
}
|
2013-06-28 15:54:40 -07:00
|
|
|
|
|
2014-03-11 12:57:02 -07:00
|
|
|
|
static inline void
|
|
|
|
|
atomic_flag_clear_explicit(volatile atomic_flag *flag,
|
|
|
|
|
memory_order order OVS_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
atomic_flag_clear(flag);
|
|
|
|
|
}
|