This source file includes following definitions.
- opal_atomic_fetch_min_32
- opal_atomic_fetch_max_32
- opal_atomic_swap_32
- OPAL_ATOMIC_DEFINE_CMPXCG_OP
- opal_atomic_fetch_max_64
- opal_atomic_swap_64
- opal_atomic_add_xx
- opal_atomic_sub_xx
- OPAL_ATOMIC_DEFINE_OP_FETCH
- opal_atomic_max_fetch_32
- OPAL_ATOMIC_DEFINE_OP_FETCH
- opal_atomic_max_fetch_64
- opal_atomic_fetch_add_ptr
- opal_atomic_add_fetch_ptr
- opal_atomic_fetch_sub_ptr
- opal_atomic_sub_fetch_ptr
- opal_atomic_lock_init
- opal_atomic_trylock
- opal_atomic_lock
- opal_atomic_unlock
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #include <stdlib.h>
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 #if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_32
41
42 #if !defined(OPAL_HAVE_ATOMIC_MIN_32)
43 static inline int32_t opal_atomic_fetch_min_32 (opal_atomic_int32_t *addr, int32_t value)
44 {
45 int32_t old = *addr;
46 do {
47 if (old <= value) {
48 break;
49 }
50 } while (!opal_atomic_compare_exchange_strong_32 (addr, &old, value));
51
52 return old;
53 }
54
55 #define OPAL_HAVE_ATOMIC_MIN_32 1
56
57 #endif
58
59 #if !defined(OPAL_HAVE_ATOMIC_MAX_32)
60 static inline int32_t opal_atomic_fetch_max_32 (opal_atomic_int32_t *addr, int32_t value)
61 {
62 int32_t old = *addr;
63 do {
64 if (old >= value) {
65 break;
66 }
67 } while (!opal_atomic_compare_exchange_strong_32 (addr, &old, value));
68
69 return old;
70 }
71
72 #define OPAL_HAVE_ATOMIC_MAX_32 1
73 #endif
74
75 #define OPAL_ATOMIC_DEFINE_CMPXCG_OP(type, bits, operation, name) \
76 static inline type opal_atomic_fetch_ ## name ## _ ## bits (opal_atomic_ ## type *addr, type value) \
77 { \
78 type oldval; \
79 do { \
80 oldval = *addr; \
81 } while (!opal_atomic_compare_exchange_strong_ ## bits (addr, &oldval, oldval operation value)); \
82 \
83 return oldval; \
84 }
85
86 #if !defined(OPAL_HAVE_ATOMIC_SWAP_32)
87 #define OPAL_HAVE_ATOMIC_SWAP_32 1
88 static inline int32_t opal_atomic_swap_32(opal_atomic_int32_t *addr,
89 int32_t newval)
90 {
91 int32_t old = *addr;
92 do {
93 } while (!opal_atomic_compare_exchange_strong_32 (addr, &old, newval));
94
95 return old;
96 }
97 #endif
98
99 #if !defined(OPAL_HAVE_ATOMIC_ADD_32)
100 #define OPAL_HAVE_ATOMIC_ADD_32 1
101
102 OPAL_ATOMIC_DEFINE_CMPXCG_OP(int32_t, 32, +, add)
103
104 #endif
105
106 #if !defined(OPAL_HAVE_ATOMIC_AND_32)
107 #define OPAL_HAVE_ATOMIC_AND_32 1
108
109 OPAL_ATOMIC_DEFINE_CMPXCG_OP(int32_t, 32, &, and)
110
111 #endif
112
113 #if !defined(OPAL_HAVE_ATOMIC_OR_32)
114 #define OPAL_HAVE_ATOMIC_OR_32 1
115
116 OPAL_ATOMIC_DEFINE_CMPXCG_OP(int32_t, 32, |, or)
117
118 #endif
119
120 #if !defined(OPAL_HAVE_ATOMIC_XOR_32)
121 #define OPAL_HAVE_ATOMIC_XOR_32 1
122
123 OPAL_ATOMIC_DEFINE_CMPXCG_OP(int32_t, 32, ^, xor)
124
125 #endif
126
127
128 #if !defined(OPAL_HAVE_ATOMIC_SUB_32)
129 #define OPAL_HAVE_ATOMIC_SUB_32 1
130
131 OPAL_ATOMIC_DEFINE_CMPXCG_OP(int32_t, 32, -, sub)
132
133 #endif
134
135 #endif
136
137
138 #if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_64
139
140 #if !defined(OPAL_HAVE_ATOMIC_MIN_64)
141 static inline int64_t opal_atomic_fetch_min_64 (opal_atomic_int64_t *addr, int64_t value)
142 {
143 int64_t old = *addr;
144 do {
145 if (old <= value) {
146 break;
147 }
148 } while (!opal_atomic_compare_exchange_strong_64 (addr, &old, value));
149
150 return old;
151 }
152
153 #define OPAL_HAVE_ATOMIC_MIN_64 1
154
155 #endif
156
157 #if !defined(OPAL_HAVE_ATOMIC_MAX_64)
158 static inline int64_t opal_atomic_fetch_max_64 (opal_atomic_int64_t *addr, int64_t value)
159 {
160 int64_t old = *addr;
161 do {
162 if (old >= value) {
163 break;
164 }
165 } while (!opal_atomic_compare_exchange_strong_64 (addr, &old, value));
166
167 return old;
168 }
169
170 #define OPAL_HAVE_ATOMIC_MAX_64 1
171 #endif
172
173 #if !defined(OPAL_HAVE_ATOMIC_SWAP_64)
174 #define OPAL_HAVE_ATOMIC_SWAP_64 1
175 static inline int64_t opal_atomic_swap_64(opal_atomic_int64_t *addr,
176 int64_t newval)
177 {
178 int64_t old = *addr;
179 do {
180 } while (!opal_atomic_compare_exchange_strong_64 (addr, &old, newval));
181
182 return old;
183 }
184 #endif
185
186 #if !defined(OPAL_HAVE_ATOMIC_ADD_64)
187 #define OPAL_HAVE_ATOMIC_ADD_64 1
188
189 OPAL_ATOMIC_DEFINE_CMPXCG_OP(int64_t, 64, +, add)
190
191 #endif
192
193 #if !defined(OPAL_HAVE_ATOMIC_AND_64)
194 #define OPAL_HAVE_ATOMIC_AND_64 1
195
196 OPAL_ATOMIC_DEFINE_CMPXCG_OP(int64_t, 64, &, and)
197
198 #endif
199
200 #if !defined(OPAL_HAVE_ATOMIC_OR_64)
201 #define OPAL_HAVE_ATOMIC_OR_64 1
202
203 OPAL_ATOMIC_DEFINE_CMPXCG_OP(int64_t, 64, |, or)
204
205 #endif
206
207 #if !defined(OPAL_HAVE_ATOMIC_XOR_64)
208 #define OPAL_HAVE_ATOMIC_XOR_64 1
209
210 OPAL_ATOMIC_DEFINE_CMPXCG_OP(int64_t, 64, ^, xor)
211
212 #endif
213
214 #if !defined(OPAL_HAVE_ATOMIC_SUB_64)
215 #define OPAL_HAVE_ATOMIC_SUB_64 1
216
217 OPAL_ATOMIC_DEFINE_CMPXCG_OP(int64_t, 64, -, sub)
218
219 #endif
220
221 #else
222
223 #if !defined(OPAL_HAVE_ATOMIC_ADD_64)
224 #define OPAL_HAVE_ATOMIC_ADD_64 0
225 #endif
226
227 #if !defined(OPAL_HAVE_ATOMIC_SUB_64)
228 #define OPAL_HAVE_ATOMIC_SUB_64 0
229 #endif
230
231 #endif
232
233 #if (OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_32 || OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_64)
234
235 #if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_32 && OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_64
236 #define OPAL_ATOMIC_DEFINE_CMPXCG_XX(semantics) \
237 static inline bool \
238 opal_atomic_compare_exchange_strong ## semantics ## xx (opal_atomic_intptr_t* addr, intptr_t *oldval, \
239 int64_t newval, const size_t length) \
240 { \
241 switch (length) { \
242 case 4: \
243 return opal_atomic_compare_exchange_strong_32 ((opal_atomic_int32_t *) addr, \
244 (int32_t *) oldval, (int32_t) newval); \
245 case 8: \
246 return opal_atomic_compare_exchange_strong_64 ((opal_atomic_int64_t *) addr, \
247 (int64_t *) oldval, (int64_t) newval); \
248 } \
249 abort(); \
250 }
251 #elif OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_32
252 #define OPAL_ATOMIC_DEFINE_CMPXCG_XX(semantics) \
253 static inline bool \
254 opal_atomic_compare_exchange_strong ## semantics ## xx (opal_atomic_intptr_t* addr, intptr_t *oldval, \
255 int64_t newval, const size_t length) \
256 { \
257 switch (length) { \
258 case 4: \
259 return opal_atomic_compare_exchange_strong_32 ((opal_atomic_int32_t *) addr, \
260 (int32_t *) oldval, (int32_t) newval); \
261 } \
262 abort(); \
263 }
264 #else
265 #error "Platform does not have required atomic compare-and-swap functionality"
266 #endif
267
268 OPAL_ATOMIC_DEFINE_CMPXCG_XX(_)
269 OPAL_ATOMIC_DEFINE_CMPXCG_XX(_acq_)
270 OPAL_ATOMIC_DEFINE_CMPXCG_XX(_rel_)
271
272 #if SIZEOF_VOID_P == 4 && OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_32
273 #define OPAL_ATOMIC_DEFINE_CMPXCG_PTR_XX(semantics) \
274 static inline bool \
275 opal_atomic_compare_exchange_strong ## semantics ## ptr (opal_atomic_intptr_t* addr, intptr_t *oldval, intptr_t newval) \
276 { \
277 return opal_atomic_compare_exchange_strong_32 ((opal_atomic_int32_t *) addr, (int32_t *) oldval, (int32_t) newval); \
278 }
279 #elif SIZEOF_VOID_P == 8 && OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_64
280 #define OPAL_ATOMIC_DEFINE_CMPXCG_PTR_XX(semantics) \
281 static inline bool \
282 opal_atomic_compare_exchange_strong ## semantics ## ptr (opal_atomic_intptr_t* addr, intptr_t *oldval, intptr_t newval) \
283 { \
284 return opal_atomic_compare_exchange_strong_64 ((opal_atomic_int64_t *) addr, (int64_t *) oldval, (int64_t) newval); \
285 }
286 #else
287 #error "Can not define opal_atomic_compare_exchange_strong_ptr with existing atomics"
288 #endif
289
290 OPAL_ATOMIC_DEFINE_CMPXCG_PTR_XX(_)
291 OPAL_ATOMIC_DEFINE_CMPXCG_PTR_XX(_acq_)
292 OPAL_ATOMIC_DEFINE_CMPXCG_PTR_XX(_rel_)
293
294 #endif
295
296
297 #if (OPAL_HAVE_ATOMIC_SWAP_32 || OPAL_HAVE_ATOMIC_SWAP_64)
298
299 #if SIZEOF_VOID_P == 4 && OPAL_HAVE_ATOMIC_SWAP_32
300 #define opal_atomic_swap_ptr(addr, value) (intptr_t) opal_atomic_swap_32((opal_atomic_int32_t *) addr, (int32_t) value)
301 #elif SIZEOF_VOID_P == 8 && OPAL_HAVE_ATOMIC_SWAP_64
302 #define opal_atomic_swap_ptr(addr, value) (intptr_t) opal_atomic_swap_64((opal_atomic_int64_t *) addr, (int64_t) value)
303 #endif
304
305 #endif
306
307 #if (OPAL_HAVE_ATOMIC_LLSC_32 || OPAL_HAVE_ATOMIC_LLSC_64)
308
309 #if SIZEOF_VOID_P == 4 && OPAL_HAVE_ATOMIC_LLSC_32
310
311 #define opal_atomic_ll_ptr(addr, ret) opal_atomic_ll_32((opal_atomic_int32_t *) (addr), ret)
312 #define opal_atomic_sc_ptr(addr, value, ret) opal_atomic_sc_32((opal_atomic_int32_t *) (addr), (intptr_t) (value), ret)
313
314 #define OPAL_HAVE_ATOMIC_LLSC_PTR 1
315
316 #elif SIZEOF_VOID_P == 8 && OPAL_HAVE_ATOMIC_LLSC_64
317
318 #define opal_atomic_ll_ptr(addr, ret) opal_atomic_ll_64((opal_atomic_int64_t *) (addr), ret)
319 #define opal_atomic_sc_ptr(addr, value, ret) opal_atomic_sc_64((opal_atomic_int64_t *) (addr), (intptr_t) (value), ret)
320
321 #define OPAL_HAVE_ATOMIC_LLSC_PTR 1
322
323 #endif
324
325 #endif
326
327 #if !defined(OPAL_HAVE_ATOMIC_LLSC_PTR)
328 #define OPAL_HAVE_ATOMIC_LLSC_PTR 0
329 #endif
330
331 #if OPAL_HAVE_ATOMIC_MATH_32 || OPAL_HAVE_ATOMIC_MATH_64
332
333 static inline void
334 opal_atomic_add_xx(opal_atomic_intptr_t* addr, int32_t value, size_t length)
335 {
336 switch( length ) {
337 #if OPAL_HAVE_ATOMIC_ADD_32
338 case 4:
339 (void) opal_atomic_fetch_add_32( (opal_atomic_int32_t*)addr, (int32_t)value );
340 break;
341 #endif
342
343 #if OPAL_HAVE_ATOMIC_ADD_64
344 case 8:
345 (void) opal_atomic_fetch_add_64( (opal_atomic_int64_t*)addr, (int64_t)value );
346 break;
347 #endif
348 default:
349
350
351 abort();
352 }
353 }
354
355
356 static inline void
357 opal_atomic_sub_xx(opal_atomic_intptr_t* addr, int32_t value, size_t length)
358 {
359 switch( length ) {
360 #if OPAL_HAVE_ATOMIC_SUB_32
361 case 4:
362 (void) opal_atomic_fetch_sub_32( (opal_atomic_int32_t*)addr, (int32_t)value );
363 break;
364 #endif
365
366 #if OPAL_HAVE_ATOMIC_SUB_64
367 case 8:
368 (void) opal_atomic_fetch_sub_64( (opal_atomic_int64_t*)addr, (int64_t)value );
369 break;
370 #endif
371 default:
372
373
374 abort();
375 }
376 }
377
378 #define OPAL_ATOMIC_DEFINE_OP_FETCH(op, operation, type, ptr_type, suffix) \
379 static inline type opal_atomic_ ## op ## _fetch_ ## suffix (opal_atomic_ ## ptr_type *addr, type value) \
380 { \
381 return opal_atomic_fetch_ ## op ## _ ## suffix (addr, value) operation value; \
382 }
383
384 OPAL_ATOMIC_DEFINE_OP_FETCH(add, +, int32_t, int32_t, 32)
385 OPAL_ATOMIC_DEFINE_OP_FETCH(and, &, int32_t, int32_t, 32)
386 OPAL_ATOMIC_DEFINE_OP_FETCH(or, |, int32_t, int32_t, 32)
387 OPAL_ATOMIC_DEFINE_OP_FETCH(xor, ^, int32_t, int32_t, 32)
388 OPAL_ATOMIC_DEFINE_OP_FETCH(sub, -, int32_t, int32_t, 32)
389
390 static inline int32_t opal_atomic_min_fetch_32 (opal_atomic_int32_t *addr, int32_t value)
391 {
392 int32_t old = opal_atomic_fetch_min_32 (addr, value);
393 return old <= value ? old : value;
394 }
395
396 static inline int32_t opal_atomic_max_fetch_32 (opal_atomic_int32_t *addr, int32_t value)
397 {
398 int32_t old = opal_atomic_fetch_max_32 (addr, value);
399 return old >= value ? old : value;
400 }
401
402 #if OPAL_HAVE_ATOMIC_MATH_64
403 OPAL_ATOMIC_DEFINE_OP_FETCH(add, +, int64_t, int64_t, 64)
404 OPAL_ATOMIC_DEFINE_OP_FETCH(and, &, int64_t, int64_t, 64)
405 OPAL_ATOMIC_DEFINE_OP_FETCH(or, |, int64_t, int64_t, 64)
406 OPAL_ATOMIC_DEFINE_OP_FETCH(xor, ^, int64_t, int64_t, 64)
407 OPAL_ATOMIC_DEFINE_OP_FETCH(sub, -, int64_t, int64_t, 64)
408
409 static inline int64_t opal_atomic_min_fetch_64 (opal_atomic_int64_t *addr, int64_t value)
410 {
411 int64_t old = opal_atomic_fetch_min_64 (addr, value);
412 return old <= value ? old : value;
413 }
414
415 static inline int64_t opal_atomic_max_fetch_64 (opal_atomic_int64_t *addr, int64_t value)
416 {
417 int64_t old = opal_atomic_fetch_max_64 (addr, value);
418 return old >= value ? old : value;
419 }
420
421 #endif
422
423 static inline intptr_t opal_atomic_fetch_add_ptr( opal_atomic_intptr_t* addr,
424 void* delta )
425 {
426 #if SIZEOF_VOID_P == 4 && OPAL_HAVE_ATOMIC_ADD_32
427 return opal_atomic_fetch_add_32((opal_atomic_int32_t*) addr, (unsigned long) delta);
428 #elif SIZEOF_VOID_P == 8 && OPAL_HAVE_ATOMIC_ADD_64
429 return opal_atomic_fetch_add_64((opal_atomic_int64_t*) addr, (unsigned long) delta);
430 #else
431 abort ();
432 return 0;
433 #endif
434 }
435
436 static inline intptr_t opal_atomic_add_fetch_ptr( opal_atomic_intptr_t* addr,
437 void* delta )
438 {
439 #if SIZEOF_VOID_P == 4 && OPAL_HAVE_ATOMIC_ADD_32
440 return opal_atomic_add_fetch_32((opal_atomic_int32_t*) addr, (unsigned long) delta);
441 #elif SIZEOF_VOID_P == 8 && OPAL_HAVE_ATOMIC_ADD_64
442 return opal_atomic_add_fetch_64((opal_atomic_int64_t*) addr, (unsigned long) delta);
443 #else
444 abort ();
445 return 0;
446 #endif
447 }
448
449 static inline intptr_t opal_atomic_fetch_sub_ptr( opal_atomic_intptr_t* addr,
450 void* delta )
451 {
452 #if SIZEOF_VOID_P == 4 && OPAL_HAVE_ATOMIC_SUB_32
453 return opal_atomic_fetch_sub_32((opal_atomic_int32_t*) addr, (unsigned long) delta);
454 #elif SIZEOF_VOID_P == 8 && OPAL_HAVE_ATOMIC_SUB_32
455 return opal_atomic_fetch_sub_64((opal_atomic_int64_t*) addr, (unsigned long) delta);
456 #else
457 abort();
458 return 0;
459 #endif
460 }
461
462 static inline intptr_t opal_atomic_sub_fetch_ptr( opal_atomic_intptr_t* addr,
463 void* delta )
464 {
465 #if SIZEOF_VOID_P == 4 && OPAL_HAVE_ATOMIC_SUB_32
466 return opal_atomic_sub_fetch_32((opal_atomic_int32_t*) addr, (unsigned long) delta);
467 #elif SIZEOF_VOID_P == 8 && OPAL_HAVE_ATOMIC_SUB_32
468 return opal_atomic_sub_fetch_64((opal_atomic_int64_t*) addr, (unsigned long) delta);
469 #else
470 abort();
471 return 0;
472 #endif
473 }
474
475 #endif
476
477
478
479
480
481
482 #ifdef OPAL_NEED_INLINE_ATOMIC_SPINLOCKS
483
484
485
486
487 static inline void
488 opal_atomic_lock_init( opal_atomic_lock_t* lock, int32_t value )
489 {
490 lock->u.lock = value;
491 }
492
493
494 static inline int
495 opal_atomic_trylock(opal_atomic_lock_t *lock)
496 {
497 int32_t unlocked = OPAL_ATOMIC_LOCK_UNLOCKED;
498 bool ret = opal_atomic_compare_exchange_strong_acq_32 (&lock->u.lock, &unlocked, OPAL_ATOMIC_LOCK_LOCKED);
499 return (ret == false) ? 1 : 0;
500 }
501
502
503 static inline void
504 opal_atomic_lock(opal_atomic_lock_t *lock)
505 {
506 while (opal_atomic_trylock (lock)) {
507 while (lock->u.lock == OPAL_ATOMIC_LOCK_LOCKED) {
508 ;
509 }
510 }
511 }
512
513
514 static inline void
515 opal_atomic_unlock(opal_atomic_lock_t *lock)
516 {
517 opal_atomic_wmb();
518 lock->u.lock=OPAL_ATOMIC_LOCK_UNLOCKED;
519 }
520
521 #endif