• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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