Home | History | Annotate | Download | only in include
      1 // -*- C++ -*- compatibility header.
      2 
      3 // Copyright (C) 2008, 2009 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file stdatomic.h
     26  *  This is a Standard C++ Library header.
     27  */
     28 
     29 #include <bits/c++config.h>
     30 #include <stddef.h>
     31 #include <stdbool.h> // XXX need to define bool w/o stdbool.h in tr1/cstdbool
     32 
     33 #ifndef _GLIBCXX_STDATOMIC_H
     34 #define _GLIBCXX_STDATOMIC_H 1
     35 
     36 _GLIBCXX_BEGIN_NAMESPACE(std)
     37 _GLIBCXX_BEGIN_EXTERN_C
     38 
     39   /**
     40    * @defgroup atomics Atomics
     41    *
     42    * Components for performing atomic operations.
     43    * @{
     44    */
     45 
     46   /// Enumeration for memory_order
     47   typedef enum memory_order
     48     {
     49       memory_order_relaxed,
     50       memory_order_consume,
     51       memory_order_acquire,
     52       memory_order_release,
     53       memory_order_acq_rel,
     54       memory_order_seq_cst
     55     } memory_order;
     56 
     57   // Base for atomic_flag.
     58   typedef struct __atomic_flag_base
     59   {
     60     bool _M_i;
     61   } __atomic_flag_base;
     62 
     63 #define ATOMIC_FLAG_INIT { false }
     64 
     65   /// 29.2 Lock-free Property
     66 #if defined(_GLIBCXX_ATOMIC_BUILTINS_1) && defined(_GLIBCXX_ATOMIC_BUILTINS_2) \
     67   && defined(_GLIBCXX_ATOMIC_BUILTINS_4) && defined(_GLIBCXX_ATOMIC_BUILTINS_8)
     68 # define _GLIBCXX_ATOMIC_PROPERTY 2
     69 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic2
     70 #elif defined(_GLIBCXX_ATOMIC_BUILTINS_1)
     71 # define _GLIBCXX_ATOMIC_PROPERTY 1
     72 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic1
     73 #else
     74 # define _GLIBCXX_ATOMIC_PROPERTY 0
     75 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic0
     76 #endif
     77 
     78 #define ATOMIC_INTEGRAL_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY
     79 #define ATOMIC_ADDRESS_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY
     80 
     81   // Switch atomic integral base types based on C or C++.  In
     82   // addition, for "C" only provide type-generic macros for atomic
     83   // operations. (As C++ accomplishes the same thing with sets of
     84   // overloaded functions.
     85 #ifdef __cplusplus
     86   inline namespace _GLIBCXX_ATOMIC_NAMESPACE { }
     87 # include <bits/atomicfwd_cxx.h>
     88 #else
     89 # include <bits/atomicfwd_c.h>
     90 #endif
     91 
     92   // Typedefs for other atomic integral types.
     93   typedef atomic_schar 		atomic_int_least8_t;
     94   typedef atomic_uchar 		atomic_uint_least8_t;
     95   typedef atomic_short 		atomic_int_least16_t;
     96   typedef atomic_ushort 	atomic_uint_least16_t;
     97   typedef atomic_int 		atomic_int_least32_t;
     98   typedef atomic_uint 		atomic_uint_least32_t;
     99   typedef atomic_llong 		atomic_int_least64_t;
    100   typedef atomic_ullong 	atomic_uint_least64_t;
    101 
    102   typedef atomic_schar 		atomic_int_fast8_t;
    103   typedef atomic_uchar 		atomic_uint_fast8_t;
    104   typedef atomic_short 		atomic_int_fast16_t;
    105   typedef atomic_ushort 	atomic_uint_fast16_t;
    106   typedef atomic_int 		atomic_int_fast32_t;
    107   typedef atomic_uint 		atomic_uint_fast32_t;
    108   typedef atomic_llong 		atomic_int_fast64_t;
    109   typedef atomic_ullong 	atomic_uint_fast64_t;
    110 
    111   typedef atomic_long 		atomic_intptr_t;
    112   typedef atomic_ulong 		atomic_uintptr_t;
    113 
    114   typedef atomic_long 		atomic_ssize_t;
    115   typedef atomic_ulong 		atomic_size_t;
    116 
    117   typedef atomic_llong 		atomic_intmax_t;
    118   typedef atomic_ullong 	atomic_uintmax_t;
    119 
    120   typedef atomic_long 		atomic_ptrdiff_t;
    121 
    122   // Accessor functions for base atomic_flag type.
    123   bool
    124   atomic_flag_test_and_set_explicit(volatile __atomic_flag_base*, memory_order);
    125 
    126   inline bool
    127   atomic_flag_test_and_set(volatile __atomic_flag_base* __a)
    128   { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); }
    129 
    130   void
    131   atomic_flag_clear_explicit(volatile __atomic_flag_base*, memory_order);
    132 
    133   inline void
    134   atomic_flag_clear(volatile __atomic_flag_base* __a)
    135   { atomic_flag_clear_explicit(__a, memory_order_seq_cst); }
    136 
    137   void
    138   __atomic_flag_wait_explicit(volatile __atomic_flag_base*, memory_order);
    139 
    140   volatile __atomic_flag_base*
    141   __atomic_flag_for_address(const volatile void* __z) __attribute__((const));
    142 
    143   // Implementation specific defines.
    144 #define _ATOMIC_LOAD_(__a, __x)						\
    145   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;	\
    146      volatile atomic_flag* __g = __atomic_flag_for_address(__p); 	\
    147     __atomic_flag_wait_explicit(__g, __x);				\
    148     __typeof__ _ATOMIC_MEMBER_ __r = *__p;				\
    149     atomic_flag_clear_explicit(__g, __x);		       		\
    150     __r; })
    151 
    152 #define _ATOMIC_STORE_(__a, __m, __x)					\
    153   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;	\
    154     __typeof__(__m) __v = (__m);			       		\
    155     volatile atomic_flag* __g = __atomic_flag_for_address(__p); 	\
    156     __atomic_flag_wait_explicit(__g, __x);				\
    157     *__p = __v;								\
    158     atomic_flag_clear_explicit(__g, __x);		       		\
    159     __v; })
    160 
    161 #define _ATOMIC_MODIFY_(__a, __o, __m, __x)				\
    162   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;	\
    163     __typeof__(__m) __v = (__m);			       		\
    164     volatile atomic_flag* __g = __atomic_flag_for_address(__p); 	\
    165     __atomic_flag_wait_explicit(__g, __x);				\
    166     __typeof__ _ATOMIC_MEMBER_ __r = *__p;				\
    167     *__p __o __v;					       		\
    168     atomic_flag_clear_explicit(__g, __x);		       		\
    169     __r; })
    170 
    171 #define _ATOMIC_CMPEXCHNG_(__a, __e, __m, __x)				\
    172   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;	\
    173     __typeof__(__e) __q = (__e);			       		\
    174     __typeof__(__m) __v = (__m);			       		\
    175     bool __r;						       		\
    176     volatile atomic_flag* __g = __atomic_flag_for_address(__p); 	\
    177     __atomic_flag_wait_explicit(__g, __x);				\
    178     __typeof__ _ATOMIC_MEMBER_ __t__ = *__p;		       		\
    179     if (__t__ == *__q) { *__p = __v; __r = true; }			\
    180     else { *__q = __t__; __r = false; }		       			\
    181     atomic_flag_clear_explicit(__g, __x);		       		\
    182     __r; })
    183 
    184   // @} group atomics
    185 
    186 _GLIBCXX_END_EXTERN_C
    187 _GLIBCXX_END_NAMESPACE
    188 
    189 // Inject into global namespace.
    190 #ifdef __cplusplus
    191 
    192 #include <cstdatomic>
    193 
    194 using std::memory_order;
    195 using std::memory_order_relaxed;
    196 using std::memory_order_consume;
    197 using std::memory_order_acquire;
    198 using std::memory_order_release;
    199 using std::memory_order_acq_rel;
    200 using std::memory_order_seq_cst;
    201 using std::atomic_flag;
    202 using std::atomic_bool;
    203 using std::atomic_char;
    204 using std::atomic_schar;
    205 using std::atomic_uchar;
    206 using std::atomic_short;
    207 using std::atomic_ushort;
    208 using std::atomic_int;
    209 using std::atomic_uint;
    210 using std::atomic_long;
    211 using std::atomic_ulong;
    212 using std::atomic_llong;
    213 using std::atomic_ullong;
    214 using std::atomic_wchar_t;
    215 using std::atomic_char16_t;
    216 using std::atomic_char32_t;
    217 using std::atomic_address;
    218 using std::atomic;
    219 #endif
    220 
    221 #endif
    222