From 019d3958118b7dc3ec8444ad2accca50c268b737 Mon Sep 17 00:00:00 2001
From: Hans Boehm <hboehm@google.com>
Date: Thu, 14 Aug 2014 15:26:03 -0700
Subject: [PATCH] Have stdatomic.h punt to C++ atomic when possible

This is an alternate, somewhat simpler, fix that makes it safe to
include both <atomic> and <stdatomic.h> from C++ code in either order.
It means that C code consistently uses one implementation of atomics
and C++ another.  We still have to make sure that those two
implementations interoperate correctly at runtime; in particular,
any flavor of atomic object needs to be represented exactly like the
underlying type, with the proper alignment constraint.

Bug:17007799
Change-Id: Iffcfc5220d8fa150f89dd083a121b24d23f268fc
---
 libc/include/stdatomic.h | 93 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)

diff --git a/libc/include/stdatomic.h b/libc/include/stdatomic.h
index 669cefd66..2c0422138 100644
--- a/libc/include/stdatomic.h
+++ b/libc/include/stdatomic.h
@@ -31,9 +31,98 @@
 #define	_STDATOMIC_H_
 
 #include <sys/cdefs.h>
+
+#if defined(__cplusplus) && defined(_USING_LIBCXX) && \
+    (__has_feature(cxx_atomic) || _GNUC_VER >= 407)
+
+/* We have a usable C++ <atomic>; use it instead.  */
+
+#include <atomic>
+
+#define _Atomic(t) std::atomic<t>
+
+using std::atomic_is_lock_free;
+using std::atomic_init;
+using std::atomic_store;
+using std::atomic_store_explicit;
+using std::atomic_load;
+using std::atomic_load_explicit;
+using std::atomic_exchange;
+using std::atomic_exchange_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;
+using std::atomic_fetch_add;
+using std::atomic_fetch_add_explicit;
+using std::atomic_fetch_sub;
+using std::atomic_fetch_sub_explicit;
+using std::atomic_fetch_or;
+using std::atomic_fetch_or_explicit;
+using std::atomic_fetch_xor;
+using std::atomic_fetch_xor_explicit;
+using std::atomic_fetch_and;
+using std::atomic_fetch_and_explicit;
+using std::atomic_thread_fence;
+using std::atomic_signal_fence;
+
+using std::memory_order;
+using std::memory_order_relaxed;
+using std::memory_order_consume;
+using std::memory_order_release;
+using std::memory_order_acq_rel;
+using std::memory_order_seq_cst;
+
+using std::atomic_bool;
+using std::atomic_char;
+using std::atomic_schar;
+using std::atomic_uchar;
+using std::atomic_short;
+using std::atomic_ushort;
+using std::atomic_int;
+using std::atomic_uint;
+using std::atomic_long;
+using std::atomic_ulong;
+using std::atomic_llong;
+using std::atomic_ullong;
+using std::atomic_char16_t;
+using std::atomic_char32_t;
+using std::atomic_wchar_t;
+using std::atomic_int_least8_t;
+using std::atomic_uint_least8_t;
+using std::atomic_int_least16_t;
+using std::atomic_uint_least16_t;
+using std::atomic_int_least32_t;
+using std::atomic_uint_least32_t;
+using std::atomic_int_least64_t;
+using std::atomic_uint_least64_t;
+using std::atomic_int_fast8_t;
+using std::atomic_uint_fast8_t;
+using std::atomic_int_fast16_t;
+using std::atomic_uint_fast16_t;
+using std::atomic_int_fast32_t;
+using std::atomic_uint_fast32_t;
+using std::atomic_int_fast64_t;
+using std::atomic_uint_fast64_t;
+using std::atomic_intptr_t;
+using std::atomic_uintptr_t;
+using std::atomic_size_t;
+using std::atomic_ptrdiff_t;
+using std::atomic_intmax_t;
+using std::atomic_uintmax_t;
+
+#else /* <atomic> unavailable, possibly because this is C, not C++ */
+
 #include <sys/types.h>
 #include <stdbool.h>
 
+/*
+ * C: Do it ourselves.
+ * Note that the runtime representation defined here should be compatible
+ * with the C++ one, i.e. an _Atomic(T) needs to contain the same
+ * bits as a T.
+ */
+
 #if __has_extension(c_atomic) || __has_extension(cxx_atomic)
 #define	__CLANG_ATOMICS
 #elif __GNUC_PREREQ__(4, 7)
@@ -121,6 +210,8 @@
  *
  * The memory_order_* constants that denote the barrier behaviour of the
  * atomic operations.
+ * The enum values must be identical to those used by the
+ * C++ <atomic> header.
  */
 
 typedef enum {
@@ -419,4 +510,6 @@ atomic_flag_clear(volatile atomic_flag *__object)
 }
 #endif /* !_KERNEL */
 
+#endif /* <atomic> unavailable */
+
 #endif /* !_STDATOMIC_H_ */