Skip to content

Commit 84f63d0

Browse files
committed
opal/asm: add opal_atomic_compare_exchange_strong functions
This commit adds a new set of compare-and-exchange functions. These functions have a signature similar to the functions found in C11. The old cmpset functions are now deprecated and defined in terms of the new compare-and-exchange functions. All asm backends have been updated. Signed-off-by: Nathan Hjelm <[email protected]>
1 parent 45db363 commit 84f63d0

File tree

14 files changed

+697
-530
lines changed

14 files changed

+697
-530
lines changed

opal/class/opal_fifo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ static inline bool opal_fifo_is_empty( opal_fifo_t* fifo )
7676
return opal_fifo_head (fifo) == &fifo->opal_fifo_ghost;
7777
}
7878

79-
#if OPAL_HAVE_ATOMIC_CMPSET_128
79+
#if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128
8080

8181
/* Add one element to the FIFO. We will return the last head of the list
8282
* to allow the upper level to detect if this element is the first one in the

opal/class/opal_lifo.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636
BEGIN_C_DECLS
3737

3838
/* NTH: temporarily suppress warnings about this not being defined */
39-
#if !defined(OPAL_HAVE_ATOMIC_CMPSET_128)
40-
#define OPAL_HAVE_ATOMIC_CMPSET_128 0
39+
#if !defined(OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128)
40+
#define OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128 0
4141
#endif
4242

4343
/**
@@ -50,7 +50,7 @@ union opal_counted_pointer_t {
5050
/** list item pointer */
5151
volatile opal_list_item_t * volatile item;
5252
} data;
53-
#if OPAL_HAVE_ATOMIC_CMPSET_128 && HAVE_OPAL_INT128_T
53+
#if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128 && HAVE_OPAL_INT128_T
5454
/** used for atomics when there is a cmpset that can operate on
5555
* two 64-bit values */
5656
opal_int128_t value;
@@ -59,7 +59,7 @@ union opal_counted_pointer_t {
5959
typedef union opal_counted_pointer_t opal_counted_pointer_t;
6060

6161

62-
#if OPAL_HAVE_ATOMIC_CMPSET_128
62+
#if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128
6363

6464
/* Add one element to the FIFO. We will return the last head of the list
6565
* to allow the upper level to detect if this element is the first one in the
@@ -110,7 +110,7 @@ static inline bool opal_lifo_is_empty( opal_lifo_t* lifo )
110110
}
111111

112112

113-
#if OPAL_HAVE_ATOMIC_CMPSET_128
113+
#if OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_128
114114

115115
/* Add one element to the LIFO. We will return the last head of the list
116116
* to allow the upper level to detect if this element is the first one in the

opal/include/opal/sys/arm/atomic.h

Lines changed: 44 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
12
/*
23
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
34
* University Research and Technology
@@ -11,6 +12,8 @@
1112
* All rights reserved.
1213
* Copyright (c) 2010 IBM Corporation. All rights reserved.
1314
* Copyright (c) 2010 ARM ltd. All rights reserved.
15+
* Copyright (c) 2017 Los Alamos National Security, LLC. All rights
16+
* reserved.
1417
* $COPYRIGHT$
1518
*
1619
* Additional copyrights may follow
@@ -104,12 +107,12 @@ void opal_atomic_isync(void)
104107

105108
#if (OPAL_GCC_INLINE_ASSEMBLY && (OPAL_ASM_ARM_VERSION >= 6))
106109

107-
#define OPAL_HAVE_ATOMIC_CMPSET_32 1
110+
#define OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_32 1
108111
#define OPAL_HAVE_ATOMIC_MATH_32 1
109-
static inline bool opal_atomic_bool_cmpset_32(volatile int32_t *addr,
110-
int32_t oldval, int32_t newval)
112+
static inline bool opal_atomic_compare_exchange_strong_32 (volatile int32_t *addr, int32_t *oldval, int32_t newval)
111113
{
112-
int32_t ret, tmp;
114+
int32_t prev, tmp;
115+
bool ret;
113116

114117
__asm__ __volatile__ (
115118
"1: ldrex %0, [%2] \n"
@@ -120,87 +123,86 @@ static inline bool opal_atomic_bool_cmpset_32(volatile int32_t *addr,
120123
" bne 1b \n"
121124
"2: \n"
122125

123-
: "=&r" (ret), "=&r" (tmp)
124-
: "r" (addr), "r" (oldval), "r" (newval)
126+
: "=&r" (prev), "=&r" (tmp)
127+
: "r" (addr), "r" (*oldval), "r" (newval)
125128
: "cc", "memory");
126129

127-
return (ret == oldval);
130+
ret = (prev == *oldval);
131+
*oldval = prev;
132+
return ret;
128133
}
129134

130135
/* these two functions aren't inlined in the non-gcc case because then
131136
there would be two function calls (since neither cmpset_32 nor
132137
atomic_?mb can be inlined). Instead, we "inline" them by hand in
133138
the assembly, meaning there is one function call overhead instead
134139
of two */
135-
static inline bool opal_atomic_bool_cmpset_acq_32(volatile int32_t *addr,
136-
int32_t oldval, int32_t newval)
140+
static inline bool opal_atomic_compare_exchange_strong_acq_32 (volatile int32_t *addr, int32_t *oldval, int32_t newval)
137141
{
138142
bool rc;
139143

140-
rc = opal_atomic_bool_cmpset_32(addr, oldval, newval);
144+
rc = opal_atomic_compare_exchange_strong_32 (addr, oldval, newval);
141145
opal_atomic_rmb();
142146

143147
return rc;
144148
}
145149

146150

147-
static inline bool opal_atomic_bool_cmpset_rel_32(volatile int32_t *addr,
148-
int32_t oldval, int32_t newval)
151+
static inline bool opal_atomic_compare_exchange_strong_rel_32 (volatile int32_t *addr, int32_t *oldval, int32_t newval)
149152
{
150153
opal_atomic_wmb();
151-
return opal_atomic_bool_cmpset_32(addr, oldval, newval);
154+
return opal_atomic_compare_exchange_strong_32 (addr, oldval, newval);
152155
}
153156

154157
#if (OPAL_ASM_SUPPORT_64BIT == 1)
155158

156-
#define OPAL_HAVE_ATOMIC_CMPSET_64 1
157-
static inline bool opal_atomic_bool_cmpset_64(volatile int64_t *addr,
158-
int64_t oldval, int64_t newval)
159+
#define OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_64 1
160+
static inline bool opal_atomic_compare_exchange_strong_64 (volatile int64_t *addr, int64_t *oldval, int64_t newval)
159161
{
160-
int64_t ret;
161-
int tmp;
162-
163-
164-
__asm__ __volatile__ (
165-
"1: ldrexd %0, %H0, [%2] \n"
166-
" cmp %0, %3 \n"
167-
" it eq \n"
168-
" cmpeq %H0, %H3 \n"
169-
" bne 2f \n"
170-
" strexd %1, %4, %H4, [%2] \n"
171-
" cmp %1, #0 \n"
172-
" bne 1b \n"
173-
"2: \n"
174-
175-
: "=&r" (ret), "=&r" (tmp)
176-
: "r" (addr), "r" (oldval), "r" (newval)
177-
: "cc", "memory");
178-
179-
return (ret == oldval);
162+
int64_t prev;
163+
int tmp;
164+
bool ret;
165+
166+
__asm__ __volatile__ (
167+
"1: ldrexd %0, %H0, [%2] \n"
168+
" cmp %0, %3 \n"
169+
" it eq \n"
170+
" cmpeq %H0, %H3 \n"
171+
" bne 2f \n"
172+
" strexd %1, %4, %H4, [%2] \n"
173+
" cmp %1, #0 \n"
174+
" bne 1b \n"
175+
"2: \n"
176+
177+
: "=&r" (prev), "=&r" (tmp)
178+
: "r" (addr), "r" (*oldval), "r" (newval)
179+
: "cc", "memory");
180+
181+
ret = (prev == *oldval);
182+
*oldval = prev;
183+
return ret;
180184
}
181185

182186
/* these two functions aren't inlined in the non-gcc case because then
183187
there would be two function calls (since neither cmpset_64 nor
184188
atomic_?mb can be inlined). Instead, we "inline" them by hand in
185189
the assembly, meaning there is one function call overhead instead
186190
of two */
187-
static inline bool opal_atomic_bool_cmpset_acq_64(volatile int64_t *addr,
188-
int64_t oldval, int64_t newval)
191+
static inline bool opal_atomic_compare_exchange_strong_acq_64 (volatile int64_t *addr, int64_t *oldval, int64_t newval)
189192
{
190193
bool rc;
191194

192-
rc = opal_atomic_bool_cmpset_64(addr, oldval, newval);
195+
rc = opal_atomic_compare_exchange_strong_64 (addr, oldval, newval);
193196
opal_atomic_rmb();
194197

195198
return rc;
196199
}
197200

198201

199-
static inline bool opal_atomic_bool_cmpset_rel_64(volatile int64_t *addr,
200-
int64_t oldval, int64_t newval)
202+
static inline bool opal_atomic_compare_exchange_strong_rel_64 (volatile int64_t *addr, int64_t *oldval, int64_t newval)
201203
{
202204
opal_atomic_wmb();
203-
return opal_atomic_bool_cmpset_64(addr, oldval, newval);
205+
return opal_atomic_compare_exchange_strong_64 (addr, oldval, newval);
204206
}
205207

206208
#endif
@@ -247,30 +249,6 @@ static inline int32_t opal_atomic_sub_32(volatile int32_t* v, int dec)
247249
return t;
248250
}
249251

250-
#else /* OPAL_ASM_ARM_VERSION <=5 or no GCC inline assembly */
251-
252-
#define OPAL_HAVE_ATOMIC_CMPSET_32 1
253-
#define __kuser_cmpxchg (*((int (*)(int, int, volatile int*))(0xffff0fc0)))
254-
static inline bool opal_atomic_bool_cmpset_32(volatile int32_t *addr,
255-
int32_t oldval, int32_t newval)
256-
{
257-
return !(__kuser_cmpxchg(oldval, newval, addr));
258-
}
259-
260-
static inline bool opal_atomic_bool_cmpset_acq_32(volatile int32_t *addr,
261-
int32_t oldval, int32_t newval)
262-
{
263-
/* kernel function includes all necessary memory barriers */
264-
return opal_atomic_bool_cmpset_32(addr, oldval, newval);
265-
}
266-
267-
static inline bool opal_atomic_bool_cmpset_rel_32(volatile int32_t *addr,
268-
int32_t oldval, int32_t newval)
269-
{
270-
/* kernel function includes all necessary memory barriers */
271-
return opal_atomic_bool_cmpset_32(addr, oldval, newval);
272-
}
273-
274252
#endif
275253

276254
#endif /* ! OPAL_SYS_ARCH_ATOMIC_H */

0 commit comments

Comments
 (0)