OpenMPI 0.1.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

atomic.h
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
3 * University Research and Technology
4 * Corporation. All rights reserved.
5 * Copyright (c) 2004-2006 The University of Tennessee and The University
6 * of Tennessee Research Foundation. All rights
7 * reserved.
8 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9 * University of Stuttgart. All rights reserved.
10 * Copyright (c) 2004-2005 The Regents of the University of California.
11 * All rights reserved.
12 * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
13 * Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
14 * $COPYRIGHT$
15 *
16 * Additional copyrights may follow
17 *
18 * $HEADER$
19 */
20
21 /** @file
22 *
23 * Atomic operations.
24 *
25 * This API is patterned after the FreeBSD kernel atomic interface
26 * (which is influenced by Intel's ia64 architecture). The
27 * FreeBSD interface is documented at
28 *
29 * http://www.freebsd.org/cgi/man.cgi?query=atomic&sektion=9
30 *
31 * Only the necessary subset of functions are implemented here.
32 *
33 * The following #defines will be true / false based on
34 * assembly support:
35 *
36 * - \c OPAL_HAVE_ATOMIC_MEM_BARRIER atomic memory barriers
37 * - \c OPAL_HAVE_ATOMIC_SPINLOCKS atomic spinlocks
38 * - \c OPAL_HAVE_ATOMIC_MATH_32 if 32 bit add/sub/cmpset can be done "atomicly"
39 * - \c OPAL_HAVE_ATOMIC_MATH_64 if 32 bit add/sub/cmpset can be done "atomicly"
40 *
41 * Note that for the Atomic math, atomic add/sub may be implemented as
42 * C code using opal_atomic_cmpset. The appearance of atomic
43 * operation will be upheld in these cases.
44 */
45
46 #ifndef OPAL_SYS_ATOMIC_H
47 #define OPAL_SYS_ATOMIC_H 1
48
49 #include "opal_config.h"
50
51 #include "opal/sys/architecture.h"
52
53 #ifdef HAVE_SYS_TYPES_H
54 #include <sys/types.h>
55 #endif
56
57 /* do some quick #define cleanup in cases where we are doing
58 testing... */
59 #ifdef OMPI_DISABLE_INLINE_ASM
60 #undef OPAL_C_GCC_INLINE_ASSEMBLY
61 #define OPAL_C_GCC_INLINE_ASSEMBLY 0
62 #undef OMPI_CXX_GCC_INLINE_ASSEMBLY
63 #define OMPI_CXX_GCC_INLINE_ASSEMBLY 0
64 #undef OPAL_C_DEC_INLINE_ASSEMBLY
65 #define OPAL_C_DEC_INLINE_ASSEMBLY 0
66 #undef OMPI_CXX_DEC_INLINE_ASSEMBLY
67 #define OMPI_CXX_DEC_INLINE_ASSEMBLY 0
68 #undef OPAL_C_XLC_INLINE_ASSEMBLY
69 #define OPAL_C_XLC_INLINE_ASSEMBLY 0
70 #undef OMPI_CXX_XLC_INLINE_ASSEMBLY
71 #define OMPI_CXX_XLC_INLINE_ASSEMBLY 0
72 #endif
73
74 /* define OMPI_{GCC,DEC,XLC}_INLINE_ASSEMBLY based on the
75 OMPI_{C,CXX}_{GCC,DEC,XLC}_INLINE_ASSEMBLY defines and whether we
76 are in C or C++ */
77 #if defined(c_plusplus) || defined(__cplusplus)
78 #define OMPI_GCC_INLINE_ASSEMBLY OMPI_CXX_GCC_INLINE_ASSEMBLY
79 #define OMPI_DEC_INLINE_ASSEMBLY OMPI_CXX_DEC_INLINE_ASSEMBLY
80 #define OMPI_XLC_INLINE_ASSEMBLY OMPI_CXX_XLC_INLINE_ASSEMBLY
81 #else
82 #define OMPI_GCC_INLINE_ASSEMBLY OPAL_C_GCC_INLINE_ASSEMBLY
83 #define OMPI_DEC_INLINE_ASSEMBLY OPAL_C_DEC_INLINE_ASSEMBLY
84 #define OMPI_XLC_INLINE_ASSEMBLY OPAL_C_XLC_INLINE_ASSEMBLY
85 #endif
86
87
88 BEGIN_C_DECLS
89 /**********************************************************************
90 *
91 * Data structures for atomic ops
92 *
93 *********************************************************************/
94 /**
95 * Volatile lock object (with optional padding).
96 *
97 * \note The internals of the lock are included here, but should be
98 * considered private. The implementation currently in use may choose
99 * to use an int or unsigned char as the lock value - the user is not
100 * informed either way.
101 */
102 struct opal_atomic_lock_t {
103 union {
104 volatile int32_t lock; /**< The lock address (an integer) */
105 volatile unsigned char sparc_lock; /**< The lock address on sparc */
106 char padding[sizeof(int)]; /**< Array for optional padding */
107 } u;
108 };
109 typedef struct opal_atomic_lock_t opal_atomic_lock_t;
110
111 /**********************************************************************
112 *
113 * Set or unset these macros in the architecture-specific atomic.h
114 * files if we need to specify them as inline or non-inline
115 *
116 *********************************************************************/
117 #if !OMPI_GCC_INLINE_ASSEMBLY
118 #define OPAL_HAVE_INLINE_ATOMIC_MEM_BARRIER 0
119 #define OPAL_HAVE_INLINE_ATOMIC_CMPSET_32 0
120 #define OPAL_HAVE_INLINE_ATOMIC_CMPSET_64 0
121 #define OPAL_HAVE_INLINE_ATOMIC_ADD_32 0
122 #define OPAL_HAVE_INLINE_ATOMIC_SUB_32 0
123 #define OPAL_HAVE_INLINE_ATOMIC_ADD_64 0
124 #define OPAL_HAVE_INLINE_ATOMIC_SUB_64 0
125 #define OPAL_HAVE_INLINE_ATOMIC_SWAP_32 0
126 #define OPAL_HAVE_INLINE_ATOMIC_SWAP_64 0
127 #else
128 #define OPAL_HAVE_INLINE_ATOMIC_MEM_BARRIER 1
129 #define OPAL_HAVE_INLINE_ATOMIC_CMPSET_32 1
130 #define OPAL_HAVE_INLINE_ATOMIC_CMPSET_64 1
131 #define OPAL_HAVE_INLINE_ATOMIC_ADD_32 1
132 #define OPAL_HAVE_INLINE_ATOMIC_SUB_32 1
133 #define OPAL_HAVE_INLINE_ATOMIC_ADD_64 1
134 #define OPAL_HAVE_INLINE_ATOMIC_SUB_64 1
135 #define OPAL_HAVE_INLINE_ATOMIC_SWAP_32 1
136 #define OPAL_HAVE_INLINE_ATOMIC_SWAP_64 1
137 #endif
138
139 /**********************************************************************
140 *
141 * Load the appropriate architecture files and set some reasonable
142 * default values for our support
143 *
144 *********************************************************************/
145 #if defined(DOXYGEN)
146 /* don't include system-level gorp when generating doxygen files */
147 #elif OPAL_ASSEMBLY_ARCH == OMPI_WINDOWS
148 /* windows first, as they have API-level primitives for this stuff */
149 #include "opal/sys/win32/atomic.h"
150 #elif OPAL_ASSEMBLY_ARCH == OMPI_ALPHA
151 #include "opal/sys/alpha/atomic.h"
152 #elif OPAL_ASSEMBLY_ARCH == OMPI_AMD64
153 #include "opal/sys/amd64/atomic.h"
154 #elif OPAL_ASSEMBLY_ARCH == OMPI_ARM
155 #include "opal/sys/arm/atomic.h"
156 #elif OPAL_ASSEMBLY_ARCH == OMPI_IA32
157 #include "opal/sys/ia32/atomic.h"
158 #elif OPAL_ASSEMBLY_ARCH == OMPI_IA64
159 #include "opal/sys/ia64/atomic.h"
160 #elif OPAL_ASSEMBLY_ARCH == OMPI_MIPS
161 #include "opal/sys/mips/atomic.h"
162 #elif OPAL_ASSEMBLY_ARCH == OMPI_POWERPC32
163 #include "opal/sys/powerpc/atomic.h"
164 #elif OPAL_ASSEMBLY_ARCH == OMPI_POWERPC64
165 #include "opal/sys/powerpc/atomic.h"
166 #elif OPAL_ASSEMBLY_ARCH == OMPI_SPARC
167 #include "opal/sys/sparc/atomic.h"
168 #elif OPAL_ASSEMBLY_ARCH == OMPI_SPARCV9_32
169 #include "opal/sys/sparcv9/atomic.h"
170 #elif OPAL_ASSEMBLY_ARCH == OMPI_SPARCV9_64
171 #include "opal/sys/sparcv9/atomic.h"
172 #elif OPAL_ASSEMBLY_ARCH == OMPI_SYNC_BUILTIN
173 #include "opal/sys/sync_builtin/atomic.h"
174 #endif
175
176 #ifndef DOXYGEN
177 /* compare and set operations can't really be emulated from software,
178 so if these defines aren't already set, they should be set to 0
179 now */
180 #ifndef OPAL_HAVE_ATOMIC_CMPSET_32
181 #define OPAL_HAVE_ATOMIC_CMPSET_32 0
182 #endif
183 #ifndef OPAL_HAVE_ATOMIC_CMPSET_64
184 #define OPAL_HAVE_ATOMIC_CMPSET_64 0
185 #endif
186 #endif /* DOXYGEN */
187
188 /**********************************************************************
189 *
190 * Memory Barriers - defined here if running doxygen or have barriers
191 * but can't inline
192 *
193 *********************************************************************/
194 #if !defined(OPAL_HAVE_ATOMIC_MEM_BARRIER) && !defined(DOXYGEN)
195 /* no way to emulate in C code */
196 #define OPAL_HAVE_ATOMIC_MEM_BARRIER 0
197 #endif
198
199 #if defined(DOXYGEN) || OPAL_HAVE_ATOMIC_MEM_BARRIER
200 /**
201 * Memory barrier
202 *
203 * Will use system-specific features to instruct the processor and
204 * memory controller that all writes and reads that have been posted
205 * before the call to \c opal_atomic_mb() must appear to have
206 * completed before the next read or write.
207 *
208 * \note This can have some expensive side effects, including flushing
209 * the pipeline, preventing the cpu from reordering instructions, and
210 * generally grinding the memory controller's performance. Use only
211 * if you need *both* read and write barriers.
212 */
213
214 #if OPAL_HAVE_INLINE_ATOMIC_MEM_BARRIER
215 static inline
216 #endif
217 void opal_atomic_mb(void);
218
219 /**
220 * Read memory barrier
221 *
222 * Use system-specific features to instruct the processor and memory
223 * conrtoller that all reads that have been posted before the call to
224 * \c opal_atomic_rmb() must appear to have been completed before the
225 * next read. Nothing is said about the ordering of writes when using
226 * \c opal_atomic_rmb().
227 */
228
229 #if OPAL_HAVE_INLINE_ATOMIC_MEM_BARRIER
230 static inline
231 #endif
232 void opal_atomic_rmb(void);
233
234 /**
235 * Write memory barrier.
236 *
237 * Use system-specific features to instruct the processor and memory
238 * conrtoller that all writes that have been posted before the call to
239 * \c opal_atomic_wmb() must appear to have been completed before the
240 * next write. Nothing is said about the ordering of reads when using
241 * \c opal_atomic_wmb().
242 */
243
244 #if OPAL_HAVE_INLINE_ATOMIC_MEM_BARRIER
245 static inline
246 #endif
247 void opal_atomic_wmb(void);
248
249 #endif /* defined(DOXYGEN) || OPAL_HAVE_ATOMIC_MEM_BARRIER */
250
251
252 /**********************************************************************
253 *
254 * Atomic spinlocks - always inlined, if have atomic cmpset
255 *
256 *********************************************************************/
257
258 #if !defined(OPAL_HAVE_ATOMIC_SPINLOCKS) && !defined(DOXYGEN)
259 /* 0 is more like "pending" - we'll fix up at the end after all
260 the static inline functions are declared */
261 #define OPAL_HAVE_ATOMIC_SPINLOCKS 0
262 #endif
263
264 #if defined(DOXYGEN) || OPAL_HAVE_ATOMIC_SPINLOCKS || (OPAL_HAVE_ATOMIC_CMPSET_32 || OPAL_HAVE_ATOMIC_CMPSET_64)
265
266 /**
267 * Enumeration of lock states
268 */
269 enum {
270 OPAL_ATOMIC_UNLOCKED = 0,
271 OPAL_ATOMIC_LOCKED = 1
272 };
273
274
275 /**
276 * Initialize a lock to value
277 *
278 * @param lock Address of the lock
279 * @param value Initial value to set lock to
280 */
281 #if OPAL_HAVE_ATOMIC_SPINLOCKS == 0
282 static inline
283 #endif
284 void opal_atomic_init(opal_atomic_lock_t* lock, int32_t value);
285
286
287 /**
288 * Try to acquire a lock.
289 *
290 * @param lock Address of the lock.
291 * @return 0 if the lock was acquired, 1 otherwise.
292 */
293 #if OPAL_HAVE_ATOMIC_SPINLOCKS == 0
294 static inline
295 #endif
296 int opal_atomic_trylock(opal_atomic_lock_t *lock);
297
298
299 /**
300 * Acquire a lock by spinning.
301 *
302 * @param lock Address of the lock.
303 */
304 #if OPAL_HAVE_ATOMIC_SPINLOCKS == 0
305 static inline
306 #endif
307 void opal_atomic_lock(opal_atomic_lock_t *lock);
308
309
310 /**
311 * Release a lock.
312 *
313 * @param lock Address of the lock.
314 */
315 #if OPAL_HAVE_ATOMIC_SPINLOCKS == 0
316 static inline
317 #endif
318 void opal_atomic_unlock(opal_atomic_lock_t *lock);
319
320
321 #if OPAL_HAVE_ATOMIC_SPINLOCKS == 0
322 #undef OPAL_HAVE_ATOMIC_SPINLOCKS
323 #define OPAL_HAVE_ATOMIC_SPINLOCKS (OPAL_HAVE_ATOMIC_CMPSET_32 || OPAL_HAVE_ATOMIC_CMPSET_64)
324 #define OPAL_NEED_INLINE_ATOMIC_SPINLOCKS
325 #endif
326
327 #endif /* OPAL_HAVE_ATOMIC_SPINLOCKS */
328
329
330 /**********************************************************************
331 *
332 * Atomic math operations
333 *
334 *********************************************************************/
335 #if !defined(OPAL_HAVE_ATOMIC_CMPSET_32) && !defined(DOXYGEN)
336 #define OPAL_HAVE_ATOMIC_CMPSET_32 0
337 #endif
338 #if defined(DOXYGEN) || OPAL_HAVE_ATOMIC_CMPSET_32
339
340 #if OPAL_HAVE_INLINE_ATOMIC_CMPSET_32
341 static inline
342 #endif
343 int opal_atomic_cmpset_32(volatile int32_t *addr, int32_t oldval,
344 int32_t newval);
345
346 #if OPAL_HAVE_INLINE_ATOMIC_CMPSET_32
347 static inline
348 #endif
349 int opal_atomic_cmpset_acq_32(volatile int32_t *addr, int32_t oldval,
350 int32_t newval);
351
352 #if OPAL_HAVE_INLINE_ATOMIC_CMPSET_32
353 static inline
354 #endif
355 int opal_atomic_cmpset_rel_32(volatile int32_t *addr, int32_t oldval,
356 int32_t newval);
357 #endif
358
359
360 #if !defined(OPAL_HAVE_ATOMIC_CMPSET_64) && !defined(DOXYGEN)
361 #define OPAL_HAVE_ATOMIC_CMPSET_64 0
362 #endif
363 #if defined(DOXYGEN) || OPAL_HAVE_ATOMIC_CMPSET_64
364
365 #if OPAL_HAVE_INLINE_ATOMIC_CMPSET_64
366 static inline
367 #endif
368 int opal_atomic_cmpset_64(volatile int64_t *addr, int64_t oldval,
369 int64_t newval);
370
371 #if OPAL_HAVE_INLINE_ATOMIC_CMPSET_64
372 static inline
373 #endif
374 int opal_atomic_cmpset_acq_64(volatile int64_t *addr, int64_t oldval,
375 int64_t newval);
376
377 #if OPAL_HAVE_INLINE_ATOMIC_CMPSET_64
378 static inline
379 #endif
380 int opal_atomic_cmpset_rel_64(volatile int64_t *addr, int64_t oldval,
381 int64_t newval);
382
383 #endif
384
385 #if !defined(OPAL_HAVE_ATOMIC_MATH_32) && !defined(DOXYGEN)
386 /* define to 0 for these tests. WIll fix up later. */
387 #define OPAL_HAVE_ATOMIC_MATH_32 0
388 #endif
389
390 #if defined(DOXYGEN) || OPAL_HAVE_ATOMIC_MATH_32 || OPAL_HAVE_ATOMIC_CMPSET_32
391
392 /* OPAL_HAVE_INLINE_ATOMIC_*_32 will be 1 if <arch>/atomic.h provides
393 a static inline version of it (in assembly). If it's 0 but
394 OPAL_HAVE_ATOMIC_CMPSET_32 is 1, then atomic_impl.h (below) will
395 define a static inline version of it (in C, using
396 atomic_cmpset_32()). */
397 #if OPAL_HAVE_INLINE_ATOMIC_ADD_32 || OPAL_HAVE_ATOMIC_CMPSET_32
398 static inline
399 #endif
400 int32_t opal_atomic_add_32(volatile int32_t *addr, int delta);
401
402 /* OPAL_HAVE_INLINE_ATOMIC_*_32 will be 1 if <arch>/atomic.h provides
403 a static inline version of it (in assembly). If it's 0 but
404 OPAL_HAVE_ATOMIC_CMPSET_32 is 1, then atomic_impl.h (below) will
405 define a static inline version of it (in C, using
406 atomic_cmpset_32()). */
407 #if OPAL_HAVE_INLINE_ATOMIC_SUB_32 || OPAL_HAVE_ATOMIC_CMPSET_32
408 static inline
409 #endif
410 int32_t opal_atomic_sub_32(volatile int32_t *addr, int delta);
411
412 #endif /* OPAL_HAVE_ATOMIC_MATH_32 */
413
414 #if ! OPAL_HAVE_ATOMIC_MATH_32
415 /* fix up the value of ompi_have_atomic_math_32 to allow for C versions */
416 #undef OPAL_HAVE_ATOMIC_MATH_32
417 #define OPAL_HAVE_ATOMIC_MATH_32 OPAL_HAVE_ATOMIC_CMPSET_32
418 #endif
419
420 #ifndef OPAL_HAVE_ATOMIC_MATH_64
421 /* define to 0 for these tests. WIll fix up later. */
422 #define OPAL_HAVE_ATOMIC_MATH_64 0
423 #endif
424
425 #if defined(DOXYGEN) || OPAL_HAVE_ATOMIC_MATH_64 || OPAL_HAVE_ATOMIC_CMPSET_64
426
427 /* OPAL_HAVE_INLINE_ATOMIC_*_64 will be 1 if <arch>/atomic.h provides
428 a static inline version of it (in assembly). If it's 0 but
429 OPAL_HAVE_ATOMIC_CMPSET_64 is 1, then atomic_impl.h (below) will
430 define a static inline version of it (in C, using
431 atomic_cmpset_64()). */
432 #if OPAL_HAVE_INLINE_ATOMIC_ADD_64 || OPAL_HAVE_ATOMIC_CMPSET_64
433 static inline
434 #endif
435 int64_t opal_atomic_add_64(volatile int64_t *addr, int64_t delta);
436
437 /* OPAL_HAVE_INLINE_ATOMIC_*_64 will be 1 if <arch>/atomic.h provides
438 a static inline version of it (in assembly). If it's 0 but
439 OPAL_HAVE_ATOMIC_CMPSET_64 is 1, then atomic_impl.h (below) will
440 define a static inline version of it (in C, using
441 atomic_cmpset_64()). */
442 #if OPAL_HAVE_INLINE_ATOMIC_SUB_64 || OPAL_HAVE_ATOMIC_CMPSET_64
443 static inline
444 #endif
445 int64_t opal_atomic_sub_64(volatile int64_t *addr, int64_t delta);
446
447 #endif /* OPAL_HAVE_ATOMIC_MATH_32 */
448
449 #if ! OPAL_HAVE_ATOMIC_MATH_64
450 /* fix up the value of ompi_have_atomic_math_64 to allow for C versions */
451 #undef OPAL_HAVE_ATOMIC_MATH_64
452 #define OPAL_HAVE_ATOMIC_MATH_64 OPAL_HAVE_ATOMIC_CMPSET_64
453 #endif
454
455 /* provide a size_t add/subtract. When in debug mode, make it an
456 * inline function so that we don't have any casts in the
457 * interface and can catch type errors. When not in debug mode,
458 * just make it a macro, so that there's no performance penalty
459 */
460 #if defined(DOXYGEN) || OPAL_ENABLE_DEBUG
461 static inline size_t
462 opal_atomic_add_size_t(volatile size_t *addr, int delta)
463 {
464 #if SIZEOF_SIZE_T == 4
465 return (size_t) opal_atomic_add_32((int32_t*) addr, delta);
466 #elif SIZEOF_SIZE_T == 8
467 return (size_t) opal_atomic_add_64((int64_t*) addr, delta);
468 #else
469 #error "Unknown size_t size"
470 #endif
471 }
472 static inline size_t
473 opal_atomic_sub_size_t(volatile size_t *addr, int delta)
474 {
475 #if SIZEOF_SIZE_T == 4
476 return (size_t) opal_atomic_sub_32((int32_t*) addr, delta);
477 #elif SIZEOF_SIZE_T == 8
478 return (size_t) opal_atomic_sub_64((int64_t*) addr, delta);
479 #else
480 #error "Unknown size_t size"
481 #endif
482 }
483 #else
484 #if SIZEOF_SIZE_T == 4
485 #define opal_atomic_add_size_t(addr, delta) ((size_t) opal_atomic_add_32((int32_t*) addr, delta))
486 #define opal_atomic_sub_size_t(addr, delta) ((size_t) opal_atomic_sub_32((int32_t*) addr, delta))
487 #elif SIZEOF_SIZE_T ==8
488 #define opal_atomic_add_size_t(addr, delta) ((size_t) opal_atomic_add_64((int64_t*) addr, delta))
489 #define opal_atomic_sub_size_t(addr, delta) ((size_t) opal_atomic_sub_64((int64_t*) addr, delta))
490 #else
491 #error "Unknown size_t size"
492 #endif
493 #endif
494
495 #if defined(DOXYGEN) || (OPAL_HAVE_ATOMIC_CMPSET_32 || OPAL_HAVE_ATOMIC_CMPSET_64)
496 /* these are always done with inline functions, so always mark as
497 static inline */
498 static inline int opal_atomic_cmpset_xx(volatile void* addr, int64_t oldval,
499 int64_t newval, size_t length);
500 static inline int opal_atomic_cmpset_acq_xx(volatile void* addr,
501 int64_t oldval, int64_t newval,
502 size_t length);
503 static inline int opal_atomic_cmpset_rel_xx(volatile void* addr,
504 int64_t oldval, int64_t newval,
505 size_t length);
506
507 static inline int opal_atomic_cmpset_ptr(volatile void* addr,
508 void* oldval,
509 void* newval);
510 static inline int opal_atomic_cmpset_acq_ptr(volatile void* addr,
511 void* oldval,
512 void* newval);
513 static inline int opal_atomic_cmpset_rel_ptr(volatile void* addr,
514 void* oldval,
515 void* newval);
516
517 /**
518 * Atomic compare and set of pointer with relaxed semantics. This
519 * macro detect at compile time the type of the first argument and
520 * choose the correct function to be called.
521 *
522 * \note This macro should only be used for integer types.
523 *
524 * @param addr Address of <TYPE>.
525 * @param oldval Comparison value <TYPE>.
526 * @param newval New value to set if comparision is true <TYPE>.
527 *
528 * See opal_atomic_cmpset_* for pseudo-code.
529 */
530 #define opal_atomic_cmpset( ADDR, OLDVAL, NEWVAL ) \
531 opal_atomic_cmpset_xx( (volatile void*)(ADDR), (intptr_t)(OLDVAL), \
532 (intptr_t)(NEWVAL), sizeof(*(ADDR)) )
533
534 /**
535 * Atomic compare and set of pointer with acquire semantics. This
536 * macro detect at compile time the type of the first argument
537 * and choose the correct function to be called.
538 *
539 * \note This macro should only be used for integer types.
540 *
541 * @param addr Address of <TYPE>.
542 * @param oldval Comparison value <TYPE>.
543 * @param newval New value to set if comparision is true <TYPE>.
544 *
545 * See opal_atomic_cmpset_acq_* for pseudo-code.
546 */
547 #define opal_atomic_cmpset_acq( ADDR, OLDVAL, NEWVAL ) \
548 opal_atomic_cmpset_acq_xx( (volatile void*)(ADDR), (int64_t)(OLDVAL), \
549 (int64_t)(NEWVAL), sizeof(*(ADDR)) )
550
551
552 /**
553 * Atomic compare and set of pointer with release semantics. This
554 * macro detect at compile time the type of the first argument
555 * and choose the correct function to b
556 *
557 * \note This macro should only be used for integer types.
558 *
559 * @param addr Address of <TYPE>.
560 * @param oldval Comparison value <TYPE>.
561 * @param newval New value to set if comparision is true <TYPE>.
562 *
563 * See opal_atomic_cmpsetrel_* for pseudo-code.
564 */
565 #define opal_atomic_cmpset_rel( ADDR, OLDVAL, NEWVAL ) \
566 opal_atomic_cmpset_rel_xx( (volatile void*)(ADDR), (int64_t)(OLDVAL), \
567 (int64_t)(NEWVAL), sizeof(*(ADDR)) )
568
569 #endif /* (OPAL_HAVE_ATOMIC_CMPSET_32 || OPAL_HAVE_ATOMIC_CMPSET_64) */
570
571 #if defined(DOXYGEN) || (OPAL_HAVE_ATOMIC_MATH_32 || OPAL_HAVE_ATOMIC_MATH_64)
572
573 static inline void opal_atomic_add_xx(volatile void* addr,
574 int32_t value, size_t length);
575 static inline void opal_atomic_sub_xx(volatile void* addr,
576 int32_t value, size_t length);
577 #if SIZEOF_VOID_P == 4 && OPAL_HAVE_ATOMIC_CMPSET_32
578 static inline int32_t opal_atomic_add_ptr( volatile void* addr, void* delta );
579 static inline int32_t opal_atomic_sub_ptr( volatile void* addr, void* delta );
580 #elif SIZEOF_VOID_P == 8 && OPAL_HAVE_ATOMIC_CMPSET_64
581 static inline int64_t opal_atomic_add_ptr( volatile void* addr, void* delta );
582 static inline int64_t opal_atomic_sub_ptr( volatile void* addr, void* delta );
583 #else
584 #error Atomic arithmetic on pointers not supported
585 #endif
586
587 /**
588 * Atomically increment the content depending on the type. This
589 * macro detect at compile time the type of the first argument
590 * and choose the correct function to be called.
591 *
592 * \note This macro should only be used for integer types.
593 *
594 * @param addr Address of <TYPE>
595 * @param delta Value to add (converted to <TYPE>).
596 */
597 #define opal_atomic_add( ADDR, VALUE ) \
598 opal_atomic_add_xx( (volatile void*)(ADDR), (int32_t)(VALUE), \
599 sizeof(*(ADDR)) )
600
601 /**
602 * Atomically decrement the content depending on the type. This
603 * macro detect at compile time the type of the first argument
604 * and choose the correct function to be called.
605 *
606 * \note This macro should only be used for integer types.
607 *
608 * @param addr Address of <TYPE>
609 * @param delta Value to substract (converted to <TYPE>).
610 */
611 #define opal_atomic_sub( ADDR, VALUE ) \
612 opal_atomic_sub_xx( (volatile void*)(ADDR), (int32_t)(VALUE), \
613 sizeof(*(ADDR)) )
614
615 #endif /* OPAL_HAVE_ATOMIC_MATH_32 || OPAL_HAVE_ATOMIC_MATH_64 */
616
617
618 /**********************************************************************
619 *
620 * Include system specific inline asm definitions. Otherwise
621 * the definitions are in system specific .s files in src/util.
622 *
623 *********************************************************************/
624 #include "opal/sys/atomic_impl.h"
625
626 END_C_DECLS
627
628 #endif /* OPAL_SYS_ATOMIC_H */
opal_atomic_lock_t::sparc_lock
volatile unsigned char sparc_lock
The lock address on sparc.
Definition: atomic.h:105
opal_atomic_rmb
void opal_atomic_rmb(void)
Read memory barrier.
opal_atomic_lock_t
Volatile lock object (with optional padding).
Definition: atomic.h:102
opal_atomic_unlock
static void opal_atomic_unlock(opal_atomic_lock_t *lock)
Release a lock.
opal_atomic_mb
void opal_atomic_mb(void)
Memory barrier.
opal_atomic_lock
static void opal_atomic_lock(opal_atomic_lock_t *lock)
Acquire a lock by spinning.
opal_atomic_wmb
void opal_atomic_wmb(void)
Write memory barrier.
opal_atomic_init
static void opal_atomic_init(opal_atomic_lock_t *lock, int32_t value)
Initialize a lock to value.
opal_atomic_lock_t::lock
volatile int32_t lock
The lock address (an integer)
Definition: atomic.h:104
opal_atomic_trylock
static int opal_atomic_trylock(opal_atomic_lock_t *lock)
Try to acquire a lock.
opal_atomic_lock_t::padding
char padding[sizeof(int)]
Array for optional padding.
Definition: atomic.h:106