]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_porting_abstraction_layer_compiler.h
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / liblfds700 / inc / liblfds700 / lfds700_porting_abstraction_layer_compiler.h
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__ )
5 #endif
6
7
8
9
10
11 /****************************************************************************/
12 #if( defined _MSC_VER && _MSC_VER >= 1400 )
13
14   /* TRD : MSVC 8.0 and greater
15
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)
27
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
30
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
34   */
35
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
38   #endif
39
40   #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
41
42   #define LFDS700_PAL_COMPILER_STRING            "MSVC"
43
44   #define LFDS700_PAL_ALIGN(alignment)           __declspec( align(alignment) )
45   #define LFDS700_PAL_INLINE                     __forceinline
46
47   #define LFDS700_PAL_BARRIER_COMPILER_LOAD      _ReadBarrier()
48   #define LFDS700_PAL_BARRIER_COMPILER_STORE     _WriteBarrier()
49   #define LFDS700_PAL_BARRIER_COMPILER_FULL      _ReadWriteBarrier()
50
51   /* TRD : there are four processors to consider;
52
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)
57
58            can't find any indications of 64-bit ARM support yet
59
60            ARM has better intrinsics than the others, as there are no-fence variants
61
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
67
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
71   */
72
73   #if( defined _M_ARM )
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 )
77
78     #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )                                                                                          \
79     {                                                                                                                                                                                                            \
80       lfds700_pal_atom_t                                                                                                                                                                                         \
81         original_compare;                                                                                                                                                                                        \
82                                                                                                                                                                                                                  \
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 */                                                                                                                                                           \
88                                                                                                                                                                                                                  \
89       original_compare = (lfds700_pal_atom_t) *(pointer_to_compare);                                                                                                                                             \
90                                                                                                                                                                                                                  \
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;                                                                                                                                                                         \
94                                                                                                                                                                                                                  \
95       result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) );                                                                                                               \
96     }
97
98     #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result )                                                                        \
99     {                                                                                                                                                                                                       \
100       __int64                                                                                                                                                                                               \
101         original_compare;                                                                                                                                                                                   \
102                                                                                                                                                                                                             \
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 */                                                                                                                                                      \
108                                                                                                                                                                                                             \
109       original_compare = *(__int64 *) (pointer_to_compare);                                                                                                                                                 \
110                                                                                                                                                                                                             \
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;                                                                                                                                                                    \
114                                                                                                                                                                                                             \
115       result = (char unsigned) ( *(__int64 *) (pointer_to_compare) == original_compare );                                                                                                                   \
116     }
117
118     #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange )                                                                                                    \
119     {                                                                                                                                                                                     \
120       /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                       \
121       /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */                                                                                                                          \
122                                                                                                                                                                                           \
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;                                                                                                                                                  \
126     }
127   #endif
128
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()
133
134     #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )                                                                                         \
135     {                                                                                                                                                                                                           \
136       lfds700_pal_atom_t                                                                                                                                                                                        \
137         original_compare;                                                                                                                                                                                       \
138                                                                                                                                                                                                                 \
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 */                                                                                                                                                          \
144                                                                                                                                                                                                                 \
145       original_compare = (lfds700_pal_atom_t) *(pointer_to_compare);                                                                                                                                            \
146                                                                                                                                                                                                                 \
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;                                                                                                                                                                        \
150                                                                                                                                                                                                                 \
151       result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) );                                                                                                              \
152     }
153
154     #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange )                                                                                                     \
155     {                                                                                                                                                                                      \
156       /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                        \
157       /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */                                                                                                                           \
158                                                                                                                                                                                            \
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;                                                                                                                                                   \
162     }
163   #endif
164
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()
169
170     #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )                                                                                                  \
171     {                                                                                                                                                                                                                    \
172       lfds700_pal_atom_t                                                                                                                                                                                                 \
173         original_compare;                                                                                                                                                                                                \
174                                                                                                                                                                                                                          \
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 */                                                                                                                                                                   \
180                                                                                                                                                                                                                          \
181       original_compare = (lfds700_pal_atom_t) *(pointer_to_compare);                                                                                                                                                     \
182                                                                                                                                                                                                                          \
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;                                                                                                                                                                                 \
186                                                                                                                                                                                                                          \
187       result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) );                                                                                                                       \
188     }
189
190     #if( _MSC_VER >= 1500 )
191       #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result )                                                                                                     \
192       {                                                                                                                                                                                                                                    \
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 */                                                                                                                                                                                   \
198                                                                                                                                                                                                                                            \
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;                                                                                                                                                                                                 \
202       }
203     #endif
204
205     #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange )                                                                                                    \
206     {                                                                                                                                                                                     \
207       /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                       \
208       /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */                                                                                                                          \
209                                                                                                                                                                                           \
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;                                                                                                                                                  \
213     }
214   #endif
215
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()
220
221     #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )                                                                                       \
222     {                                                                                                                                                                                                         \
223       lfds700_pal_atom_t                                                                                                                                                                                      \
224         original_compare;                                                                                                                                                                                     \
225                                                                                                                                                                                                               \
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 */                                                                                                                                                        \
231                                                                                                                                                                                                               \
232       original_compare = (lfds700_pal_atom_t) *(pointer_to_compare);                                                                                                                                          \
233                                                                                                                                                                                                               \
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;                                                                                                                                                                      \
237                                                                                                                                                                                                               \
238       result = (char unsigned) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) );                                                                                                            \
239     }
240
241     #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result )                                                                     \
242     {                                                                                                                                                                                                    \
243       __int64                                                                                                                                                                                            \
244         original_compare;                                                                                                                                                                                \
245                                                                                                                                                                                                          \
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 */                                                                                                                                                   \
251                                                                                                                                                                                                          \
252       original_compare = *(__int64 *) (pointer_to_compare);                                                                                                                                              \
253                                                                                                                                                                                                          \
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;                                                                                                                                                                 \
257                                                                                                                                                                                                          \
258       result = (char unsigned) ( *(__int64 *) (pointer_to_compare) == original_compare );                                                                                                                \
259     }
260
261     #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange )                                                                                                 \
262     {                                                                                                                                                                                  \
263       /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                                                    \
264       /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */                                                                                                                       \
265                                                                                                                                                                                        \
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;                                                                                                                                               \
269     }
270   #endif
271
272 #endif
273
274
275
276
277
278 /****************************************************************************/
279 #if( defined __GNUC__ && LFDS700_PAL_GCC_VERSION >= 412 && LFDS700_PAL_GCC_VERSION < 473 )
280
281   /* TRD : GCC 4.1.2 up to 4.7.3
282
283            __GNUC__                 indicates GCC
284            LFDS700_PAL_GCC_VERSION  indicates which version
285                                       - __sync_synchronize requires 4.1.2
286
287            GCC 4.1.2 introduced the __sync_*() atomic intrinsics
288   */
289
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
292   #endif
293
294   #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
295
296   #define LFDS700_PAL_COMPILER_STRING          "GCC < 4.7.3"
297
298   #define LFDS700_PAL_ALIGN(alignment)         __attribute__( (aligned(alignment)) )
299   #define LFDS700_PAL_INLINE                   inline
300
301   static LFDS700_PAL_INLINE void lfds700_pal_barrier_compiler( void )
302   {
303     __asm__ __volatile__ ( "" : : : "memory" );
304   }
305
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()
309
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()
313
314   #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )       \
315   {                                                                                                                         \
316     lfds700_pal_atom_t                                                                                                      \
317       original_compare;                                                                                                     \
318                                                                                                                             \
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 */                                                                        \
324                                                                                                                             \
325     original_compare = (lfds700_pal_atom_t) *(pointer_to_compare);                                                          \
326                                                                                                                             \
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;                                                                                      \
330                                                                                                                             \
331     result = (unsigned char) ( original_compare == (lfds700_pal_atom_t) *(pointer_to_compare) );                            \
332   }
333
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 )                                                                                                   \
337     {                                                                                                                                                                                                                                  \
338       int long long unsigned                                                                                                                                                                                                           \
339         original_destination;                                                                                                                                                                                                          \
340                                                                                                                                                                                                                                        \
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 */                                                                                                                                                                                 \
346                                                                                                                                                                                                                                        \
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;                                                                                                                                                                                               \
350                                                                                                                                                                                                                                        \
351       result = (char unsigned) ( original_destination == *(int long long unsigned *) (pointer_to_compare) );                                                                                                                           \
352                                                                                                                                                                                                                                        \
353       *(int long long unsigned *) (pointer_to_compare) = original_destination;                                                                                                                                                         \
354     }
355   #endif
356
357   #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange )                                                                   \
358   {                                                                                                                                                    \
359     /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                                                      \
360     /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */                                                                                         \
361                                                                                                                                                        \
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;                                                                                                                 \
365   }
366
367 #endif
368
369
370
371
372
373 /****************************************************************************/
374 #if( defined __GNUC__ && LFDS700_PAL_GCC_VERSION >= 473 )
375
376   /* TRD : GCC 4.7.3 and greater
377
378            __GNUC__                 indicates GCC
379            LFDS700_PAL_GCC_VERSION  indicates which version
380                                       - __atomic_thread_fence requires 4.7.3
381
382            GCC 4.7.3 introduced the better __atomic*() atomic intrinsics
383   */
384
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
387   #endif
388
389   #define LFDS700_PAL_PORTING_ABSTRACTION_LAYER_COMPILER
390
391   #define LFDS700_PAL_COMPILER_STRING          "GCC >= 4.7.3"
392
393   #define LFDS700_PAL_ALIGN(alignment)         __attribute__( (aligned(alignment)) )
394   #define LFDS700_PAL_INLINE                   inline
395
396   // TRD : GCC >= 4.7.3 compiler barriers are built into the intrinsics
397   #define LFDS700_PAL_NO_COMPILER_BARRIERS
398
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 )
402
403   #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )                                                                      \
404   {                                                                                                                                                                                        \
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 */                                                                                                                                       \
410                                                                                                                                                                                            \
411     result = (char unsigned) __atomic_compare_exchange_n( pointer_to_destination, (void *) (pointer_to_compare), (new_destination), (cas_strength), __ATOMIC_RELAXED, __ATOMIC_RELAXED );  \
412   }
413
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 )                                                                                                                                                          \
417     {                                                                                                                                                                                                                                                                                         \
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 */                                                                                                                                                                                                                                        \
423                                                                                                                                                                                                                                                                                               \
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 );  \
425     }
426   #endif
427
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
434
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
437     */
438
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
440
441     #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result )  \
442     {                                                                                                                                 \
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 */                                                                                \
448                                                                                                                                       \
449       (result) = 0;                                                                                                                   \
450                                                                                                                                       \
451       __asm__ __volatile__                                                                                                            \
452       (                                                                                                                               \
453         "lock;"           /* make cmpxchg16b atomic        */                                                                         \
454         "cmpxchg16b %0;"  /* cmpxchg16b sets ZF on success */                                                                         \
455         "setz       %3;"  /* if ZF set, set result to 1    */                                                                         \
456                                                                                                                                       \
457         /* output */                                                                                                                  \
458         : "+m" (*pointer_to_destination), "+a" ((pointer_to_compare)[0]), "+d" ((pointer_to_compare)[1]), "=q" (result)               \
459                                                                                                                                       \
460         /* input */                                                                                                                   \
461         : "b" ((pointer_to_new_destination)[0]), "c" ((pointer_to_new_destination)[1])                                                \
462                                                                                                                                       \
463         /* clobbered */                                                                                                               \
464         : "cc", "memory"                                                                                                              \
465       );                                                                                                                              \
466     }
467   #endif
468
469   #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange )                                     \
470   {                                                                                                                      \
471     /* LFDS700_PAL_ASSERT( (pointer_to_destination) != NULL ); */                                                        \
472     /* LFDS700_PAL_ASSERT( (pointer_to_exchange) != NULL ); */                                                           \
473                                                                                                                          \
474     *(pointer_to_exchange) = __atomic_exchange_n( (pointer_to_destination), *(pointer_to_exchange), __ATOMIC_RELAXED );  \
475   }
476
477 #endif
478