NCBI C++ ToolKit
ncbi_atomic_defs.h
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef CORELIB___NCBI_ATOMIC_DEFS__HPP
2 #define CORELIB___NCBI_ATOMIC_DEFS__HPP
3 
4 /* $Id: ncbi_atomic_defs.h 92509 2021-01-26 19:30:05Z ucko $
5 * ===========================================================================
6 *
7 * PUBLIC DOMAIN NOTICE
8 * National Center for Biotechnology Information
9 *
10 * This software/database is a "United States Government Work" under the
11 * terms of the United States Copyright Act. It was written as part of
12 * the author's official duties as a United States Government employee and
13 * thus cannot be copyrighted. This software/database is freely available
14 * to the public for use. The National Library of Medicine and the U.S.
15 * Government have not placed any restriction on its use or reproduction.
16 *
17 * Although all reasonable efforts have been taken to ensure the accuracy
18 * and reliability of the software and data, the NLM and the U.S.
19 * Government do not and cannot warrant the performance or results that
20 * may be obtained by using this software or data. The NLM and the U.S.
21 * Government disclaim all warranties, express or implied, including
22 * warranties of performance, merchantability or fitness for any particular
23 * purpose.
24 *
25 * Please cite the author in any work or product based on this material.
26 *
27 * ===========================================================================
28 *
29 * Author: Aaron Ucko
30 *
31 */
32 
33 /** @file ncbi_atomic_defs.h
34  * (Highly!) platform-specific configuration for low-level atomic
35  * operations (reference-count manipulation, pointer swapping).
36  */
37 
38 #include <ncbiconf.h>
39 
40 /** @addtogroup Threads
41  *
42  * @{
43  */
44 
45 #if (defined(HAVE_SCHED_YIELD) || defined(NCBI_OS_MSWIN)) \
46  && !defined(NCBI_NO_THREADS)
47 # if defined(__cplusplus) && defined(NCBI_OS_DARWIN)
48 /* Mac OS X 10.2 and older failed to protect sched.h properly. :-/ */
49 extern "C" {
50 # include <sched.h>
51 }
52 # elif !defined(NCBI_OS_MSWIN)
53 # include <sched.h>
54 # endif
55 # if defined(NCBI_OS_MSWIN)
56 # define NCBI_SCHED_YIELD() ::SwitchToThread()
57 # define NCBI_SCHED_SPIN_INIT() int spin_counter = 0
58 # define NCBI_SCHED_SPIN_YIELD() if ( !(++spin_counter & 3) ) ::SwitchToThread()
59 # else
60 # define NCBI_SCHED_YIELD() sched_yield()
61 # define NCBI_SCHED_SPIN_INIT() int spin_counter = 0
62 # define NCBI_SCHED_SPIN_YIELD() if ( !(++spin_counter & 3) ) sched_yield()
63 # endif
64 #else
65 # define NCBI_SCHED_YIELD()
66 # define NCBI_SCHED_SPIN_INIT()
67 # define NCBI_SCHED_SPIN_YIELD()
68 #endif
69 
70 #undef NCBI_COUNTER_UNSIGNED
71 #undef NCBI_COUNTER_RESERVED_VALUE
72 #undef NCBI_COUNTER_ASM_OK
73 #undef NCBI_COUNTER_USE_ASM
74 #undef NCBI_COUNTER_USE_STD_ATOMIC
75 #undef NCBI_COUNTER_ADD
76 #undef NCBI_COUNTER_NEED_MUTEX
77 #undef NCBI_SWAP_POINTERS
78 #undef NCBI_SWAP_POINTERS_CONDITIONALLY
79 #undef NCBI_SWAP_POINTERS_EXTERN
80 #undef NCBI_SLOW_ATOMIC_SWAP
81 
82 #if defined(NCBI_COMPILER_GCC) || defined(NCBI_COMPILER_WORKSHOP) \
83  || (defined(NCBI_COMPILER_KCC) && defined(NCBI_OS_LINUX)) \
84  || defined(NCBI_COMPILER_ICC) || defined(NCBI_COMPILER_ANY_CLANG)
85 # define NCBI_COUNTER_ASM_OK 1
86 #endif
87 
88 #ifdef __cplusplus
89 # include <cstdlib> /* determine C++ standard library version */
90 #endif
91 
92 #if defined(NCBI_TCHECK)
93 # define NCBI_SWAP_POINTERS_EXTERN 1
94 #endif
95 
96 #if defined(NCBI_HAVE_CXX11) && !defined(NCBI_COMPILER_MSVC)
97 # include <atomic>
98 #endif
99 
100 /**
101  * Define platform specific atomic-operations macros/values.
102  *
103  * TNCBIAtomicValue "type" is defined based on facilities available for a
104  * compiler/platform. TNCBIAtomicValue is used in the CAtomicCounter class
105  * for defining the internal represntation of the counter.
106  *
107  * Where possible NCBI_COUNTER_ADD is defined in terms of compiler/platform
108  * specific features, favoring inline assembly over standard library calls
109  * as function-call overhead can be appreciable, particularly on x86.
110  */
111 #ifdef NCBI_NO_THREADS
112  typedef size_t TNCBIAtomicValue;
113 # if SIZEOF_SIZE_T == 8
114 # define NCBI_COUNTER_64_BIT 1
115 # endif
116 # define NCBI_COUNTER_UNSIGNED 1
117 # define NCBI_COUNTER_ADD(p, d) ((*p) += d)
118 #elif (defined(NCBI_COMPILER_GCC) || defined(NCBI_COMPILER_ICC) || \
119  defined(NCBI_COMPILER_ANY_CLANG)) && \
120  (defined(__i386) || defined(__sparc) || defined(__x86_64) || \
121  defined(__aarch64__)) && \
122  (!defined(__GLIBCXX__) || !defined(NCBI_TCHECK))
123 # if defined(__x86_64) || defined(__aarch64__)
124 # define NCBI_COUNTER_64_BIT
125 # endif
126 # ifdef NCBI_COUNTER_64_BIT
127  typedef size_t TNCBIAtomicValue;
128 # else
129  typedef unsigned int TNCBIAtomicValue;
130 # endif
131 # define NCBI_COUNTER_UNSIGNED 1
132 # define NCBI_COUNTER_USE_ASM 1
133 # if defined(__sparc) && !defined(__sparcv9)
134 # define NCBI_COUNTER_RESERVED_VALUE 0x3FFFFFFF
135 # endif
136 #elif defined(NCBI_HAVE_CXX11) && !defined(NCBI_COMPILER_MSVC)
137  /* std::atomic<> in MSVC has non-default constructor so
138  static CAtomicCounter couldn't be initialized in MT-safe manner */
139  typedef size_t TNCBIAtomicValue;
140 # if SIZEOF_SIZE_T == 8
141 # define NCBI_COUNTER_64_BIT 1
142 # endif
143 # define NCBI_ATOMIC_TYPE(t) std::atomic<t>
144 # define NCBI_COUNTER_UNSIGNED 1
145 # define NCBI_COUNTER_USE_STD_ATOMIC 1
146 # define NCBI_COUNTER_ADD(p, d) ((*p) += d)
147 #elif defined(NCBI_OS_SOLARIS) && defined(HAVE_ATOMIC_H) /* Solaris 10+. */
148 # include <atomic.h>
149 # ifndef NCBI_COUNTER_ADD
150  typedef uint32_t TNCBIAtomicValue;
151 # define NCBI_COUNTER_UNSIGNED 1
152 # define NCBI_COUNTER_ADD(p, d) atomic_add_32_nv(p, d)
153 # endif
154  /* Some systems have old, incomplete(!) versions of (sys/)atomic.h. :-/ */
155 # ifndef _SYS_ATOMIC_H
156  extern
157 # ifdef __cplusplus
158  "C"
159 # endif
160  void *atomic_swap_ptr(volatile void *, void *);
161 # endif
162 # define NCBI_SWAP_POINTERS(loc, nv) atomic_swap_ptr(loc, nv)
163 #elif defined(NCBI_COMPILER_WORKSHOP)
164 # ifdef __cplusplus
165 extern "C" {
166 # endif
167 # ifdef __sparcv9
168  typedef unsigned int TNCBIAtomicValue;
169 # define NCBI_COUNTER_UNSIGNED 1
170  TNCBIAtomicValue NCBICORE_asm_cas(TNCBIAtomicValue new_value,
171  TNCBIAtomicValue* address,
172  TNCBIAtomicValue old_value);
173  void* NCBICORE_asm_casx(void* new_value, void** location, void* old_value);
174 # define NCBI_SWAP_POINTERS_CONDITIONALLY(loc, ov, nv) \
175  (NCBICORE_asm_casx(nv, loc, ov) == ov)
176 # define NCBI_SWAP_POINTERS_EXTERN 1
177 # elif defined(__sparc)
178  typedef unsigned int TNCBIAtomicValue;
179 # define NCBI_COUNTER_RESERVED_VALUE 0x3FFFFFFF
180 # define NCBI_COUNTER_UNSIGNED 1
181  TNCBIAtomicValue NCBICORE_asm_swap(TNCBIAtomicValue new_value,
182  TNCBIAtomicValue* address);
183 # define NCBI_SWAP_POINTERS(loc, nv) \
184  ((void*))(NCBICORE_asm_swap((TNCBIAtomicValue)(nv), \
185  (TNCBIAtomicValue*)(loc)))
186 # define NCBI_SWAP_POINTERS_EXTERN 1
187 # elif defined(__x86_64)
188  typedef unsigned int TNCBIAtomicValue;
189 # define NCBI_COUNTER_UNSIGNED 1
190  TNCBIAtomicValue NCBICORE_asm_lock_xaddl_64(TNCBIAtomicValue* address,
191  int delta);
192  void* NCBICORE_asm_xchgq(void* new_value, void** location);
193 # define NCBI_COUNTER_ADD(p, d) (NCBICORE_asm_lock_xaddl_64(p, d) + d)
194 # define NCBI_COUNTER_USE_EXTERN_ASM 1
195 # define NCBI_SWAP_POINTERS(loc, nv) NCBICORE_asm_xchgq(nv, loc)
196 # define NCBI_SWAP_POINTERS_EXTERN 1
197 # elif defined(__i386)
198  typedef unsigned int TNCBIAtomicValue;
199 # define NCBI_COUNTER_UNSIGNED 1
200  TNCBIAtomicValue NCBICORE_asm_lock_xaddl(TNCBIAtomicValue* address,
201  int delta);
202  void* NCBICORE_asm_xchg(void* new_value, void** location);
203 # define NCBI_COUNTER_ADD(p, d) (NCBICORE_asm_lock_xaddl(p, d) + d)
204 # define NCBI_COUNTER_USE_EXTERN_ASM 1
205 # define NCBI_SWAP_POINTERS(loc, nv) NCBICORE_asm_xchg(nv, loc)
206 # define NCBI_SWAP_POINTERS_EXTERN 1
207 # else
208 # undef NCBI_COUNTER_ASM_OK
209 # endif
210 # ifdef __cplusplus
211 }
212 # endif
213 #elif defined(_CXXCONFIG)
214 # include <ext/atomicity.h>
215  typedef _Atomic_word TNCBIAtomicValue;
216 # define NCBI_COUNTER_ADD(p, d) (__gnu_cxx::__exchange_and_add(p, d) + d)
217 #elif defined(NCBI_COMPILER_COMPAQ)
218 # include <machine/builtins.h>
219  typedef int TNCBIAtomicValue;
220 # define NCBI_COUNTER_ADD(p, d) (__ATOMIC_ADD_LONG(p, d) + d)
221 # define NCBI_SWAP_POINTERS(loc, nv) \
222  ((void*)(__ATOMIC_EXCH_QUAD((loc), (long)(nv))))
223 #endif
224 
225 #if defined(NCBI_NO_THREADS)
226 /* Already handled, but checked again here to avoid extra indentation */
227 #elif defined(NCBI_OS_IRIX)
228 # include <mutex.h>
229 # ifndef NCBI_COUNTER_ADD
230  typedef __uint32_t TNCBIAtomicValue;
231 # define NCBI_COUNTER_UNSIGNED 1
232 # define NCBI_COUNTER_ADD(p, d) add_then_test32(p, d)
233 # endif
234 # define NCBI_SWAP_POINTERS(loc, nv) \
235  ((void*) (test_and_set((unsigned long*)(loc), (unsigned long)(nv))))
236 #elif defined(NCBI_OS_AIX)
237 # include <sys/atomic_op.h>
238 # ifndef NCBI_COUNTER_ADD
239  typedef int TNCBIAtomicValue;
240 # define NCBI_COUNTER_ADD(p, d) (fetch_and_add(p, d) + d)
241 # endif
242 # define NCBI_SWAP_POINTERS_CONDITIONALLY(loc, ov, nv) \
243  (compare_and_swap((atomic_p)(loc), (int*)(&(ov)), (int)(nv)) != FALSE)
244 #elif defined(NCBI_OS_DARWIN) && 0 /* even CarbonCore is deprecated */
245 # include <CarbonCore/DriverSynchronization.h>
246 # if !defined(NCBI_COUNTER_ADD) && !defined(NCBI_COUNTER_USE_ASM)
247  typedef SInt32 TNCBIAtomicValue;
248 # define NCBI_COUNTER_ADD(p, d) (AddAtomic(d, p) + d)
249 # endif
250 # if SIZEOF_VOIDP == 4
251 # define NCBI_SWAP_POINTERS_CONDITIONALLY(loc, ov, nv) \
252  CompareAndSwap((UInt32)(ov), (UInt32)(nv), (UInt32*)(loc))
253 # endif
254 #elif defined(NCBI_OS_MSWIN)
256 # if !defined(NCBI_COUNTER_ADD) && !defined(NCBI_COUNTER_USE_ASM)
257 # if NCBI_PLATFORM_BITS >= 64
258 # define NCBI_COUNTER_64_BIT
259 # endif
260 # ifdef NCBI_COUNTER_64_BIT
261  typedef LONGLONG TNCBIAtomicValue;
262 # define NCBI_COUNTER_ADD(p, d) (InterlockedExchangeAdd64(p, d) + d)
263 # else
264  typedef LONG TNCBIAtomicValue;
265 # define NCBI_COUNTER_ADD(p, d) (InterlockedExchangeAdd(p, d) + d)
266 # endif
267 # endif
268 # define NCBI_SWAP_POINTERS(loc, nv) (InterlockedExchangePointer(loc, nv))
269 #elif !defined(NCBI_COUNTER_ADD) && !defined(NCBI_COUNTER_USE_ASM)
270  typedef unsigned int TNCBIAtomicValue;
271 # define NCBI_COUNTER_UNSIGNED 1
272 # if defined (NCBI_COUNTER_ASM_OK) && (defined(__i386) || defined(__sparc) || defined(__x86_64))
273 # define NCBI_COUNTER_USE_ASM 1
274 # else
275 # define NCBI_COUNTER_NEED_MUTEX 1
276 # endif
277 #endif
278 
279 #if !defined(NCBI_SWAP_POINTERS) \
280  && !defined(NCBI_SWAP_POINTERS_CONDITIONALLY) \
281  && !defined(NCBI_NO_THREADS) \
282  && (!defined(NCBI_COUNTER_ASM_OK) \
283  || (!defined(__i386) && !defined(__powerpc__) \
284  && !defined(__powerpc64__) && !defined(__ppc__) \
285  && !defined(__ppc64__) && !defined(__sparc) \
286  && !defined(__x86_64) && !defined(__aarch64__)))
287 # define NCBI_SWAP_POINTERS_EXTERN 1
288 # define NCBI_SLOW_ATOMIC_SWAP 1
289 #endif
290 
291 #ifndef NCBI_ATOMIC_TYPE
292 # define NCBI_ATOMIC_TYPE(t) t
293 #endif
294 
295 /* @} */
296 
297 #endif /* CORELIB___NCBI_ATOMIC_DEFS__HPP */
static const char location[]
Definition: config.c:97
Uint4 uint32_t
size_t TNCBIAtomicValue
Define platform specific atomic-operations macros/values.
Defines some MS Windows specifics for our "C" code.
Front end for a platform-specific configuration summary.
Int4 delta(size_t dimension_, const Int4 *score_)
Modified on Sun Apr 28 04:48:57 2024 by modify_doxy.py rev. 669887