1 /****************************************************************************/
2 #if( defined __GNUC__ )
3 // TRD : makes checking GCC versions much tidier
4 #define LFDS700_PAL_GCC_VERSION ( __GNUC__ * 100 + __GNUC_MINOR__ * 10 + __GNUC_PATCHLEVEL__ )
11 /****************************************************************************/
12 #if( defined _MSC_VER && _MSC_VER >= 1400 )
14 /* TRD : MSVC 8.0 and greater
16 _MSC_VER indicates Microsoft C compiler and version
17 - __declspec(align) requires 7.1 (1310)
18 - __nop requires 8.0 (1400)
19 - _ReadBarrier requires 8.0 (1400)
20 - _WriteBarrier requires 8.0 (1400)
21 - _ReadWriteBarrier requires 7.1 (1310)
22 - _InterlockedCompareExchangePointer requires 8.0 (1400)
23 - _InterlockedExchange requires 7.1 (1310)
24 - _InterlockedExchangePointer requires 8.0 (1400)
25 - _InterlockedCompareExchange64 requires 8.0 (1400) (seems to, docs unclear)
26 - _InterlockedCompareExchange128 requires 9.0 (1500)
28 load/store barriers are mandatory for liblfds, which means the earliest viable version of MSCV is 1400
29 strictly we could get away with 1310 and use _ReadWriteBarrier, but the difference between 1310 and 1400 is small, so WTH
31 _InterlockedCompareExchange128 is needed on 64-bit platforms to provide DWCAS, but DWCAS is not mandatory,
32 so we check against the compiler version - remember, any unimplemented atomic will be masked by its dummy define,
33 so everything will compile - it just means you can't use data structures which require that atomic
36 #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
37 #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_compiler.h
40 #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
42 #define LFDS700_PAL_COMPILER_STRING "MSVC"
44 #define LFDS700_PAL_ALIGN(alignment) __declspec( align(alignment) )
45 #define LFDS700_PAL_INLINE __forceinline
47 #define LFDS700_PAL_BARRIER_COMPILER_LOAD _ReadBarrier()
48 #define LFDS700_PAL_BARRIER_COMPILER_STORE _WriteBarrier()
49 #define LFDS700_PAL_BARRIER_COMPILER_FULL _ReadWriteBarrier()
51 /* TRD : there are four processors to consider;
53 . ARM32 (32 bit, CAS, DWCAS) (defined _M_ARM)
54 . Itanium (64 bit, CAS) (defined _M_IA64)
55 . x64 (64 bit, CAS, DWCAS) (defined _M_X64 || defined _M_AMD64)
56 . x86 (32 bit, CAS, DWCAS) (defined _M_IX86)
58 can't find any indications of 64-bit ARM support yet
60 ARM has better intrinsics than the others, as there are no-fence variants
62 in theory we also have to deal with 32-bit Windows on a 64-bit platform,
63 and I presume we'd see the compiler properly indicate this in its macros,
64 but this would require that we use 32-bit atomics on the 64-bit platforms,
65 while keeping 64-bit cache line lengths and so on, and this is just so
66 wierd a thing to do these days that it's not supported
68 note that _InterlockedCompareExchangePointer performs CAS on all processors
69 however, it is documented as being available for x86 when in fact it is not
70 so we have to #if for processor type and use the length specific intrinsics
74 #define LFDS700_PAL_BARRIER_PROCESSOR_LOAD __dmb( _ARM_BARRIER_ISH )
75 #define LFDS700_PAL_BARRIER_PROCESSOR_STORE __dmb( _ARM_BARRIER_ISHST )
76 #define LFDS700_PAL_BARRIER_PROCESSOR_FULL __dmb( _ARM_BARRIER_ISH )
78 #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
83 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
84 /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
85 /* TRD : new_destination can be any value in its range */ \
86 /* TRD : cas_strength can be any value in its range */ \
87 /* TRD : result can be any value in its range */ \
89 original_compare = (lfds700_pal_atom_t) *(pointer_to_compare); \
91 LFDS700_PAL_BARRIER_COMPILER_FULL; \
92 *(lfds700_pal_atom_t *) (pointer_to_compare) = (lfds700_pal_atom_t) _InterlockedCompareExchange_nf( (long volatile *) (pointer_to_destination), (long) (new_destination), (long) *(pointer_to_compare) ); \
93 LFDS700_PAL_BARRIER_COMPILER_FULL; \
95 result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) ); \
98 #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
103 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
104 /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
105 /* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */ \
106 /* TRD : cas_strength can be any value in its range */ \
107 /* TRD : result can be any value in its range */ \
109 original_compare = *(__int64 *) (pointer_to_compare); \
111 LFDS700_PAL_BARRIER_COMPILER_FULL; \
112 *(__int64 *) (pointer_to_compare) = _InterlockedCompareExchange64_nf( (__int64 volatile *) (pointer_to_destination), *(__int64 *) (pointer_to_new_destination), *(__int64 *) (pointer_to_compare) ); \
113 LFDS700_PAL_BARRIER_COMPILER_FULL; \
115 result = (char unsigned) ( *(__int64 *) (pointer_to_compare) == original_compare ); \
118 #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
120 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
121 /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */ \
123 LFDS700_PAL_BARRIER_COMPILER_FULL; \
124 *(lfds700_pal_atom_t *) (pointer_to_exchange) = (lfds700_pal_atom_t) _InterlockedExchange_nf( (int long volatile *) (pointer_to_destination), (int long) *(pointer_to_exchange) ); \
125 LFDS700_PAL_BARRIER_COMPILER_FULL; \
129 #if( defined _M_IA64 )
130 #define LFDS700_PAL_BARRIER_PROCESSOR_LOAD __mf()
131 #define LFDS700_PAL_BARRIER_PROCESSOR_STORE __mf()
132 #define LFDS700_PAL_BARRIER_PROCESSOR_FULL __mf()
134 #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
139 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
140 /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
141 /* TRD : new_destination can be any value in its range */ \
142 /* TRD : cas_strength can be any value in its range */ \
143 /* TRD : result can be any value in its range */ \
145 original_compare = (lfds700_pal_atom_t) *(pointer_to_compare); \
147 LFDS700_PAL_BARRIER_COMPILER_FULL; \
148 *(lfds700_pal_atom_t *) (pointer_to_compare) = (lfds700_pal_atom_t) _InterlockedCompareExchange64_acq( (__int64 volatile *) (pointer_to_destination), (__int64) (new_destination), (__int64) *(pointer_to_compare) ); \
149 LFDS700_PAL_BARRIER_COMPILER_FULL; \
151 result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) ); \
154 #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
156 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
157 /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */ \
159 LFDS700_PAL_BARRIER_COMPILER_FULL; \
160 *(lfds700_pal_atom_t *) (pointer_to_exchange) = (lfds700_pal_atom_t) _InterlockedExchange64_acq( (__int64 volatile *) (pointer_to_destination), (__int64) *(pointer_to_exchange) ); \
161 LFDS700_PAL_BARRIER_COMPILER_FULL; \
165 #if( defined _M_X64 || defined _M_AMD64 )
166 #define LFDS700_PAL_BARRIER_PROCESSOR_LOAD _mm_lfence()
167 #define LFDS700_PAL_BARRIER_PROCESSOR_STORE _mm_sfence()
168 #define LFDS700_PAL_BARRIER_PROCESSOR_FULL _mm_mfence()
170 #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
175 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
176 /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
177 /* TRD : new_destination can be any value in its range */ \
178 /* TRD : cas_strength can be any value in its range */ \
179 /* TRD : result can be any value in its range */ \
181 original_compare = (lfds700_pal_atom_t) *(pointer_to_compare); \
183 LFDS700_PAL_BARRIER_COMPILER_FULL; \
184 *(lfds700_pal_atom_t *) (pointer_to_compare) = (lfds700_pal_atom_t) _InterlockedCompareExchange64( (__int64 volatile *) (pointer_to_destination), (__int64) (new_destination), (__int64) *(pointer_to_compare) ); \
185 LFDS700_PAL_BARRIER_COMPILER_FULL; \
187 result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) ); \
190 #if( _MSC_VER >= 1500 )
191 #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
193 /* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */ \
194 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
195 /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
196 /* TRD : cas_strength can be any value in its range */ \
197 /* TRD : result can be any value in its range */ \
199 LFDS700_PAL_BARRIER_COMPILER_FULL; \
200 result = (char unsigned) _InterlockedCompareExchange128( (__int64 volatile *) (pointer_to_destination), (__int64) (pointer_to_new_destination[1]), (__int64) (pointer_to_new_destination[0]), (__int64 *) (pointer_to_compare) ); \
201 LFDS700_PAL_BARRIER_COMPILER_FULL; \
205 #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
207 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
208 /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */ \
210 LFDS700_PAL_BARRIER_COMPILER_FULL; \
211 *(lfds700_pal_atom_t *) (pointer_to_exchange) = (lfds700_pal_atom_t) _InterlockedExchangePointer( (void * volatile *) (pointer_to_destination), (void *) *(pointer_to_exchange) ); \
212 LFDS700_PAL_BARRIER_COMPILER_FULL; \
216 #if( defined _M_IX86 )
217 #define LFDS700_PAL_BARRIER_PROCESSOR_LOAD lfds700_misc_force_store()
218 #define LFDS700_PAL_BARRIER_PROCESSOR_STORE lfds700_misc_force_store()
219 #define LFDS700_PAL_BARRIER_PROCESSOR_FULL lfds700_misc_force_store()
221 #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
226 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
227 /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
228 /* TRD : new_destination can be any value in its range */ \
229 /* TRD : cas_strength can be any value in its range */ \
230 /* TRD : result can be any value in its range */ \
232 original_compare = (lfds700_pal_atom_t) *(pointer_to_compare); \
234 LFDS700_PAL_BARRIER_COMPILER_FULL; \
235 *(lfds700_pal_atom_t *) (pointer_to_compare) = (lfds700_pal_atom_t) _InterlockedCompareExchange( (long volatile *) (pointer_to_destination), (long) (new_destination), (long) *(pointer_to_compare) ); \
236 LFDS700_PAL_BARRIER_COMPILER_FULL; \
238 result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) ); \
241 #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
246 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
247 /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
248 /* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */ \
249 /* TRD : cas_strength can be any value in its range */ \
250 /* TRD : result can be any value in its range */ \
252 original_compare = *(__int64 *) (pointer_to_compare); \
254 LFDS700_PAL_BARRIER_COMPILER_FULL; \
255 *(__int64 *) (pointer_to_compare) = _InterlockedCompareExchange64( (__int64 volatile *) (pointer_to_destination), *(__int64 *) (pointer_to_new_destination), *(__int64 *) (pointer_to_compare) ); \
256 LFDS700_PAL_BARRIER_COMPILER_FULL; \
258 result = (char unsigned) ( *(__int64 *) (pointer_to_compare) == original_compare ); \
261 #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
263 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
264 /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */ \
266 LFDS700_PAL_BARRIER_COMPILER_FULL; \
267 *(lfds700_pal_atom_t *) (pointer_to_exchange) = (lfds700_pal_atom_t) _InterlockedExchange( (int long volatile *) (pointer_to_destination), (int long) *(pointer_to_exchange) ); \
268 LFDS700_PAL_BARRIER_COMPILER_FULL; \
278 /****************************************************************************/
279 #if( defined __GNUC__ && LFDS700_PAL_GCC_VERSION >= 412 && LFDS700_PAL_GCC_VERSION < 473 )
281 /* TRD : GCC 4.1.2 up to 4.7.3
283 __GNUC__ indicates GCC
284 LFDS700_PAL_GCC_VERSION indicates which version
285 - __sync_synchronize requires 4.1.2
287 GCC 4.1.2 introduced the __sync_*() atomic intrinsics
290 #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
291 #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_compiler.h
294 #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
296 #define LFDS700_PAL_COMPILER_STRING "GCC < 4.7.3"
298 #define LFDS700_PAL_ALIGN(alignment) __attribute__( (aligned(alignment)) )
299 #define LFDS700_PAL_INLINE inline
301 static LFDS700_PAL_INLINE void lfds700_pal_barrier_compiler( void )
303 __asm__ __volatile__ ( "" : : : "memory" );
306 #define LFDS700_PAL_BARRIER_COMPILER_LOAD lfds700_pal_barrier_compiler()
307 #define LFDS700_PAL_BARRIER_COMPILER_STORE lfds700_pal_barrier_compiler()
308 #define LFDS700_PAL_BARRIER_COMPILER_FULL lfds700_pal_barrier_compiler()
310 #define LFDS700_PAL_BARRIER_PROCESSOR_LOAD __sync_synchronize()
311 #define LFDS700_PAL_BARRIER_PROCESSOR_STORE __sync_synchronize()
312 #define LFDS700_PAL_BARRIER_PROCESSOR_FULL __sync_synchronize()
314 #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
319 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
320 /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
321 /* TRD : new_destination can be any value in its range */ \
322 /* TRD : cas_strength can be any value in its range */ \
323 /* TRD : result can be any value in its range */ \
325 original_compare = (lfds700_pal_atom_t) *(pointer_to_compare); \
327 LFDS700_PAL_BARRIER_COMPILER_FULL; \
328 *(pointer_to_compare) = __sync_val_compare_and_swap( pointer_to_destination, *(pointer_to_compare), new_destination ); \
329 LFDS700_PAL_BARRIER_COMPILER_FULL; \
331 result = (unsigned char) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) ); \
334 // TRD : ARM and x86 have DWCAS which we can get via GCC intrinsics
335 #if( defined __arm__ || defined __i686__ || defined __i586__ || defined __i486__ )
336 #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
338 int long long unsigned \
339 original_destination; \
341 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
342 /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
343 /* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */ \
344 /* TRD : cas_strength can be any value in its range */ \
345 /* TRD : result can be any value in its range */ \
347 LFDS700_PAL_BARRIER_COMPILER_FULL; \
348 original_destination = __sync_val_compare_and_swap( (int long long unsigned volatile *) (pointer_to_destination), *(int long long unsigned *) (pointer_to_compare), *(int long long unsigned *) (pointer_to_new_destination) ); \
349 LFDS700_PAL_BARRIER_COMPILER_FULL; \
351 result = (char unsigned) ( original_destination == *(int long long unsigned *) (pointer_to_compare) ); \
353 *(int long long unsigned *) (pointer_to_compare) = original_destination; \
357 #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
359 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
360 /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */ \
362 LFDS700_PAL_BARRIER_COMPILER_FULL; \
363 *( (lfds700_pal_atom_t *) pointer_to_exchange) = (lfds700_pal_atom_t) __sync_lock_test_and_set( pointer_to_destination, *(pointer_to_exchange) ); \
364 LFDS700_PAL_BARRIER_COMPILER_FULL; \
373 /****************************************************************************/
374 #if( defined __GNUC__ && LFDS700_PAL_GCC_VERSION >= 473 )
376 /* TRD : GCC 4.7.3 and greater
378 __GNUC__ indicates GCC
379 LFDS700_PAL_GCC_VERSION indicates which version
380 - __atomic_thread_fence requires 4.7.3
382 GCC 4.7.3 introduced the better __atomic*() atomic intrinsics
385 #ifdef LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
386 #error More than one porting abstraction layer matches the current platform in lfds700_porting_abstraction_layer_compiler.h
389 #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
391 #define LFDS700_PAL_COMPILER_STRING "GCC >= 4.7.3"
393 #define LFDS700_PAL_ALIGN(alignment) __attribute__( (aligned(alignment)) )
394 #define LFDS700_PAL_INLINE inline
396 // TRD : GCC >= 4.7.3 compiler barriers are built into the intrinsics
397 #define LFDS700_PAL_NO_COMPILER_BARRIERS
399 #define LFDS700_PAL_BARRIER_PROCESSOR_LOAD __atomic_thread_fence( __ATOMIC_ACQUIRE )
400 #define LFDS700_PAL_BARRIER_PROCESSOR_STORE __atomic_thread_fence( __ATOMIC_RELEASE )
401 #define LFDS700_PAL_BARRIER_PROCESSOR_FULL __atomic_thread_fence( __ATOMIC_ACQ_REL )
403 #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
405 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
406 /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
407 /* TRD : new_destination can be any value in its range */ \
408 /* TRD : cas_strength can be any value in its range */ \
409 /* TRD : result can be any value in its range */ \
411 result = (char unsigned) __atomic_compare_exchange_n( pointer_to_destination, (void *) (pointer_to_compare), (new_destination), (cas_strength), __ATOMIC_RELAXED, __ATOMIC_RELAXED ); \
414 // TRD : ARM and x86 have DWCAS which we can get via GCC intrinsics
415 #if( defined __arm__ || defined __i686__ || defined __i586__ || defined __i486__ )
416 #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
418 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
419 /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
420 /* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */ \
421 /* TRD : cas_strength can be any value in its range */ \
422 /* TRD : result can be any value in its range */ \
424 (result) = (char unsigned) __atomic_compare_exchange_n( (int long long unsigned volatile *) (pointer_to_destination), (int long long unsigned *) (pointer_to_compare), *(int long long unsigned *) (pointer_to_new_destination), (cas_strength), __ATOMIC_RELAXED, __ATOMIC_RELAXED ); \
428 #if( defined __x86_64__ )
429 /* TRD : __GNUC__ indicates GCC
430 - __asm__ requires GCC
431 - __volatile__ requires GCC
432 __x86_64__ indicates x64
433 - cmpxchg16b requires x64
435 On 64 bit platforms, unsigned long long int is 64 bit, so we must manually use cmpxchg16b,
436 as __sync_val_compare_and_swap() will only emit cmpxchg8b
439 // TRD : lfds700_pal_atom_t volatile (*destination)[2], lfds700_pal_atom_t (*compare)[2], lfds700_pal_atom_t (*new_destination)[2], enum lfds700_misc_cas_strength cas_strength, char unsigned result
441 #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
443 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
444 /* LFDS700_PAL_ASSERT( (pointer_to_compare) != NULL ); */ \
445 /* LFDS700_PAL_ASSERT( (pointer_to_new_destination) != NULL ); */ \
446 /* TRD : cas_strength can be any value in its range */ \
447 /* TRD : result can be any value in its range */ \
451 __asm__ __volatile__ \
453 "lock;" /* make cmpxchg16b atomic */ \
454 "cmpxchg16b %0;" /* cmpxchg16b sets ZF on success */ \
455 "setz %3;" /* if ZF set, set result to 1 */ \
458 : "+m" (*pointer_to_destination), "+a" ((pointer_to_compare)[0]), "+d" ((pointer_to_compare)[1]), "=q" (result) \
461 : "b" ((pointer_to_new_destination)[0]), "c" ((pointer_to_new_destination)[1]) \
469 #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
471 /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */ \
472 /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */ \
474 *(pointer_to_exchange) = __atomic_exchange_n( (pointer_to_destination), *(pointer_to_exchange), __ATOMIC_RELAXED ); \