1 #include "lfds611_abstraction_internal_body.h"
7 /****************************************************************************/
8 #if (defined _WIN64 && defined _MSC_VER)
10 /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
12 _WIN64 indicates 64 bit Windows
13 _MSC_VER indicates Microsoft C compiler
16 static LFDS611_INLINE unsigned char lfds611_abstraction_dcas( volatile lfds611_atom_t *destination, lfds611_atom_t *exchange, lfds611_atom_t *compare )
21 assert( destination != NULL );
22 assert( exchange != NULL );
23 assert( compare != NULL );
25 LFDS611_BARRIER_COMPILER_FULL;
27 cas_result = _InterlockedCompareExchange128( (volatile __int64 *) destination, (__int64) *(exchange+1), (__int64) *exchange, (__int64 *) compare );
29 LFDS611_BARRIER_COMPILER_FULL;
31 return( cas_result ) ;
40 /****************************************************************************/
41 #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER)
43 /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
45 (!defined _WIN64 && defined _WIN32) indicates 32 bit Windows
46 _MSC_VER indicates Microsoft C compiler
49 static LFDS611_INLINE unsigned char lfds611_abstraction_dcas( volatile lfds611_atom_t *destination, lfds611_atom_t *exchange, lfds611_atom_t *compare )
54 assert( destination != NULL );
55 assert( exchange != NULL );
56 assert( compare != NULL );
58 *(__int64 *) &original_compare = *(__int64 *) compare;
60 LFDS611_BARRIER_COMPILER_FULL;
62 *(__int64 *) compare = _InterlockedCompareExchange64( (volatile __int64 *) destination, *(__int64 *) exchange, *(__int64 *) compare );
64 LFDS611_BARRIER_COMPILER_FULL;
66 return( (unsigned char) (*(__int64 *) compare == *(__int64 *) &original_compare) );
75 /****************************************************************************/
76 #if (defined __x86_64__ && defined __GNUC__)
78 /* TRD : any OS on x64 with GCC
80 __x86_64__ indicates x64
81 __GNUC__ indicates GCC
84 static LFDS611_INLINE unsigned char lfds611_abstraction_dcas( volatile lfds611_atom_t *destination, lfds611_atom_t *exchange, lfds611_atom_t *compare )
89 assert( destination != NULL );
90 assert( exchange != NULL );
91 assert( compare != NULL );
93 // TRD : __asm__ with "memory" in the clobber list is for GCC a full compiler barrier
96 "lock;" // make cmpxchg16b atomic
97 "cmpxchg16b %0;" // cmpxchg16b sets ZF on success
98 "setz %3;" // if ZF set, set cas_result to 1
101 : "+m" (*(volatile lfds611_atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
104 : "b" (*exchange), "c" (*(exchange+1))
110 return( cas_result );
119 /****************************************************************************/
120 #if ((defined __i686__ || defined __arm__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
122 /* TRD : any OS on x86 or ARM with GCC 4.1.0 or better
124 GCC 4.1.0 introduced the __sync_*() atomic intrinsics
126 __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ indicates GCC and which version
129 static LFDS611_INLINE unsigned char lfds611_abstraction_dcas( volatile lfds611_atom_t *destination, lfds611_atom_t *exchange, lfds611_atom_t *compare )
134 unsigned long long int
135 original_destination;
137 assert( destination != NULL );
138 assert( exchange != NULL );
139 assert( compare != NULL );
141 LFDS611_BARRIER_COMPILER_FULL;
143 original_destination = __sync_val_compare_and_swap( (volatile unsigned long long int *) destination, *(unsigned long long int *) compare, *(unsigned long long int *) exchange );
145 LFDS611_BARRIER_COMPILER_FULL;
147 if( original_destination == *(unsigned long long int *) compare )
150 *(unsigned long long int *) compare = original_destination;
152 return( cas_result );