]> pd.if.org Git - liblfds/blob - liblfds/liblfds6.1.0/liblfds610/src/lfds610_abstraction/lfds610_abstraction_dcas.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds6.1.0 / liblfds610 / src / lfds610_abstraction / lfds610_abstraction_dcas.c
1 #include "lfds610_abstraction_internal_body.h"
2
3
4
5
6
7 /****************************************************************************/
8 #if (defined _WIN64 && defined _MSC_VER)
9
10   /* TRD : 64 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
11
12            _WIN64    indicates 64 bit Windows
13            _MSC_VER  indicates Microsoft C compiler
14   */
15
16   static LFDS610_INLINE unsigned char lfds610_abstraction_dcas( volatile lfds610_atom_t *destination, lfds610_atom_t *exchange, lfds610_atom_t *compare )
17   {
18     assert( destination != NULL );
19     assert( exchange != NULL );
20     assert( compare != NULL );
21
22     return( _InterlockedCompareExchange128((volatile __int64 *) destination, (__int64) *(exchange+1), (__int64) *exchange, (__int64 *) compare) );
23   }
24
25 #endif
26
27
28
29
30
31 /****************************************************************************/
32 #if (!defined _WIN64 && defined _WIN32 && defined _MSC_VER)
33
34   /* TRD : 32 bit Windows (user-mode or kernel) on any CPU with the Microsoft C compiler
35
36            (!defined _WIN64 && defined _WIN32)  indicates 32 bit Windows
37            _MSC_VER                             indicates Microsoft C compiler
38   */
39
40   static LFDS610_INLINE unsigned char lfds610_abstraction_dcas( volatile lfds610_atom_t *destination, lfds610_atom_t *exchange, lfds610_atom_t *compare )
41   {
42     __int64
43       original_compare;
44
45     assert( destination != NULL );
46     assert( exchange != NULL );
47     assert( compare != NULL );
48
49     *(__int64 *) &original_compare = *(__int64 *) compare;
50
51     *(__int64 *) compare = _InterlockedCompareExchange64( (volatile __int64 *) destination, *(__int64 *) exchange, *(__int64 *) compare );
52
53     return( (unsigned char) (*(__int64 *) compare == *(__int64 *) &original_compare) );
54   }
55
56 #endif
57
58
59
60
61
62 /****************************************************************************/
63 #if (defined __x86_64__ && defined __GNUC__)
64
65   /* TRD : any OS on x64 with GCC
66
67            __x86_64__  indicates x64
68            __GNUC__    indicates GCC
69   */
70
71   static LFDS610_INLINE unsigned char lfds610_abstraction_dcas( volatile lfds610_atom_t *destination, lfds610_atom_t *exchange, lfds610_atom_t *compare )
72   {
73     unsigned char
74       cas_result;
75
76     assert( destination != NULL );
77     assert( exchange != NULL );
78     assert( compare != NULL );
79
80     __asm__ __volatile__
81     (
82       "lock;"           // make cmpxchg16b atomic
83       "cmpxchg16b %0;"  // cmpxchg16b sets ZF on success
84       "setz       %3;"  // if ZF set, set cas_result to 1
85
86       // output
87       : "+m" (*(volatile lfds610_atom_t (*)[2]) destination), "+a" (*compare), "+d" (*(compare+1)), "=q" (cas_result)
88
89       // input
90       : "b" (*exchange), "c" (*(exchange+1))
91
92       // clobbered
93       : "cc", "memory"
94     );
95
96     return( cas_result );
97   }
98
99 #endif
100
101
102
103
104
105 /****************************************************************************/
106 #if ((defined __i686__ || defined __arm__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1 && __GNUC_PATCHLEVEL__ >= 0)
107
108   /* TRD : any OS on x86 or ARM with GCC 4.1.0 or better
109
110            GCC 4.1.0 introduced the __sync_*() atomic intrinsics
111
112            __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__  indicates GCC and which version
113   */
114
115   static LFDS610_INLINE unsigned char lfds610_abstraction_dcas( volatile lfds610_atom_t *destination, lfds610_atom_t *exchange, lfds610_atom_t *compare )
116   {
117     unsigned char
118       cas_result = 0;
119
120     unsigned long long int
121       original_destination;
122
123     assert( destination != NULL );
124     assert( exchange != NULL );
125     assert( compare != NULL );
126
127     original_destination = __sync_val_compare_and_swap( (volatile unsigned long long int *) destination, *(unsigned long long int *) compare, *(unsigned long long int *) exchange );
128
129     if( original_destination == *(unsigned long long int *) compare )
130       cas_result = 1;
131
132     *(unsigned long long int *) compare = original_destination;
133
134     return( cas_result );
135   }
136
137 #endif
138
139