2 * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.
3 * Copyright (c) 2009-2018 Ivan Maidanski
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 /* This file contains AO primitives based on VC++ built-in intrinsic */
25 /* functions commonly available across 32-bit architectures. */
27 /* This file should be included from arch-specific header files. */
28 /* Define AO_USE_INTERLOCKED_INTRINSICS if _Interlocked primitives */
29 /* (used below) are available as intrinsic ones for a target arch */
30 /* (otherwise "Interlocked" functions family is used instead). */
31 /* Define AO_ASSUME_WINDOWS98 if CAS is available. */
33 #if _MSC_VER <= 1400 || !defined(AO_USE_INTERLOCKED_INTRINSICS) \
34 || defined(_WIN32_WCE)
36 /* Seems like over-kill, but that's what MSDN recommends. */
37 /* And apparently winbase.h is not always self-contained. */
40 #if _MSC_VER < 1310 || !defined(AO_USE_INTERLOCKED_INTRINSICS)
42 # define _InterlockedIncrement InterlockedIncrement
43 # define _InterlockedDecrement InterlockedDecrement
44 # define _InterlockedExchangeAdd InterlockedExchangeAdd
45 # define _InterlockedCompareExchange InterlockedCompareExchange
47 # define AO_INTERLOCKED_VOLATILE /**/
49 #else /* elif _MSC_VER >= 1310 */
56 # else /* elif _MSC_VER < 1400 */
60 LONG __cdecl _InterlockedIncrement(LONG volatile *);
61 LONG __cdecl _InterlockedDecrement(LONG volatile *);
62 LONG __cdecl _InterlockedExchangeAdd(LONG volatile *, LONG);
63 LONG __cdecl _InterlockedCompareExchange(LONG volatile *,
64 LONG /* Exchange */, LONG /* Comp */);
68 # endif /* _MSC_VER < 1400 */
70 # if !defined(AO_PREFER_GENERALIZED) || !defined(AO_ASSUME_WINDOWS98)
71 # pragma intrinsic (_InterlockedIncrement)
72 # pragma intrinsic (_InterlockedDecrement)
73 # pragma intrinsic (_InterlockedExchangeAdd)
74 # endif /* !AO_PREFER_GENERALIZED */
75 # pragma intrinsic (_InterlockedCompareExchange)
77 # define AO_INTERLOCKED_VOLATILE volatile
79 #endif /* _MSC_VER >= 1310 */
81 #if !defined(AO_PREFER_GENERALIZED) || !defined(AO_ASSUME_WINDOWS98)
83 AO_fetch_and_add_full(volatile AO_t *p, AO_t incr)
85 return _InterlockedExchangeAdd((long AO_INTERLOCKED_VOLATILE *)p, incr);
87 #define AO_HAVE_fetch_and_add_full
90 AO_fetch_and_add1_full(volatile AO_t *p)
92 return _InterlockedIncrement((long AO_INTERLOCKED_VOLATILE *)p) - 1;
94 #define AO_HAVE_fetch_and_add1_full
97 AO_fetch_and_sub1_full(volatile AO_t *p)
99 return _InterlockedDecrement((long AO_INTERLOCKED_VOLATILE *)p) + 1;
101 #define AO_HAVE_fetch_and_sub1_full
102 #endif /* !AO_PREFER_GENERALIZED */
104 #ifdef AO_ASSUME_WINDOWS98
106 AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val,
109 # ifdef AO_OLD_STYLE_INTERLOCKED_COMPARE_EXCHANGE
110 return (AO_t)_InterlockedCompareExchange(
111 (void *AO_INTERLOCKED_VOLATILE *)addr,
112 (void *)new_val, (void *)old_val);
114 return _InterlockedCompareExchange((long AO_INTERLOCKED_VOLATILE *)addr,
118 # define AO_HAVE_fetch_compare_and_swap_full
119 #endif /* AO_ASSUME_WINDOWS98 */
121 #if (_MSC_VER > 1400) && (!defined(_M_ARM) || _MSC_VER >= 1800)
123 # pragma intrinsic (_InterlockedAnd8)
124 # pragma intrinsic (_InterlockedCompareExchange16)
125 # pragma intrinsic (_InterlockedOr8)
126 # pragma intrinsic (_InterlockedXor8)
129 AO_char_and_full(volatile unsigned char *p, unsigned char value)
131 _InterlockedAnd8((char volatile *)p, value);
133 # define AO_HAVE_char_and_full
136 AO_char_or_full(volatile unsigned char *p, unsigned char value)
138 _InterlockedOr8((char volatile *)p, value);
140 # define AO_HAVE_char_or_full
143 AO_char_xor_full(volatile unsigned char *p, unsigned char value)
145 _InterlockedXor8((char volatile *)p, value);
147 # define AO_HAVE_char_xor_full
149 AO_INLINE unsigned short
150 AO_short_fetch_compare_and_swap_full(volatile unsigned short *addr,
151 unsigned short old_val,
152 unsigned short new_val)
154 return _InterlockedCompareExchange16((short volatile *)addr,
157 # define AO_HAVE_short_fetch_compare_and_swap_full
159 # ifndef AO_PREFER_GENERALIZED
160 # pragma intrinsic (_InterlockedIncrement16)
161 # pragma intrinsic (_InterlockedDecrement16)
163 AO_INLINE unsigned short
164 AO_short_fetch_and_add1_full(volatile unsigned short *p)
166 return _InterlockedIncrement16((short volatile *)p) - 1;
168 # define AO_HAVE_short_fetch_and_add1_full
170 AO_INLINE unsigned short
171 AO_short_fetch_and_sub1_full(volatile unsigned short *p)
173 return _InterlockedDecrement16((short volatile *)p) + 1;
175 # define AO_HAVE_short_fetch_and_sub1_full
176 # endif /* !AO_PREFER_GENERALIZED */
177 #endif /* _MSC_VER > 1400 */
179 #if _MSC_VER >= 1800 /* Visual Studio 2013+ */
181 # pragma intrinsic (_InterlockedCompareExchange8)
183 AO_INLINE unsigned char
184 AO_char_fetch_compare_and_swap_full(volatile unsigned char *addr,
185 unsigned char old_val,
186 unsigned char new_val)
188 return _InterlockedCompareExchange8((char volatile *)addr,
191 # define AO_HAVE_char_fetch_compare_and_swap_full
193 # if !defined(AO_PREFER_GENERALIZED) && !defined(_M_ARM)
194 # pragma intrinsic (_InterlockedExchangeAdd16)
195 # pragma intrinsic (_InterlockedExchangeAdd8)
197 AO_INLINE unsigned char
198 AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr)
200 return _InterlockedExchangeAdd8((char volatile *)p, incr);
202 # define AO_HAVE_char_fetch_and_add_full
204 AO_INLINE unsigned short
205 AO_short_fetch_and_add_full(volatile unsigned short *p,
208 return _InterlockedExchangeAdd16((short volatile *)p, incr);
210 # define AO_HAVE_short_fetch_and_add_full
211 # endif /* !AO_PREFER_GENERALIZED && !_M_ARM */
212 #endif /* _MSC_VER >= 1800 */