1 // This is the implementation of Python atomic operations for MSVC if the
2 // compiler does not support C11 or C++11 atomics.
3 //
4 // MSVC intrinsics are defined on char, short, long, __int64, and pointer
5 // types. Note that long and int are both 32-bits even on 64-bit Windows,
6 // so operations on int are cast to long.
7 //
8 // The volatile keyword has additional memory ordering semantics on MSVC. On
9 // x86 and x86-64, volatile accesses have acquire-release semantics. On ARM64,
10 // volatile accesses behave like C11's memory_order_relaxed.
11
12 #ifndef Py_ATOMIC_MSC_H
13 # error "this header file must not be included directly"
14 #endif
15
16 #include <intrin.h>
17
18 #define _Py_atomic_ASSERT_ARG_TYPE(TYPE) \
19 Py_BUILD_ASSERT(sizeof(*obj) == sizeof(TYPE))
20
21
22 // --- _Py_atomic_add --------------------------------------------------------
23
24 static inline int8_t
_Py_atomic_add_int8(int8_t * obj,int8_t value)25 _Py_atomic_add_int8(int8_t *obj, int8_t value)
26 {
27 _Py_atomic_ASSERT_ARG_TYPE(char);
28 return (int8_t)_InterlockedExchangeAdd8((volatile char *)obj, (char)value);
29 }
30
31 static inline int16_t
_Py_atomic_add_int16(int16_t * obj,int16_t value)32 _Py_atomic_add_int16(int16_t *obj, int16_t value)
33 {
34 _Py_atomic_ASSERT_ARG_TYPE(short);
35 return (int16_t)_InterlockedExchangeAdd16((volatile short *)obj, (short)value);
36 }
37
38 static inline int32_t
_Py_atomic_add_int32(int32_t * obj,int32_t value)39 _Py_atomic_add_int32(int32_t *obj, int32_t value)
40 {
41 _Py_atomic_ASSERT_ARG_TYPE(long);
42 return (int32_t)_InterlockedExchangeAdd((volatile long *)obj, (long)value);
43 }
44
45 static inline int64_t
_Py_atomic_add_int64(int64_t * obj,int64_t value)46 _Py_atomic_add_int64(int64_t *obj, int64_t value)
47 {
48 #if defined(_M_X64) || defined(_M_ARM64)
49 _Py_atomic_ASSERT_ARG_TYPE(__int64);
50 return (int64_t)_InterlockedExchangeAdd64((volatile __int64 *)obj, (__int64)value);
51 #else
52 int64_t old_value = _Py_atomic_load_int64_relaxed(obj);
53 for (;;) {
54 int64_t new_value = old_value + value;
55 if (_Py_atomic_compare_exchange_int64(obj, &old_value, new_value)) {
56 return old_value;
57 }
58 }
59 #endif
60 }
61
62
63 static inline uint8_t
_Py_atomic_add_uint8(uint8_t * obj,uint8_t value)64 _Py_atomic_add_uint8(uint8_t *obj, uint8_t value)
65 {
66 return (uint8_t)_Py_atomic_add_int8((int8_t *)obj, (int8_t)value);
67 }
68
69 static inline uint16_t
_Py_atomic_add_uint16(uint16_t * obj,uint16_t value)70 _Py_atomic_add_uint16(uint16_t *obj, uint16_t value)
71 {
72 return (uint16_t)_Py_atomic_add_int16((int16_t *)obj, (int16_t)value);
73 }
74
75 static inline uint32_t
_Py_atomic_add_uint32(uint32_t * obj,uint32_t value)76 _Py_atomic_add_uint32(uint32_t *obj, uint32_t value)
77 {
78 return (uint32_t)_Py_atomic_add_int32((int32_t *)obj, (int32_t)value);
79 }
80
81 static inline int
_Py_atomic_add_int(int * obj,int value)82 _Py_atomic_add_int(int *obj, int value)
83 {
84 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
85 return (int)_Py_atomic_add_int32((int32_t *)obj, (int32_t)value);
86 }
87
88 static inline unsigned int
_Py_atomic_add_uint(unsigned int * obj,unsigned int value)89 _Py_atomic_add_uint(unsigned int *obj, unsigned int value)
90 {
91 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
92 return (unsigned int)_Py_atomic_add_int32((int32_t *)obj, (int32_t)value);
93 }
94
95 static inline uint64_t
_Py_atomic_add_uint64(uint64_t * obj,uint64_t value)96 _Py_atomic_add_uint64(uint64_t *obj, uint64_t value)
97 {
98 return (uint64_t)_Py_atomic_add_int64((int64_t *)obj, (int64_t)value);
99 }
100
101 static inline intptr_t
_Py_atomic_add_intptr(intptr_t * obj,intptr_t value)102 _Py_atomic_add_intptr(intptr_t *obj, intptr_t value)
103 {
104 #if SIZEOF_VOID_P == 8
105 _Py_atomic_ASSERT_ARG_TYPE(int64_t);
106 return (intptr_t)_Py_atomic_add_int64((int64_t *)obj, (int64_t)value);
107 #else
108 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
109 return (intptr_t)_Py_atomic_add_int32((int32_t *)obj, (int32_t)value);
110 #endif
111 }
112
113 static inline uintptr_t
_Py_atomic_add_uintptr(uintptr_t * obj,uintptr_t value)114 _Py_atomic_add_uintptr(uintptr_t *obj, uintptr_t value)
115 {
116 _Py_atomic_ASSERT_ARG_TYPE(intptr_t);
117 return (uintptr_t)_Py_atomic_add_intptr((intptr_t *)obj, (intptr_t)value);
118 }
119
120 static inline Py_ssize_t
_Py_atomic_add_ssize(Py_ssize_t * obj,Py_ssize_t value)121 _Py_atomic_add_ssize(Py_ssize_t *obj, Py_ssize_t value)
122 {
123 _Py_atomic_ASSERT_ARG_TYPE(intptr_t);
124 return (Py_ssize_t)_Py_atomic_add_intptr((intptr_t *)obj, (intptr_t)value);
125 }
126
127
128 // --- _Py_atomic_compare_exchange -------------------------------------------
129
130 static inline int
_Py_atomic_compare_exchange_int8(int8_t * obj,int8_t * expected,int8_t value)131 _Py_atomic_compare_exchange_int8(int8_t *obj, int8_t *expected, int8_t value)
132 {
133 _Py_atomic_ASSERT_ARG_TYPE(char);
134 int8_t initial = (int8_t)_InterlockedCompareExchange8(
135 (volatile char *)obj,
136 (char)value,
137 (char)*expected);
138 if (initial == *expected) {
139 return 1;
140 }
141 *expected = initial;
142 return 0;
143 }
144
145 static inline int
_Py_atomic_compare_exchange_int16(int16_t * obj,int16_t * expected,int16_t value)146 _Py_atomic_compare_exchange_int16(int16_t *obj, int16_t *expected, int16_t value)
147 {
148 _Py_atomic_ASSERT_ARG_TYPE(short);
149 int16_t initial = (int16_t)_InterlockedCompareExchange16(
150 (volatile short *)obj,
151 (short)value,
152 (short)*expected);
153 if (initial == *expected) {
154 return 1;
155 }
156 *expected = initial;
157 return 0;
158 }
159
160 static inline int
_Py_atomic_compare_exchange_int32(int32_t * obj,int32_t * expected,int32_t value)161 _Py_atomic_compare_exchange_int32(int32_t *obj, int32_t *expected, int32_t value)
162 {
163 _Py_atomic_ASSERT_ARG_TYPE(long);
164 int32_t initial = (int32_t)_InterlockedCompareExchange(
165 (volatile long *)obj,
166 (long)value,
167 (long)*expected);
168 if (initial == *expected) {
169 return 1;
170 }
171 *expected = initial;
172 return 0;
173 }
174
175 static inline int
_Py_atomic_compare_exchange_int64(int64_t * obj,int64_t * expected,int64_t value)176 _Py_atomic_compare_exchange_int64(int64_t *obj, int64_t *expected, int64_t value)
177 {
178 _Py_atomic_ASSERT_ARG_TYPE(__int64);
179 int64_t initial = (int64_t)_InterlockedCompareExchange64(
180 (volatile __int64 *)obj,
181 (__int64)value,
182 (__int64)*expected);
183 if (initial == *expected) {
184 return 1;
185 }
186 *expected = initial;
187 return 0;
188 }
189
190 static inline int
_Py_atomic_compare_exchange_ptr(void * obj,void * expected,void * value)191 _Py_atomic_compare_exchange_ptr(void *obj, void *expected, void *value)
192 {
193 void *initial = _InterlockedCompareExchangePointer(
194 (void**)obj,
195 value,
196 *(void**)expected);
197 if (initial == *(void**)expected) {
198 return 1;
199 }
200 *(void**)expected = initial;
201 return 0;
202 }
203
204
205 static inline int
_Py_atomic_compare_exchange_uint8(uint8_t * obj,uint8_t * expected,uint8_t value)206 _Py_atomic_compare_exchange_uint8(uint8_t *obj, uint8_t *expected, uint8_t value)
207 {
208 return _Py_atomic_compare_exchange_int8((int8_t *)obj,
209 (int8_t *)expected,
210 (int8_t)value);
211 }
212
213 static inline int
_Py_atomic_compare_exchange_uint16(uint16_t * obj,uint16_t * expected,uint16_t value)214 _Py_atomic_compare_exchange_uint16(uint16_t *obj, uint16_t *expected, uint16_t value)
215 {
216 return _Py_atomic_compare_exchange_int16((int16_t *)obj,
217 (int16_t *)expected,
218 (int16_t)value);
219 }
220
221 static inline int
_Py_atomic_compare_exchange_uint32(uint32_t * obj,uint32_t * expected,uint32_t value)222 _Py_atomic_compare_exchange_uint32(uint32_t *obj, uint32_t *expected, uint32_t value)
223 {
224 return _Py_atomic_compare_exchange_int32((int32_t *)obj,
225 (int32_t *)expected,
226 (int32_t)value);
227 }
228
229 static inline int
_Py_atomic_compare_exchange_int(int * obj,int * expected,int value)230 _Py_atomic_compare_exchange_int(int *obj, int *expected, int value)
231 {
232 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
233 return _Py_atomic_compare_exchange_int32((int32_t *)obj,
234 (int32_t *)expected,
235 (int32_t)value);
236 }
237
238 static inline int
_Py_atomic_compare_exchange_uint(unsigned int * obj,unsigned int * expected,unsigned int value)239 _Py_atomic_compare_exchange_uint(unsigned int *obj, unsigned int *expected, unsigned int value)
240 {
241 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
242 return _Py_atomic_compare_exchange_int32((int32_t *)obj,
243 (int32_t *)expected,
244 (int32_t)value);
245 }
246
247 static inline int
_Py_atomic_compare_exchange_uint64(uint64_t * obj,uint64_t * expected,uint64_t value)248 _Py_atomic_compare_exchange_uint64(uint64_t *obj, uint64_t *expected, uint64_t value)
249 {
250 return _Py_atomic_compare_exchange_int64((int64_t *)obj,
251 (int64_t *)expected,
252 (int64_t)value);
253 }
254
255 static inline int
_Py_atomic_compare_exchange_intptr(intptr_t * obj,intptr_t * expected,intptr_t value)256 _Py_atomic_compare_exchange_intptr(intptr_t *obj, intptr_t *expected, intptr_t value)
257 {
258 _Py_atomic_ASSERT_ARG_TYPE(void*);
259 return _Py_atomic_compare_exchange_ptr((void**)obj,
260 (void**)expected,
261 (void*)value);
262 }
263
264 static inline int
_Py_atomic_compare_exchange_uintptr(uintptr_t * obj,uintptr_t * expected,uintptr_t value)265 _Py_atomic_compare_exchange_uintptr(uintptr_t *obj, uintptr_t *expected, uintptr_t value)
266 {
267 _Py_atomic_ASSERT_ARG_TYPE(void*);
268 return _Py_atomic_compare_exchange_ptr((void**)obj,
269 (void**)expected,
270 (void*)value);
271 }
272
273 static inline int
_Py_atomic_compare_exchange_ssize(Py_ssize_t * obj,Py_ssize_t * expected,Py_ssize_t value)274 _Py_atomic_compare_exchange_ssize(Py_ssize_t *obj, Py_ssize_t *expected, Py_ssize_t value)
275 {
276 _Py_atomic_ASSERT_ARG_TYPE(void*);
277 return _Py_atomic_compare_exchange_ptr((void**)obj,
278 (void**)expected,
279 (void*)value);
280 }
281
282
283 // --- _Py_atomic_exchange ---------------------------------------------------
284
285 static inline int8_t
_Py_atomic_exchange_int8(int8_t * obj,int8_t value)286 _Py_atomic_exchange_int8(int8_t *obj, int8_t value)
287 {
288 _Py_atomic_ASSERT_ARG_TYPE(char);
289 return (int8_t)_InterlockedExchange8((volatile char *)obj, (char)value);
290 }
291
292 static inline int16_t
_Py_atomic_exchange_int16(int16_t * obj,int16_t value)293 _Py_atomic_exchange_int16(int16_t *obj, int16_t value)
294 {
295 _Py_atomic_ASSERT_ARG_TYPE(short);
296 return (int16_t)_InterlockedExchange16((volatile short *)obj, (short)value);
297 }
298
299 static inline int32_t
_Py_atomic_exchange_int32(int32_t * obj,int32_t value)300 _Py_atomic_exchange_int32(int32_t *obj, int32_t value)
301 {
302 _Py_atomic_ASSERT_ARG_TYPE(long);
303 return (int32_t)_InterlockedExchange((volatile long *)obj, (long)value);
304 }
305
306 static inline int64_t
_Py_atomic_exchange_int64(int64_t * obj,int64_t value)307 _Py_atomic_exchange_int64(int64_t *obj, int64_t value)
308 {
309 #if defined(_M_X64) || defined(_M_ARM64)
310 _Py_atomic_ASSERT_ARG_TYPE(__int64);
311 return (int64_t)_InterlockedExchange64((volatile __int64 *)obj, (__int64)value);
312 #else
313 int64_t old_value = _Py_atomic_load_int64_relaxed(obj);
314 for (;;) {
315 if (_Py_atomic_compare_exchange_int64(obj, &old_value, value)) {
316 return old_value;
317 }
318 }
319 #endif
320 }
321
322 static inline void*
_Py_atomic_exchange_ptr(void * obj,void * value)323 _Py_atomic_exchange_ptr(void *obj, void *value)
324 {
325 return (void*)_InterlockedExchangePointer((void * volatile *)obj, (void *)value);
326 }
327
328
329 static inline uint8_t
_Py_atomic_exchange_uint8(uint8_t * obj,uint8_t value)330 _Py_atomic_exchange_uint8(uint8_t *obj, uint8_t value)
331 {
332 return (uint8_t)_Py_atomic_exchange_int8((int8_t *)obj,
333 (int8_t)value);
334 }
335
336 static inline uint16_t
_Py_atomic_exchange_uint16(uint16_t * obj,uint16_t value)337 _Py_atomic_exchange_uint16(uint16_t *obj, uint16_t value)
338 {
339 return (uint16_t)_Py_atomic_exchange_int16((int16_t *)obj,
340 (int16_t)value);
341 }
342
343 static inline uint32_t
_Py_atomic_exchange_uint32(uint32_t * obj,uint32_t value)344 _Py_atomic_exchange_uint32(uint32_t *obj, uint32_t value)
345 {
346 return (uint32_t)_Py_atomic_exchange_int32((int32_t *)obj,
347 (int32_t)value);
348 }
349
350 static inline int
_Py_atomic_exchange_int(int * obj,int value)351 _Py_atomic_exchange_int(int *obj, int value)
352 {
353 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
354 return (int)_Py_atomic_exchange_int32((int32_t *)obj,
355 (int32_t)value);
356 }
357
358 static inline unsigned int
_Py_atomic_exchange_uint(unsigned int * obj,unsigned int value)359 _Py_atomic_exchange_uint(unsigned int *obj, unsigned int value)
360 {
361 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
362 return (unsigned int)_Py_atomic_exchange_int32((int32_t *)obj,
363 (int32_t)value);
364 }
365
366 static inline uint64_t
_Py_atomic_exchange_uint64(uint64_t * obj,uint64_t value)367 _Py_atomic_exchange_uint64(uint64_t *obj, uint64_t value)
368 {
369 return (uint64_t)_Py_atomic_exchange_int64((int64_t *)obj,
370 (int64_t)value);
371 }
372
373 static inline intptr_t
_Py_atomic_exchange_intptr(intptr_t * obj,intptr_t value)374 _Py_atomic_exchange_intptr(intptr_t *obj, intptr_t value)
375 {
376 _Py_atomic_ASSERT_ARG_TYPE(void*);
377 return (intptr_t)_Py_atomic_exchange_ptr((void**)obj,
378 (void*)value);
379 }
380
381 static inline uintptr_t
_Py_atomic_exchange_uintptr(uintptr_t * obj,uintptr_t value)382 _Py_atomic_exchange_uintptr(uintptr_t *obj, uintptr_t value)
383 {
384 _Py_atomic_ASSERT_ARG_TYPE(void*);
385 return (uintptr_t)_Py_atomic_exchange_ptr((void**)obj,
386 (void*)value);
387 }
388
389 static inline Py_ssize_t
_Py_atomic_exchange_ssize(Py_ssize_t * obj,Py_ssize_t value)390 _Py_atomic_exchange_ssize(Py_ssize_t *obj, Py_ssize_t value)
391 {
392 _Py_atomic_ASSERT_ARG_TYPE(void*);
393 return (Py_ssize_t)_Py_atomic_exchange_ptr((void**)obj,
394 (void*)value);
395 }
396
397
398 // --- _Py_atomic_and --------------------------------------------------------
399
400 static inline uint8_t
_Py_atomic_and_uint8(uint8_t * obj,uint8_t value)401 _Py_atomic_and_uint8(uint8_t *obj, uint8_t value)
402 {
403 _Py_atomic_ASSERT_ARG_TYPE(char);
404 return (uint8_t)_InterlockedAnd8((volatile char *)obj, (char)value);
405 }
406
407 static inline uint16_t
_Py_atomic_and_uint16(uint16_t * obj,uint16_t value)408 _Py_atomic_and_uint16(uint16_t *obj, uint16_t value)
409 {
410 _Py_atomic_ASSERT_ARG_TYPE(short);
411 return (uint16_t)_InterlockedAnd16((volatile short *)obj, (short)value);
412 }
413
414 static inline uint32_t
_Py_atomic_and_uint32(uint32_t * obj,uint32_t value)415 _Py_atomic_and_uint32(uint32_t *obj, uint32_t value)
416 {
417 _Py_atomic_ASSERT_ARG_TYPE(long);
418 return (uint32_t)_InterlockedAnd((volatile long *)obj, (long)value);
419 }
420
421 static inline uint64_t
_Py_atomic_and_uint64(uint64_t * obj,uint64_t value)422 _Py_atomic_and_uint64(uint64_t *obj, uint64_t value)
423 {
424 #if defined(_M_X64) || defined(_M_ARM64)
425 _Py_atomic_ASSERT_ARG_TYPE(__int64);
426 return (uint64_t)_InterlockedAnd64((volatile __int64 *)obj, (__int64)value);
427 #else
428 uint64_t old_value = _Py_atomic_load_uint64_relaxed(obj);
429 for (;;) {
430 uint64_t new_value = old_value & value;
431 if (_Py_atomic_compare_exchange_uint64(obj, &old_value, new_value)) {
432 return old_value;
433 }
434 }
435 #endif
436 }
437
438 static inline uintptr_t
_Py_atomic_and_uintptr(uintptr_t * obj,uintptr_t value)439 _Py_atomic_and_uintptr(uintptr_t *obj, uintptr_t value)
440 {
441 #if SIZEOF_VOID_P == 8
442 _Py_atomic_ASSERT_ARG_TYPE(uint64_t);
443 return (uintptr_t)_Py_atomic_and_uint64((uint64_t *)obj,
444 (uint64_t)value);
445 #else
446 _Py_atomic_ASSERT_ARG_TYPE(uint32_t);
447 return (uintptr_t)_Py_atomic_and_uint32((uint32_t *)obj,
448 (uint32_t)value);
449 #endif
450 }
451
452
453 // --- _Py_atomic_or ---------------------------------------------------------
454
455 static inline uint8_t
_Py_atomic_or_uint8(uint8_t * obj,uint8_t value)456 _Py_atomic_or_uint8(uint8_t *obj, uint8_t value)
457 {
458 _Py_atomic_ASSERT_ARG_TYPE(char);
459 return (uint8_t)_InterlockedOr8((volatile char *)obj, (char)value);
460 }
461
462 static inline uint16_t
_Py_atomic_or_uint16(uint16_t * obj,uint16_t value)463 _Py_atomic_or_uint16(uint16_t *obj, uint16_t value)
464 {
465 _Py_atomic_ASSERT_ARG_TYPE(short);
466 return (uint16_t)_InterlockedOr16((volatile short *)obj, (short)value);
467 }
468
469 static inline uint32_t
_Py_atomic_or_uint32(uint32_t * obj,uint32_t value)470 _Py_atomic_or_uint32(uint32_t *obj, uint32_t value)
471 {
472 _Py_atomic_ASSERT_ARG_TYPE(long);
473 return (uint32_t)_InterlockedOr((volatile long *)obj, (long)value);
474 }
475
476 static inline uint64_t
_Py_atomic_or_uint64(uint64_t * obj,uint64_t value)477 _Py_atomic_or_uint64(uint64_t *obj, uint64_t value)
478 {
479 #if defined(_M_X64) || defined(_M_ARM64)
480 _Py_atomic_ASSERT_ARG_TYPE(__int64);
481 return (uint64_t)_InterlockedOr64((volatile __int64 *)obj, (__int64)value);
482 #else
483 uint64_t old_value = _Py_atomic_load_uint64_relaxed(obj);
484 for (;;) {
485 uint64_t new_value = old_value | value;
486 if (_Py_atomic_compare_exchange_uint64(obj, &old_value, new_value)) {
487 return old_value;
488 }
489 }
490 #endif
491 }
492
493
494 static inline uintptr_t
_Py_atomic_or_uintptr(uintptr_t * obj,uintptr_t value)495 _Py_atomic_or_uintptr(uintptr_t *obj, uintptr_t value)
496 {
497 #if SIZEOF_VOID_P == 8
498 _Py_atomic_ASSERT_ARG_TYPE(uint64_t);
499 return (uintptr_t)_Py_atomic_or_uint64((uint64_t *)obj,
500 (uint64_t)value);
501 #else
502 _Py_atomic_ASSERT_ARG_TYPE(uint32_t);
503 return (uintptr_t)_Py_atomic_or_uint32((uint32_t *)obj,
504 (uint32_t)value);
505 #endif
506 }
507
508
509 // --- _Py_atomic_load -------------------------------------------------------
510
511 static inline uint8_t
_Py_atomic_load_uint8(const uint8_t * obj)512 _Py_atomic_load_uint8(const uint8_t *obj)
513 {
514 #if defined(_M_X64) || defined(_M_IX86)
515 return *(volatile uint8_t *)obj;
516 #elif defined(_M_ARM64)
517 return (uint8_t)__ldar8((unsigned __int8 volatile *)obj);
518 #else
519 # error "no implementation of _Py_atomic_load_uint8"
520 #endif
521 }
522
523 static inline uint16_t
_Py_atomic_load_uint16(const uint16_t * obj)524 _Py_atomic_load_uint16(const uint16_t *obj)
525 {
526 #if defined(_M_X64) || defined(_M_IX86)
527 return *(volatile uint16_t *)obj;
528 #elif defined(_M_ARM64)
529 return (uint16_t)__ldar16((unsigned __int16 volatile *)obj);
530 #else
531 # error "no implementation of _Py_atomic_load_uint16"
532 #endif
533 }
534
535 static inline uint32_t
_Py_atomic_load_uint32(const uint32_t * obj)536 _Py_atomic_load_uint32(const uint32_t *obj)
537 {
538 #if defined(_M_X64) || defined(_M_IX86)
539 return *(volatile uint32_t *)obj;
540 #elif defined(_M_ARM64)
541 return (uint32_t)__ldar32((unsigned __int32 volatile *)obj);
542 #else
543 # error "no implementation of _Py_atomic_load_uint32"
544 #endif
545 }
546
547 static inline uint64_t
_Py_atomic_load_uint64(const uint64_t * obj)548 _Py_atomic_load_uint64(const uint64_t *obj)
549 {
550 #if defined(_M_X64) || defined(_M_IX86)
551 return *(volatile uint64_t *)obj;
552 #elif defined(_M_ARM64)
553 return (uint64_t)__ldar64((unsigned __int64 volatile *)obj);
554 #else
555 # error "no implementation of _Py_atomic_load_uint64"
556 #endif
557 }
558
559 static inline int8_t
_Py_atomic_load_int8(const int8_t * obj)560 _Py_atomic_load_int8(const int8_t *obj)
561 {
562 return (int8_t)_Py_atomic_load_uint8((const uint8_t *)obj);
563 }
564
565 static inline int16_t
_Py_atomic_load_int16(const int16_t * obj)566 _Py_atomic_load_int16(const int16_t *obj)
567 {
568 return (int16_t)_Py_atomic_load_uint16((const uint16_t *)obj);
569 }
570
571 static inline int32_t
_Py_atomic_load_int32(const int32_t * obj)572 _Py_atomic_load_int32(const int32_t *obj)
573 {
574 return (int32_t)_Py_atomic_load_uint32((const uint32_t *)obj);
575 }
576
577 static inline int
_Py_atomic_load_int(const int * obj)578 _Py_atomic_load_int(const int *obj)
579 {
580 _Py_atomic_ASSERT_ARG_TYPE(uint32_t);
581 return (int)_Py_atomic_load_uint32((uint32_t *)obj);
582 }
583
584 static inline unsigned int
_Py_atomic_load_uint(const unsigned int * obj)585 _Py_atomic_load_uint(const unsigned int *obj)
586 {
587 _Py_atomic_ASSERT_ARG_TYPE(uint32_t);
588 return (unsigned int)_Py_atomic_load_uint32((uint32_t *)obj);
589 }
590
591 static inline int64_t
_Py_atomic_load_int64(const int64_t * obj)592 _Py_atomic_load_int64(const int64_t *obj)
593 {
594 return (int64_t)_Py_atomic_load_uint64((const uint64_t *)obj);
595 }
596
597 static inline void*
_Py_atomic_load_ptr(const void * obj)598 _Py_atomic_load_ptr(const void *obj)
599 {
600 #if SIZEOF_VOID_P == 8
601 return (void*)_Py_atomic_load_uint64((const uint64_t *)obj);
602 #else
603 return (void*)_Py_atomic_load_uint32((const uint32_t *)obj);
604 #endif
605 }
606
607 static inline intptr_t
_Py_atomic_load_intptr(const intptr_t * obj)608 _Py_atomic_load_intptr(const intptr_t *obj)
609 {
610 _Py_atomic_ASSERT_ARG_TYPE(void*);
611 return (intptr_t)_Py_atomic_load_ptr((void*)obj);
612 }
613
614 static inline uintptr_t
_Py_atomic_load_uintptr(const uintptr_t * obj)615 _Py_atomic_load_uintptr(const uintptr_t *obj)
616 {
617 _Py_atomic_ASSERT_ARG_TYPE(void*);
618 return (uintptr_t)_Py_atomic_load_ptr((void*)obj);
619 }
620
621 static inline Py_ssize_t
_Py_atomic_load_ssize(const Py_ssize_t * obj)622 _Py_atomic_load_ssize(const Py_ssize_t *obj)
623 {
624 _Py_atomic_ASSERT_ARG_TYPE(void*);
625 return (Py_ssize_t)_Py_atomic_load_ptr((void*)obj);
626 }
627
628
629 // --- _Py_atomic_load_relaxed -----------------------------------------------
630
631 static inline int
_Py_atomic_load_int_relaxed(const int * obj)632 _Py_atomic_load_int_relaxed(const int *obj)
633 {
634 return *(volatile int *)obj;
635 }
636
637 static inline int8_t
_Py_atomic_load_int8_relaxed(const int8_t * obj)638 _Py_atomic_load_int8_relaxed(const int8_t *obj)
639 {
640 return *(volatile int8_t *)obj;
641 }
642
643 static inline int16_t
_Py_atomic_load_int16_relaxed(const int16_t * obj)644 _Py_atomic_load_int16_relaxed(const int16_t *obj)
645 {
646 return *(volatile int16_t *)obj;
647 }
648
649 static inline int32_t
_Py_atomic_load_int32_relaxed(const int32_t * obj)650 _Py_atomic_load_int32_relaxed(const int32_t *obj)
651 {
652 return *(volatile int32_t *)obj;
653 }
654
655 static inline int64_t
_Py_atomic_load_int64_relaxed(const int64_t * obj)656 _Py_atomic_load_int64_relaxed(const int64_t *obj)
657 {
658 return *(volatile int64_t *)obj;
659 }
660
661 static inline intptr_t
_Py_atomic_load_intptr_relaxed(const intptr_t * obj)662 _Py_atomic_load_intptr_relaxed(const intptr_t *obj)
663 {
664 return *(volatile intptr_t *)obj;
665 }
666
667 static inline uint8_t
_Py_atomic_load_uint8_relaxed(const uint8_t * obj)668 _Py_atomic_load_uint8_relaxed(const uint8_t *obj)
669 {
670 return *(volatile uint8_t *)obj;
671 }
672
673 static inline uint16_t
_Py_atomic_load_uint16_relaxed(const uint16_t * obj)674 _Py_atomic_load_uint16_relaxed(const uint16_t *obj)
675 {
676 return *(volatile uint16_t *)obj;
677 }
678
679 static inline uint32_t
_Py_atomic_load_uint32_relaxed(const uint32_t * obj)680 _Py_atomic_load_uint32_relaxed(const uint32_t *obj)
681 {
682 return *(volatile uint32_t *)obj;
683 }
684
685 static inline uint64_t
_Py_atomic_load_uint64_relaxed(const uint64_t * obj)686 _Py_atomic_load_uint64_relaxed(const uint64_t *obj)
687 {
688 return *(volatile uint64_t *)obj;
689 }
690
691 static inline uintptr_t
_Py_atomic_load_uintptr_relaxed(const uintptr_t * obj)692 _Py_atomic_load_uintptr_relaxed(const uintptr_t *obj)
693 {
694 return *(volatile uintptr_t *)obj;
695 }
696
697 static inline unsigned int
_Py_atomic_load_uint_relaxed(const unsigned int * obj)698 _Py_atomic_load_uint_relaxed(const unsigned int *obj)
699 {
700 return *(volatile unsigned int *)obj;
701 }
702
703 static inline Py_ssize_t
_Py_atomic_load_ssize_relaxed(const Py_ssize_t * obj)704 _Py_atomic_load_ssize_relaxed(const Py_ssize_t *obj)
705 {
706 return *(volatile Py_ssize_t *)obj;
707 }
708
709 static inline void*
_Py_atomic_load_ptr_relaxed(const void * obj)710 _Py_atomic_load_ptr_relaxed(const void *obj)
711 {
712 return *(void * volatile *)obj;
713 }
714
715 static inline unsigned long long
_Py_atomic_load_ullong_relaxed(const unsigned long long * obj)716 _Py_atomic_load_ullong_relaxed(const unsigned long long *obj)
717 {
718 return *(volatile unsigned long long *)obj;
719 }
720
721
722 // --- _Py_atomic_store ------------------------------------------------------
723
724 static inline void
_Py_atomic_store_int(int * obj,int value)725 _Py_atomic_store_int(int *obj, int value)
726 {
727 (void)_Py_atomic_exchange_int(obj, value);
728 }
729
730 static inline void
_Py_atomic_store_int8(int8_t * obj,int8_t value)731 _Py_atomic_store_int8(int8_t *obj, int8_t value)
732 {
733 (void)_Py_atomic_exchange_int8(obj, value);
734 }
735
736 static inline void
_Py_atomic_store_int16(int16_t * obj,int16_t value)737 _Py_atomic_store_int16(int16_t *obj, int16_t value)
738 {
739 (void)_Py_atomic_exchange_int16(obj, value);
740 }
741
742 static inline void
_Py_atomic_store_int32(int32_t * obj,int32_t value)743 _Py_atomic_store_int32(int32_t *obj, int32_t value)
744 {
745 (void)_Py_atomic_exchange_int32(obj, value);
746 }
747
748 static inline void
_Py_atomic_store_int64(int64_t * obj,int64_t value)749 _Py_atomic_store_int64(int64_t *obj, int64_t value)
750 {
751 (void)_Py_atomic_exchange_int64(obj, value);
752 }
753
754 static inline void
_Py_atomic_store_intptr(intptr_t * obj,intptr_t value)755 _Py_atomic_store_intptr(intptr_t *obj, intptr_t value)
756 {
757 (void)_Py_atomic_exchange_intptr(obj, value);
758 }
759
760 static inline void
_Py_atomic_store_uint8(uint8_t * obj,uint8_t value)761 _Py_atomic_store_uint8(uint8_t *obj, uint8_t value)
762 {
763 (void)_Py_atomic_exchange_uint8(obj, value);
764 }
765
766 static inline void
_Py_atomic_store_uint16(uint16_t * obj,uint16_t value)767 _Py_atomic_store_uint16(uint16_t *obj, uint16_t value)
768 {
769 (void)_Py_atomic_exchange_uint16(obj, value);
770 }
771
772 static inline void
_Py_atomic_store_uint32(uint32_t * obj,uint32_t value)773 _Py_atomic_store_uint32(uint32_t *obj, uint32_t value)
774 {
775 (void)_Py_atomic_exchange_uint32(obj, value);
776 }
777
778 static inline void
_Py_atomic_store_uint64(uint64_t * obj,uint64_t value)779 _Py_atomic_store_uint64(uint64_t *obj, uint64_t value)
780 {
781 (void)_Py_atomic_exchange_uint64(obj, value);
782 }
783
784 static inline void
_Py_atomic_store_uintptr(uintptr_t * obj,uintptr_t value)785 _Py_atomic_store_uintptr(uintptr_t *obj, uintptr_t value)
786 {
787 (void)_Py_atomic_exchange_uintptr(obj, value);
788 }
789
790 static inline void
_Py_atomic_store_uint(unsigned int * obj,unsigned int value)791 _Py_atomic_store_uint(unsigned int *obj, unsigned int value)
792 {
793 (void)_Py_atomic_exchange_uint(obj, value);
794 }
795
796 static inline void
_Py_atomic_store_ptr(void * obj,void * value)797 _Py_atomic_store_ptr(void *obj, void *value)
798 {
799 (void)_Py_atomic_exchange_ptr(obj, value);
800 }
801
802 static inline void
_Py_atomic_store_ssize(Py_ssize_t * obj,Py_ssize_t value)803 _Py_atomic_store_ssize(Py_ssize_t *obj, Py_ssize_t value)
804 {
805 (void)_Py_atomic_exchange_ssize(obj, value);
806 }
807
808
809 // --- _Py_atomic_store_relaxed ----------------------------------------------
810
811 static inline void
_Py_atomic_store_int_relaxed(int * obj,int value)812 _Py_atomic_store_int_relaxed(int *obj, int value)
813 {
814 *(volatile int *)obj = value;
815 }
816
817 static inline void
_Py_atomic_store_int8_relaxed(int8_t * obj,int8_t value)818 _Py_atomic_store_int8_relaxed(int8_t *obj, int8_t value)
819 {
820 *(volatile int8_t *)obj = value;
821 }
822
823 static inline void
_Py_atomic_store_int16_relaxed(int16_t * obj,int16_t value)824 _Py_atomic_store_int16_relaxed(int16_t *obj, int16_t value)
825 {
826 *(volatile int16_t *)obj = value;
827 }
828
829 static inline void
_Py_atomic_store_int32_relaxed(int32_t * obj,int32_t value)830 _Py_atomic_store_int32_relaxed(int32_t *obj, int32_t value)
831 {
832 *(volatile int32_t *)obj = value;
833 }
834
835 static inline void
_Py_atomic_store_int64_relaxed(int64_t * obj,int64_t value)836 _Py_atomic_store_int64_relaxed(int64_t *obj, int64_t value)
837 {
838 *(volatile int64_t *)obj = value;
839 }
840
841 static inline void
_Py_atomic_store_intptr_relaxed(intptr_t * obj,intptr_t value)842 _Py_atomic_store_intptr_relaxed(intptr_t *obj, intptr_t value)
843 {
844 *(volatile intptr_t *)obj = value;
845 }
846
847 static inline void
_Py_atomic_store_uint8_relaxed(uint8_t * obj,uint8_t value)848 _Py_atomic_store_uint8_relaxed(uint8_t *obj, uint8_t value)
849 {
850 *(volatile uint8_t *)obj = value;
851 }
852
853 static inline void
_Py_atomic_store_uint16_relaxed(uint16_t * obj,uint16_t value)854 _Py_atomic_store_uint16_relaxed(uint16_t *obj, uint16_t value)
855 {
856 *(volatile uint16_t *)obj = value;
857 }
858
859 static inline void
_Py_atomic_store_uint32_relaxed(uint32_t * obj,uint32_t value)860 _Py_atomic_store_uint32_relaxed(uint32_t *obj, uint32_t value)
861 {
862 *(volatile uint32_t *)obj = value;
863 }
864
865 static inline void
_Py_atomic_store_uint64_relaxed(uint64_t * obj,uint64_t value)866 _Py_atomic_store_uint64_relaxed(uint64_t *obj, uint64_t value)
867 {
868 *(volatile uint64_t *)obj = value;
869 }
870
871 static inline void
_Py_atomic_store_uintptr_relaxed(uintptr_t * obj,uintptr_t value)872 _Py_atomic_store_uintptr_relaxed(uintptr_t *obj, uintptr_t value)
873 {
874 *(volatile uintptr_t *)obj = value;
875 }
876
877 static inline void
_Py_atomic_store_uint_relaxed(unsigned int * obj,unsigned int value)878 _Py_atomic_store_uint_relaxed(unsigned int *obj, unsigned int value)
879 {
880 *(volatile unsigned int *)obj = value;
881 }
882
883 static inline void
_Py_atomic_store_ptr_relaxed(void * obj,void * value)884 _Py_atomic_store_ptr_relaxed(void *obj, void* value)
885 {
886 *(void * volatile *)obj = value;
887 }
888
889 static inline void
_Py_atomic_store_ssize_relaxed(Py_ssize_t * obj,Py_ssize_t value)890 _Py_atomic_store_ssize_relaxed(Py_ssize_t *obj, Py_ssize_t value)
891 {
892 *(volatile Py_ssize_t *)obj = value;
893 }
894
895 static inline void
_Py_atomic_store_ullong_relaxed(unsigned long long * obj,unsigned long long value)896 _Py_atomic_store_ullong_relaxed(unsigned long long *obj,
897 unsigned long long value)
898 {
899 *(volatile unsigned long long *)obj = value;
900 }
901
902
903 // --- _Py_atomic_load_ptr_acquire / _Py_atomic_store_ptr_release ------------
904
905 static inline void *
_Py_atomic_load_ptr_acquire(const void * obj)906 _Py_atomic_load_ptr_acquire(const void *obj)
907 {
908 #if defined(_M_X64) || defined(_M_IX86)
909 return *(void * volatile *)obj;
910 #elif defined(_M_ARM64)
911 return (void *)__ldar64((unsigned __int64 volatile *)obj);
912 #else
913 # error "no implementation of _Py_atomic_load_ptr_acquire"
914 #endif
915 }
916
917 static inline uintptr_t
_Py_atomic_load_uintptr_acquire(const uintptr_t * obj)918 _Py_atomic_load_uintptr_acquire(const uintptr_t *obj)
919 {
920 #if defined(_M_X64) || defined(_M_IX86)
921 return *(uintptr_t volatile *)obj;
922 #elif defined(_M_ARM64)
923 return (uintptr_t)__ldar64((unsigned __int64 volatile *)obj);
924 #else
925 # error "no implementation of _Py_atomic_load_uintptr_acquire"
926 #endif
927 }
928
929 static inline void
_Py_atomic_store_ptr_release(void * obj,void * value)930 _Py_atomic_store_ptr_release(void *obj, void *value)
931 {
932 #if defined(_M_X64) || defined(_M_IX86)
933 *(void * volatile *)obj = value;
934 #elif defined(_M_ARM64)
935 __stlr64((unsigned __int64 volatile *)obj, (uintptr_t)value);
936 #else
937 # error "no implementation of _Py_atomic_store_ptr_release"
938 #endif
939 }
940
941 static inline void
_Py_atomic_store_uintptr_release(uintptr_t * obj,uintptr_t value)942 _Py_atomic_store_uintptr_release(uintptr_t *obj, uintptr_t value)
943 {
944 #if defined(_M_X64) || defined(_M_IX86)
945 *(uintptr_t volatile *)obj = value;
946 #elif defined(_M_ARM64)
947 _Py_atomic_ASSERT_ARG_TYPE(unsigned __int64);
948 __stlr64((unsigned __int64 volatile *)obj, (unsigned __int64)value);
949 #else
950 # error "no implementation of _Py_atomic_store_uintptr_release"
951 #endif
952 }
953
954 static inline void
_Py_atomic_store_int_release(int * obj,int value)955 _Py_atomic_store_int_release(int *obj, int value)
956 {
957 #if defined(_M_X64) || defined(_M_IX86)
958 *(int volatile *)obj = value;
959 #elif defined(_M_ARM64)
960 _Py_atomic_ASSERT_ARG_TYPE(unsigned __int32);
961 __stlr32((unsigned __int32 volatile *)obj, (unsigned __int32)value);
962 #else
963 # error "no implementation of _Py_atomic_store_int_release"
964 #endif
965 }
966
967 static inline void
_Py_atomic_store_ssize_release(Py_ssize_t * obj,Py_ssize_t value)968 _Py_atomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value)
969 {
970 #if defined(_M_X64) || defined(_M_IX86)
971 *(Py_ssize_t volatile *)obj = value;
972 #elif defined(_M_ARM64)
973 __stlr64((unsigned __int64 volatile *)obj, (unsigned __int64)value);
974 #else
975 # error "no implementation of _Py_atomic_store_ssize_release"
976 #endif
977 }
978
979 static inline int
_Py_atomic_load_int_acquire(const int * obj)980 _Py_atomic_load_int_acquire(const int *obj)
981 {
982 #if defined(_M_X64) || defined(_M_IX86)
983 return *(int volatile *)obj;
984 #elif defined(_M_ARM64)
985 _Py_atomic_ASSERT_ARG_TYPE(unsigned __int32);
986 return (int)__ldar32((unsigned __int32 volatile *)obj);
987 #else
988 # error "no implementation of _Py_atomic_load_int_acquire"
989 #endif
990 }
991
992 static inline void
_Py_atomic_store_uint32_release(uint32_t * obj,uint32_t value)993 _Py_atomic_store_uint32_release(uint32_t *obj, uint32_t value)
994 {
995 #if defined(_M_X64) || defined(_M_IX86)
996 *(uint32_t volatile *)obj = value;
997 #elif defined(_M_ARM64)
998 _Py_atomic_ASSERT_ARG_TYPE(unsigned __int32);
999 __stlr32((unsigned __int32 volatile *)obj, (unsigned __int32)value);
1000 #else
1001 # error "no implementation of _Py_atomic_store_uint32_release"
1002 #endif
1003 }
1004
1005 static inline void
_Py_atomic_store_uint64_release(uint64_t * obj,uint64_t value)1006 _Py_atomic_store_uint64_release(uint64_t *obj, uint64_t value)
1007 {
1008 #if defined(_M_X64) || defined(_M_IX86)
1009 *(uint64_t volatile *)obj = value;
1010 #elif defined(_M_ARM64)
1011 _Py_atomic_ASSERT_ARG_TYPE(unsigned __int64);
1012 __stlr64((unsigned __int64 volatile *)obj, (unsigned __int64)value);
1013 #else
1014 # error "no implementation of _Py_atomic_store_uint64_release"
1015 #endif
1016 }
1017
1018 static inline uint64_t
_Py_atomic_load_uint64_acquire(const uint64_t * obj)1019 _Py_atomic_load_uint64_acquire(const uint64_t *obj)
1020 {
1021 #if defined(_M_X64) || defined(_M_IX86)
1022 return *(uint64_t volatile *)obj;
1023 #elif defined(_M_ARM64)
1024 _Py_atomic_ASSERT_ARG_TYPE(__int64);
1025 return (uint64_t)__ldar64((unsigned __int64 volatile *)obj);
1026 #else
1027 # error "no implementation of _Py_atomic_load_uint64_acquire"
1028 #endif
1029 }
1030
1031 static inline uint32_t
_Py_atomic_load_uint32_acquire(const uint32_t * obj)1032 _Py_atomic_load_uint32_acquire(const uint32_t *obj)
1033 {
1034 #if defined(_M_X64) || defined(_M_IX86)
1035 return *(uint32_t volatile *)obj;
1036 #elif defined(_M_ARM64)
1037 return (uint32_t)__ldar32((uint32_t volatile *)obj);
1038 #else
1039 # error "no implementation of _Py_atomic_load_uint32_acquire"
1040 #endif
1041 }
1042
1043 static inline Py_ssize_t
_Py_atomic_load_ssize_acquire(const Py_ssize_t * obj)1044 _Py_atomic_load_ssize_acquire(const Py_ssize_t *obj)
1045 {
1046 #if defined(_M_X64) || defined(_M_IX86)
1047 return *(Py_ssize_t volatile *)obj;
1048 #elif defined(_M_ARM64)
1049 return (Py_ssize_t)__ldar64((unsigned __int64 volatile *)obj);
1050 #else
1051 # error "no implementation of _Py_atomic_load_ssize_acquire"
1052 #endif
1053 }
1054
1055 // --- _Py_atomic_fence ------------------------------------------------------
1056
1057 static inline void
_Py_atomic_fence_seq_cst(void)1058 _Py_atomic_fence_seq_cst(void)
1059 {
1060 #if defined(_M_ARM64)
1061 __dmb(_ARM64_BARRIER_ISH);
1062 #elif defined(_M_X64)
1063 __faststorefence();
1064 #elif defined(_M_IX86)
1065 _mm_mfence();
1066 #else
1067 # error "no implementation of _Py_atomic_fence_seq_cst"
1068 #endif
1069 }
1070
1071 static inline void
_Py_atomic_fence_acquire(void)1072 _Py_atomic_fence_acquire(void)
1073 {
1074 #if defined(_M_ARM64)
1075 __dmb(_ARM64_BARRIER_ISHLD);
1076 #elif defined(_M_X64) || defined(_M_IX86)
1077 _ReadBarrier();
1078 #else
1079 # error "no implementation of _Py_atomic_fence_acquire"
1080 #endif
1081 }
1082
1083 static inline void
_Py_atomic_fence_release(void)1084 _Py_atomic_fence_release(void)
1085 {
1086 #if defined(_M_ARM64)
1087 __dmb(_ARM64_BARRIER_ISH);
1088 #elif defined(_M_X64) || defined(_M_IX86)
1089 _ReadWriteBarrier();
1090 #else
1091 # error "no implementation of _Py_atomic_fence_release"
1092 #endif
1093 }
1094
1095 #undef _Py_atomic_ASSERT_ARG_TYPE
1096