mirror of
https://github.com/openvswitch/ovs
synced 2025-10-19 14:37:21 +00:00
ovs-atomic: Add C++ compatible implementation.
G++ 5 does not implement the _Atomic keyword, which is part of C11 but not
C++11, so the existing <stdatomic.h> based atomic implementation doesn't
work. This commit adds a new implementation based on the C++11 <atomic>
header.
In this area, C++ is pickier about types than C, so a few of the
definitions in ovs-atomic.h have to be updated to use more precise types
for integer constants.
This updates the code that generates cxxtest.cc to #include <config.h>
(so that HAVE_ATOMIC is defined) and to automatically regenerate when the
program is reconfigured (because otherwise the #include <config.h>) won't
get added without a "make clean" step).
"ovs-atomic.h" is not a public header, but apparently some code was
using it anyway.
Fixes: 9c463631e8
("ovs-atomic: Report error for contradictory configuration.")
Reported-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Yi-Hung Wei <yihung.wei@gmail.com>
This commit is contained in:
@@ -41,10 +41,12 @@ if HAVE_CXX
|
||||
# are acceptable as C++.
|
||||
noinst_LTLIBRARIES += include/openvswitch/libcxxtest.la
|
||||
nodist_include_openvswitch_libcxxtest_la_SOURCES = include/openvswitch/cxxtest.cc
|
||||
include/openvswitch/cxxtest.cc: include/openvswitch/automake.mk
|
||||
$(AM_V_GEN)for header in $(openvswitchinclude_HEADERS); do \
|
||||
echo $$header; \
|
||||
done | sed 's,^include/\(.*\)$$,#include <\1>,' > $@
|
||||
include/openvswitch/cxxtest.cc: \
|
||||
include/openvswitch/automake.mk $(top_builddir)/config.status
|
||||
$(AM_V_GEN){ echo "#include <config.h>"; \
|
||||
for header in $(openvswitchinclude_HEADERS); do \
|
||||
echo $$header; \
|
||||
done | sed 's,^include/\(.*\)$$,#include <\1>,'; } > $@
|
||||
endif
|
||||
|
||||
# OVS does not use C++ itself, but it provides public header files
|
||||
|
@@ -159,6 +159,7 @@ lib_libopenvswitch_la_SOURCES = \
|
||||
lib/ofp-version-opt.h \
|
||||
lib/ofp-version-opt.c \
|
||||
lib/ofpbuf.c \
|
||||
lib/ovs-atomic-c++.h \
|
||||
lib/ovs-atomic-c11.h \
|
||||
lib/ovs-atomic-clang.h \
|
||||
lib/ovs-atomic-flag-gcc4.7+.h \
|
||||
|
64
lib/ovs-atomic-c++.h
Normal file
64
lib/ovs-atomic-c++.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* This header implements atomic operation primitives on compilers that
|
||||
* have built-in support for ++C11 <atomic> */
|
||||
#ifndef IN_OVS_ATOMIC_H
|
||||
#error "This header should only be included indirectly via ovs-atomic.h."
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#define ATOMIC(TYPE) std::atomic<TYPE>
|
||||
|
||||
using std::atomic_init;
|
||||
|
||||
using std::memory_order_relaxed;
|
||||
using std::memory_order_consume;
|
||||
using std::memory_order_acquire;
|
||||
using std::memory_order_release;
|
||||
using std::memory_order_acq_rel;
|
||||
using std::memory_order_seq_cst;
|
||||
|
||||
using std::atomic_thread_fence;
|
||||
using std::atomic_signal_fence;
|
||||
using std::atomic_is_lock_free;
|
||||
|
||||
using std::atomic_store;
|
||||
using std::atomic_store_explicit;
|
||||
|
||||
using std::atomic_compare_exchange_strong;
|
||||
using std::atomic_compare_exchange_strong_explicit;
|
||||
using std::atomic_compare_exchange_weak;
|
||||
using std::atomic_compare_exchange_weak_explicit;
|
||||
|
||||
#define atomic_read(SRC, DST) \
|
||||
atomic_read_explicit(SRC, DST, memory_order_seq_cst)
|
||||
#define atomic_read_explicit(SRC, DST, ORDER) \
|
||||
(*(DST) = std::atomic_load_explicit(SRC, ORDER), \
|
||||
(void) 0)
|
||||
|
||||
#define atomic_add(RMW, ARG, ORIG) \
|
||||
atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst)
|
||||
#define atomic_sub(RMW, ARG, ORIG) \
|
||||
atomic_sub_explicit(RMW, ARG, ORIG, memory_order_seq_cst)
|
||||
#define atomic_or(RMW, ARG, ORIG) \
|
||||
atomic_or_explicit(RMW, ARG, ORIG, memory_order_seq_cst)
|
||||
#define atomic_xor(RMW, ARG, ORIG) \
|
||||
atomic_xor_explicit(RMW, ARG, ORIG, memory_order_seq_cst)
|
||||
#define atomic_and(RMW, ARG, ORIG) \
|
||||
atomic_and_explicit(RMW, ARG, ORIG, memory_order_seq_cst)
|
||||
|
||||
#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \
|
||||
(*(ORIG) = std::atomic_fetch_add_explicit(RMW, ARG, ORDER), (void) 0)
|
||||
#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \
|
||||
(*(ORIG) = std::atomic_fetch_sub_explicit(RMW, ARG, ORDER), (void) 0)
|
||||
#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \
|
||||
(*(ORIG) = std::atomic_fetch_or_explicit(RMW, ARG, ORDER), (void) 0)
|
||||
#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \
|
||||
(*(ORIG) = std::atomic_fetch_xor_explicit(RMW, ARG, ORDER), (void) 0)
|
||||
#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \
|
||||
(*(ORIG) = std::atomic_fetch_and_explicit(RMW, ARG, ORDER), (void) 0)
|
||||
|
||||
using std::atomic_flag;
|
||||
using std::atomic_flag_test_and_set_explicit;
|
||||
using std::atomic_flag_test_and_set;
|
||||
using std::atomic_flag_clear_explicit;
|
||||
using std::atomic_flag_clear;
|
@@ -325,11 +325,13 @@
|
||||
#include "ovs-atomic-pthreads.h"
|
||||
#elif __has_extension(c_atomic)
|
||||
#include "ovs-atomic-clang.h"
|
||||
#elif HAVE_STDATOMIC_H
|
||||
#elif HAVE_ATOMIC && __cplusplus >= 201103L
|
||||
#include "ovs-atomic-c++.h"
|
||||
#elif HAVE_STDATOMIC_H && !defined(__cplusplus)
|
||||
#include "ovs-atomic-c11.h"
|
||||
#elif __GNUC__ >= 5
|
||||
#elif __GNUC__ >= 5 && !defined(__cplusplus)
|
||||
#error "GCC 5+ should have <stdatomic.h>"
|
||||
#elif __GNUC__ >= 4 && __GNUC_MINOR__ >= 7
|
||||
#elif __GNUC__ >= 5 || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 7)
|
||||
#include "ovs-atomic-gcc4.7+.h"
|
||||
#elif __GNUC__ && defined(__x86_64__)
|
||||
#include "ovs-atomic-x86_64.h"
|
||||
@@ -446,7 +448,7 @@ atomic_count_inc(atomic_count *count)
|
||||
{
|
||||
unsigned int old;
|
||||
|
||||
atomic_add_relaxed(&count->count, 1, &old);
|
||||
atomic_add_relaxed(&count->count, 1u, &old);
|
||||
|
||||
return old;
|
||||
}
|
||||
@@ -456,7 +458,7 @@ atomic_count_dec(atomic_count *count)
|
||||
{
|
||||
unsigned int old;
|
||||
|
||||
atomic_sub_relaxed(&count->count, 1, &old);
|
||||
atomic_sub_relaxed(&count->count, 1u, &old);
|
||||
|
||||
return old;
|
||||
}
|
||||
@@ -486,7 +488,7 @@ struct ovs_refcount {
|
||||
static inline void
|
||||
ovs_refcount_init(struct ovs_refcount *refcount)
|
||||
{
|
||||
atomic_init(&refcount->count, 1);
|
||||
atomic_init(&refcount->count, 1u);
|
||||
}
|
||||
|
||||
/* Increments 'refcount'.
|
||||
@@ -498,7 +500,7 @@ ovs_refcount_ref(struct ovs_refcount *refcount)
|
||||
{
|
||||
unsigned int old_refcount;
|
||||
|
||||
atomic_add_explicit(&refcount->count, 1, &old_refcount,
|
||||
atomic_add_explicit(&refcount->count, 1u, &old_refcount,
|
||||
memory_order_relaxed);
|
||||
ovs_assert(old_refcount > 0);
|
||||
}
|
||||
@@ -521,7 +523,7 @@ ovs_refcount_unref(struct ovs_refcount *refcount)
|
||||
{
|
||||
unsigned int old_refcount;
|
||||
|
||||
atomic_sub_explicit(&refcount->count, 1, &old_refcount,
|
||||
atomic_sub_explicit(&refcount->count, 1u, &old_refcount,
|
||||
memory_order_release);
|
||||
ovs_assert(old_refcount > 0);
|
||||
if (old_refcount == 1) {
|
||||
@@ -619,7 +621,7 @@ ovs_refcount_unref_relaxed(struct ovs_refcount *refcount)
|
||||
{
|
||||
unsigned int old_refcount;
|
||||
|
||||
atomic_sub_explicit(&refcount->count, 1, &old_refcount,
|
||||
atomic_sub_explicit(&refcount->count, 1u, &old_refcount,
|
||||
memory_order_relaxed);
|
||||
ovs_assert(old_refcount > 0);
|
||||
return old_refcount;
|
||||
|
@@ -632,6 +632,9 @@ AC_DEFUN([OVS_CHECK_CXX],
|
||||
AX_CXX_COMPILE_STDCXX([11], [], [optional])
|
||||
if test $enable_Werror = yes && test $HAVE_CXX11 = 1; then
|
||||
enable_cxx=:
|
||||
AC_LANG_PUSH([C++])
|
||||
AC_CHECK_HEADERS([atomic])
|
||||
AC_LANG_POP([C++])
|
||||
else
|
||||
enable_cxx=false
|
||||
fi
|
||||
|
Reference in New Issue
Block a user