libstdc++
atomicity.h
Go to the documentation of this file.
1 // Support for atomic operations -*- C++ -*-
2 
3 // Copyright (C) 2004-2026 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 ext/atomicity.h
26  * This file is a GNU extension to the Standard C++ Library.
27  */
28 
29 #ifndef _GLIBCXX_ATOMICITY_H
30 #define _GLIBCXX_ATOMICITY_H 1
31 
32 #ifdef _GLIBCXX_SYSHDR
33 #pragma GCC system_header
34 #endif
35 
36 #include <bits/c++config.h>
37 #include <bits/gthr.h>
38 #include <bits/atomic_word.h>
39 #if __has_include(<sys/single_threaded.h>)
40 # include <sys/single_threaded.h>
41 #endif
42 #if __cplusplus >= 201103L
43 # include <type_traits> // make_unsigned_t
44 #endif
45 
46 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
47 {
48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
49 
50  __attribute__((__always_inline__))
51  inline bool
52  __is_single_threaded() _GLIBCXX_NOTHROW
53  {
54 #ifndef __GTHREADS
55  return true;
56 #elif __has_include(<sys/single_threaded.h>)
57  return ::__libc_single_threaded;
58 #else
59  return !__gthread_active_p();
60 #endif
61  }
62 
63  // Functions for portable atomic access.
64  // To abstract locking primitives across all thread policies, use:
65  // __exchange_and_add_dispatch
66  // __atomic_add_dispatch
67 #ifdef _GLIBCXX_ATOMIC_WORD_BUILTINS
68  inline _Atomic_word
69  __attribute__((__always_inline__))
70  __exchange_and_add(volatile _Atomic_word* __mem, int __val)
71  { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
72 
73  inline void
74  __attribute__((__always_inline__))
75  __atomic_add(volatile _Atomic_word* __mem, int __val)
76  { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
77 #else // Defined in config/cpu/.../atomicity.h
78  _Atomic_word
79  __exchange_and_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW;
80 
81  void
82  __atomic_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW;
83 #endif
84 
85 #if __cplusplus < 201103L
86  // The array bound will be ill-formed in the very unlikely case that
87  // _Atomic_word is wider than long and we need to use unsigned long long
88  // below in __exchange_and_add_single and __atomic_add_single.
89  typedef int
90  _Atomic_word_fits_in_long[sizeof(_Atomic_word) <= sizeof(long) ? 1 : -1];
91 #endif
92 
93  // Targets where _Atomic_word uses __attribute__((__aligned__(n))) will get
94  // a warning for make_unsigned<_Atomic_word>. That warning can be ignored,
95  // because we only need an unsigned type, we don't care about its alignment.
96 #pragma GCC diagnostic push
97 #pragma GCC diagnostic ignored "-Wignored-attributes"
98 
99  // We need an unsigned type that can be used for the arithmetic below.
100  // This type must not be use for atomic ops because it might not be
101  // sufficiently aligned. Define it as a macro that we #undef below,
102  // to prevent misuse elsewhere in the library.
103 #if __cplusplus >= 201103L
104 # define _GLIBCXX_UNSIGNED_ATOMIC_WORD std::make_unsigned<_Atomic_word>::type
105 #else
106  // For most targets make_unsigned_t<_Atomic_word> is unsigned int,
107  // but 64-bit sparc uses long for _Atomic_word, so needs unsigned long.
108  // Sign-extending to unsigned long works for both cases, so use that.
109 # define _GLIBCXX_UNSIGNED_ATOMIC_WORD unsigned long
110 #endif
111 
112  inline _Atomic_word
113  __attribute__((__always_inline__))
114  __exchange_and_add_single(_Atomic_word* __mem, int __val)
115  {
116  _Atomic_word __result = *__mem;
117  // Do the addition with an unsigned type so that overflow is well defined.
118  _GLIBCXX_UNSIGNED_ATOMIC_WORD __u;
119  __u = __result;
120  __u += __val;
121  *__mem = __u;
122  return __result;
123  }
124 
125  inline void
126  __attribute__((__always_inline__))
127  __atomic_add_single(_Atomic_word* __mem, int __val)
128  {
129  _GLIBCXX_UNSIGNED_ATOMIC_WORD __u;
130  __u = *__mem;
131  __u += __val;
132  *__mem = __u;
133  }
134 #undef _GLIBCXX_UNSIGNED_ATOMIC_WORD
135 #pragma GCC diagnostic pop
136 
137  inline _Atomic_word
138  __attribute__ ((__always_inline__))
139  __exchange_and_add_dispatch(_Atomic_word* __mem, int __val)
140  {
141  if (__is_single_threaded())
142  return __exchange_and_add_single(__mem, __val);
143  else
144  return __exchange_and_add(__mem, __val);
145  }
146 
147  inline void
148  __attribute__ ((__always_inline__))
149  __atomic_add_dispatch(_Atomic_word* __mem, int __val)
150  {
151  if (__is_single_threaded())
152  __atomic_add_single(__mem, __val);
153  else
154  __atomic_add(__mem, __val);
155  }
156 
157 _GLIBCXX_END_NAMESPACE_VERSION
158 } // namespace
159 
160 // Even if the CPU doesn't need a memory barrier, we need to ensure
161 // that the compiler doesn't reorder memory accesses across the
162 // barriers.
163 #ifndef _GLIBCXX_READ_MEM_BARRIER
164 #define _GLIBCXX_READ_MEM_BARRIER __atomic_thread_fence (__ATOMIC_ACQUIRE)
165 #endif
166 #ifndef _GLIBCXX_WRITE_MEM_BARRIER
167 #define _GLIBCXX_WRITE_MEM_BARRIER __atomic_thread_fence (__ATOMIC_RELEASE)
168 #endif
169 
170 #endif
type_traits
atomic_word.h
c++config.h
__gnu_cxx
GNU extensions for public use.