Skip to content

Commit 6786d1d

Browse files
committed
opal/atomic: always use C11 atomics if available
This commit disables the use of both the builtin and hand-written atomics if proper C11 atomic support is detected. This is the first step towards requiring the availability of C11 atomics for the C compiler used to build Open MPI. Signed-off-by: Nathan Hjelm <[email protected]>
1 parent 1297cde commit 6786d1d

File tree

8 files changed

+286
-10
lines changed

8 files changed

+286
-10
lines changed

opal/class/opal_object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ int opal_class_init_epoch = 1;
5555
/*
5656
* Local variables
5757
*/
58-
static opal_atomic_lock_t class_lock = { { OPAL_ATOMIC_LOCK_UNLOCKED } };
58+
static opal_atomic_lock_t class_lock = OPAL_ATOMIC_LOCK_INIT;
5959
static void** classes = NULL;
6060
static int num_classes = 0;
6161
static int max_classes = 0;

opal/include/opal/sys/atomic.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@
5858
#include "opal/sys/architecture.h"
5959
#include "opal_stdatomic.h"
6060

61+
#if OPAL_C_HAVE__ATOMIC
62+
63+
#include "atomic_stdc.h"
64+
65+
#else /* !OPAL_C_HAVE__ATOMIC */
66+
6167
/* do some quick #define cleanup in cases where we are doing
6268
testing... */
6369
#ifdef OPAL_DISABLE_INLINE_ASM
@@ -643,6 +649,8 @@ static inline intptr_t opal_atomic_fetch_sub_ptr( opal_atomic_intptr_t* addr, vo
643649
*/
644650
#include "opal/sys/atomic_impl.h"
645651

652+
#endif /* !OPAL_C_HAVE__ATOMIC */
653+
646654
END_C_DECLS
647655

648656
#endif /* OPAL_SYS_ATOMIC_H */

opal/include/opal/sys/atomic_stdc.h

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2+
/*
3+
* Copyright (c) 2018 Los Alamos National Security, LLC. All rights
4+
* reserved.
5+
* $COPYRIGHT$
6+
*
7+
* Additional copyrights may follow
8+
*
9+
* $HEADER$
10+
*/
11+
12+
/* This file provides shims between the opal atomics interface and the C11 atomics interface. It
13+
* is intended as the first step in moving to using C11 atomics across the entire codebase. Once
14+
* all officially supported compilers offer C11 atomic (GCC 4.9.0+, icc 2018+, pgi, xlc, etc) then
15+
* this shim will go away and the codebase will be updated to use C11's atomic support
16+
* directly.
17+
* This shim contains some functions already present in atomic_impl.h because we do not include
18+
* atomic_impl.h when using C11 atomics. It would require alot of #ifdefs to avoid duplicate
19+
* definitions to be worthwhile. */
20+
21+
#if !defined(OPAL_ATOMIC_STDC_H)
22+
#define OPAL_ATOMIC_STDC_H
23+
24+
#include <stdatomic.h>
25+
#include <stdint.h>
26+
#include "opal/include/opal_stdint.h"
27+
28+
#define OPAL_HAVE_ATOMIC_MEM_BARRIER 1
29+
30+
#define OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_32 1
31+
#define OPAL_HAVE_ATOMIC_SWAP_32 1
32+
33+
#define OPAL_HAVE_ATOMIC_MATH_32 1
34+
#define OPAL_HAVE_ATOMIC_ADD_32 1
35+
#define OPAL_HAVE_ATOMIC_AND_32 1
36+
#define OPAL_HAVE_ATOMIC_OR_32 1
37+
#define OPAL_HAVE_ATOMIC_XOR_32 1
38+
#define OPAL_HAVE_ATOMIC_SUB_32 1
39+
40+
#define OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_64 1
41+
#define OPAL_HAVE_ATOMIC_SWAP_64 1
42+
43+
#define OPAL_HAVE_ATOMIC_MATH_64 1
44+
#define OPAL_HAVE_ATOMIC_ADD_64 1
45+
#define OPAL_HAVE_ATOMIC_AND_64 1
46+
#define OPAL_HAVE_ATOMIC_OR_64 1
47+
#define OPAL_HAVE_ATOMIC_XOR_64 1
48+
#define OPAL_HAVE_ATOMIC_SUB_64 1
49+
50+
#define OPAL_HAVE_ATOMIC_LLSC_32 0
51+
#define OPAL_HAVE_ATOMIC_LLSC_64 0
52+
#define OPAL_HAVE_ATOMIC_LLSC_PTR 0
53+
54+
#define OPAL_HAVE_ATOMIC_MIN_32 1
55+
#define OPAL_HAVE_ATOMIC_MAX_32 1
56+
57+
#define OPAL_HAVE_ATOMIC_MIN_64 1
58+
#define OPAL_HAVE_ATOMIC_MAX_64 1
59+
60+
#define OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128 1
61+
62+
#define OPAL_HAVE_ATOMIC_SPINLOCKS 1
63+
64+
static inline void opal_atomic_mb (void)
65+
{
66+
atomic_thread_fence (memory_order_seq_cst);
67+
}
68+
69+
static inline void opal_atomic_wmb (void)
70+
{
71+
atomic_thread_fence (memory_order_release);
72+
}
73+
74+
static inline void opal_atomic_rmb (void)
75+
{
76+
atomic_thread_fence (memory_order_acquire);
77+
}
78+
79+
#define opal_atomic_compare_exchange_strong_32 atomic_compare_exchange_strong
80+
#define opal_atomic_compare_exchange_strong_64 atomic_compare_exchange_strong
81+
#define opal_atomic_compare_exchange_strong_128 atomic_compare_exchange_strong
82+
#define opal_atomic_compare_exchange_strong_ptr atomic_compare_exchange_strong
83+
#define opal_atomic_compare_exchange_strong_acq_32(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_acquire, memory_order_relaxed)
84+
#define opal_atomic_compare_exchange_strong_acq_64(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_acquire, memory_order_relaxed)
85+
#define opal_atomic_compare_exchange_strong_acq_ptr(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_acquire, memory_order_relaxed)
86+
87+
#define opal_atomic_compare_exchange_strong_rel_32(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_release, memory_order_relaxed)
88+
#define opal_atomic_compare_exchange_strong_rel_64(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_release, memory_order_relaxed)
89+
#define opal_atomic_compare_exchange_strong_rel_ptr(addr, compare, value) atomic_compare_exchange_strong_explicit (addr, compare, value, memory_order_release, memory_order_relaxed)
90+
91+
#define opal_atomic_compare_exchange_strong atomic_compare_exchange_strong
92+
#define opal_atomic_compare_exchange_strong_acq(addr, oldval, newval) atomic_compare_exchange_strong_explicit (addr, oldval, newval, memory_order_acquire, memory_order_relaxed)
93+
#define opal_atomic_compare_exchange_strong_rel(addr, oldval, newval) atomic_compare_exchange_strong_explicit (addr, oldval, newval, memory_order_release, memory_order_relaxed)
94+
95+
#define opal_atomic_swap_32 atomic_exchange
96+
#define opal_atomic_swap_64 atomic_exchange
97+
#define opal_atomic_swap_ptr atomic_exchange
98+
99+
#define OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(op, bits, type, operator) \
100+
static inline type opal_atomic_fetch_ ## op ##_## bits (opal_atomic_ ## type *addr, type value) \
101+
{ \
102+
return atomic_fetch_ ## op (addr, value); \
103+
} \
104+
\
105+
static inline type opal_atomic_## op ## _fetch_ ## bits (opal_atomic_ ## type *addr, type value) \
106+
{ \
107+
return atomic_fetch_ ## op (addr, value) operator value; \
108+
}
109+
110+
OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(add, 32, int32_t, +)
111+
OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(add, 64, int64_t, +)
112+
OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(add, size_t, size_t, +)
113+
114+
OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(sub, 32, int32_t, -)
115+
OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(sub, 64, int64_t, -)
116+
OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(sub, size_t, size_t, -)
117+
118+
OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(or, 32, int32_t, |)
119+
OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(or, 64, int64_t, |)
120+
121+
OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(xor, 32, int32_t, ^)
122+
OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(xor, 64, int64_t, ^)
123+
124+
OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(and, 32, int32_t, &)
125+
OPAL_ATOMIC_STDC_DEFINE_FETCH_OP(and, 64, int64_t, &)
126+
127+
#define opal_atomic_add (void) atomic_fetch_add
128+
129+
static inline int32_t opal_atomic_fetch_min_32 (opal_atomic_int32_t *addr, int32_t value)
130+
{
131+
int32_t old = *addr;
132+
do {
133+
if (old <= value) {
134+
break;
135+
}
136+
} while (!opal_atomic_compare_exchange_strong_32 (addr, &old, value));
137+
138+
return old;
139+
}
140+
141+
static inline int32_t opal_atomic_fetch_max_32 (opal_atomic_int32_t *addr, int32_t value)
142+
{
143+
int32_t old = *addr;
144+
do {
145+
if (old >= value) {
146+
break;
147+
}
148+
} while (!opal_atomic_compare_exchange_strong_32 (addr, &old, value));
149+
150+
return old;
151+
}
152+
153+
static inline int64_t opal_atomic_fetch_min_64 (opal_atomic_int64_t *addr, int64_t value)
154+
{
155+
int64_t old = *addr;
156+
do {
157+
if (old <= value) {
158+
break;
159+
}
160+
} while (!opal_atomic_compare_exchange_strong_64 (addr, &old, value));
161+
162+
return old;
163+
}
164+
165+
static inline int64_t opal_atomic_fetch_max_64 (opal_atomic_int64_t *addr, int64_t value)
166+
{
167+
int64_t old = *addr;
168+
do {
169+
if (old >= value) {
170+
break;
171+
}
172+
} while (!opal_atomic_compare_exchange_strong_64 (addr, &old, value));
173+
174+
return old;
175+
}
176+
177+
static inline int32_t opal_atomic_min_fetch_32 (opal_atomic_int32_t *addr, int32_t value)
178+
{
179+
int32_t old = opal_atomic_fetch_min_32 (addr, value);
180+
return old <= value ? old : value;
181+
}
182+
183+
static inline int32_t opal_atomic_max_fetch_32 (opal_atomic_int32_t *addr, int32_t value)
184+
{
185+
int32_t old = opal_atomic_fetch_max_32 (addr, value);
186+
return old >= value ? old : value;
187+
}
188+
189+
static inline int64_t opal_atomic_min_fetch_64 (opal_atomic_int64_t *addr, int64_t value)
190+
{
191+
int64_t old = opal_atomic_fetch_min_64 (addr, value);
192+
return old <= value ? old : value;
193+
}
194+
195+
static inline int64_t opal_atomic_max_fetch_64 (opal_atomic_int64_t *addr, int64_t value)
196+
{
197+
int64_t old = opal_atomic_fetch_max_64 (addr, value);
198+
return old >= value ? old : value;
199+
}
200+
201+
#define OPAL_ATOMIC_LOCK_UNLOCKED false
202+
#define OPAL_ATOMIC_LOCK_LOCKED true
203+
204+
#define OPAL_ATOMIC_LOCK_INIT ATOMIC_FLAG_INIT
205+
206+
typedef atomic_flag opal_atomic_lock_t;
207+
208+
/*
209+
* Lock initialization function. It set the lock to UNLOCKED.
210+
*/
211+
static inline void opal_atomic_lock_init (opal_atomic_lock_t *lock, bool value)
212+
{
213+
atomic_flag_clear (lock);
214+
}
215+
216+
217+
static inline int opal_atomic_trylock (opal_atomic_lock_t *lock)
218+
{
219+
return (int) atomic_flag_test_and_set (lock);
220+
}
221+
222+
223+
static inline void opal_atomic_lock(opal_atomic_lock_t *lock)
224+
{
225+
while (opal_atomic_trylock (lock)) {
226+
}
227+
}
228+
229+
230+
static inline void opal_atomic_unlock (opal_atomic_lock_t *lock)
231+
{
232+
atomic_flag_clear (lock);
233+
}
234+
235+
#endif /* !defined(OPAL_ATOMIC_STDC_H) */

opal/include/opal_stdatomic.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
#include "opal_stdint.h"
1616

17+
#if !OPAL_C_HAVE__ATOMIC
18+
19+
typedef volatile int opal_atomic_int_t;
1720
typedef volatile long opal_atomic_long_t;
1821

1922
typedef volatile int32_t opal_atomic_int32_t;
@@ -22,6 +25,7 @@ typedef volatile int64_t opal_atomic_int64_t;
2225
typedef volatile uint64_t opal_atomic_uint64_t;
2326

2427
typedef volatile size_t opal_atomic_size_t;
28+
typedef volatile ssize_t opal_atomic_ssize_t;
2529
typedef volatile intptr_t opal_atomic_intptr_t;
2630
typedef volatile uintptr_t opal_atomic_uintptr_t;
2731

@@ -31,5 +35,29 @@ typedef volatile opal_int128_t opal_atomic_int128_t;
3135

3236
#endif
3337

38+
#else /* OPAL_HAVE_C__ATOMIC */
39+
40+
#include <stdatomic.h>
41+
42+
typedef atomic_int opal_atomic_int_t;
43+
typedef atomic_long opal_atomic_long_t;
44+
45+
typedef _Atomic int32_t opal_atomic_int32_t;
46+
typedef _Atomic uint32_t opal_atomic_uint32_t;
47+
typedef _Atomic int64_t opal_atomic_int64_t;
48+
typedef _Atomic uint64_t opal_atomic_uint64_t;
49+
50+
typedef _Atomic size_t opal_atomic_size_t;
51+
typedef _Atomic ssize_t opal_atomic_ssize_t;
52+
typedef _Atomic intptr_t opal_atomic_intptr_t;
53+
typedef _Atomic uintptr_t opal_atomic_uintptr_t;
54+
55+
#ifdef HAVE_OPAL_INT128_T
56+
57+
typedef _Atomic opal_int128_t opal_atomic_int128_t;
58+
59+
#endif
60+
61+
#endif /* OPAL_HAVE_C__ATOMIC */
3462

3563
#endif /* !defined(OPAL_STDATOMIC_H) */

opal/include/opal_stdint.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#ifndef OPAL_STDINT_H
2929
#define OPAL_STDINT_H 1
3030

31+
#include "opal_config.h"
32+
3133
/*
3234
* Include what we can and define what is missing.
3335
*/

opal/mca/btl/vader/btl_vader_component.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ static int mca_btl_base_vader_modex_send (void)
365365
return rc;
366366
}
367367

368+
#if OPAL_BTL_VADER_HAVE_XPMEM || OPAL_BTL_VADER_HAVE_CMA || OPAL_BTL_VADER_HAVE_KNEM
368369
static void mca_btl_vader_select_next_single_copy_mechanism (void)
369370
{
370371
for (int i = 0 ; single_copy_mechanisms[i].value != MCA_BTL_VADER_NONE ; ++i) {
@@ -374,10 +375,13 @@ static void mca_btl_vader_select_next_single_copy_mechanism (void)
374375
}
375376
}
376377
}
378+
#endif
377379

378380
static void mca_btl_vader_check_single_copy (void)
379381
{
382+
#if OPAL_BTL_VADER_HAVE_XPMEM || OPAL_BTL_VADER_HAVE_CMA || OPAL_BTL_VADER_HAVE_KNEM
380383
int initial_mechanism = mca_btl_vader_component.single_copy_mechanism;
384+
#endif
381385

382386
#if OPAL_BTL_VADER_HAVE_XPMEM
383387
if (MCA_BTL_VADER_XPMEM == mca_btl_vader_component.single_copy_mechanism) {
@@ -520,7 +524,6 @@ static mca_btl_base_module_t **mca_btl_vader_component_init (int *num_btls,
520524
mca_btl_vader_check_single_copy ();
521525

522526
if (MCA_BTL_VADER_XPMEM != mca_btl_vader_component.single_copy_mechanism) {
523-
const char *base_dir = opal_process_info.proc_session_dir;
524527
char *sm_file;
525528

526529
rc = asprintf(&sm_file, "%s" OPAL_PATH_SEP "vader_segment.%s.%x.%d", mca_btl_vader_component.backing_directory,

opal/threads/mutex_unix.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,14 @@ OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_recursive_mutex_t);
7676
.m_lock_debug = 0, \
7777
.m_lock_file = NULL, \
7878
.m_lock_line = 0, \
79-
.m_lock_atomic = { .u = { .lock = OPAL_ATOMIC_LOCK_UNLOCKED } }, \
79+
.m_lock_atomic = OPAL_ATOMIC_LOCK_INIT, \
8080
}
8181
#else
8282
#define OPAL_MUTEX_STATIC_INIT \
8383
{ \
8484
.super = OPAL_OBJ_STATIC_INIT(opal_mutex_t), \
8585
.m_lock_pthread = PTHREAD_MUTEX_INITIALIZER, \
86-
.m_lock_atomic = { .u = { .lock = OPAL_ATOMIC_LOCK_UNLOCKED } }, \
86+
.m_lock_atomic = OPAL_ATOMIC_LOCK_INIT, \
8787
}
8888
#endif
8989

@@ -97,14 +97,14 @@ OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_recursive_mutex_t);
9797
.m_lock_debug = 0, \
9898
.m_lock_file = NULL, \
9999
.m_lock_line = 0, \
100-
.m_lock_atomic = { .u = { .lock = OPAL_ATOMIC_LOCK_UNLOCKED } }, \
100+
.m_lock_atomic = OPAL_ATOMIC_LOCK_INIT, \
101101
}
102102
#else
103103
#define OPAL_RECURSIVE_MUTEX_STATIC_INIT \
104104
{ \
105105
.super = OPAL_OBJ_STATIC_INIT(opal_mutex_t), \
106106
.m_lock_pthread = OPAL_PTHREAD_RECURSIVE_MUTEX_INITIALIZER, \
107-
.m_lock_atomic = { .u = { .lock = OPAL_ATOMIC_LOCK_UNLOCKED } }, \
107+
.m_lock_atomic = OPAL_ATOMIC_LOCK_INIT, \
108108
}
109109
#endif
110110

0 commit comments

Comments
 (0)