File indexing completed on 2025-11-19 09:50:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef Py_ATOMIC_MSC_H
0013 # error "this header file must not be included directly"
0014 #endif
0015
0016 #include <intrin.h>
0017
0018 #define _Py_atomic_ASSERT_ARG_TYPE(TYPE) \
0019 Py_BUILD_ASSERT(sizeof(*obj) == sizeof(TYPE))
0020
0021
0022
0023
0024 static inline int8_t
0025 _Py_atomic_add_int8(int8_t *obj, int8_t value)
0026 {
0027 _Py_atomic_ASSERT_ARG_TYPE(char);
0028 return (int8_t)_InterlockedExchangeAdd8((volatile char *)obj, (char)value);
0029 }
0030
0031 static inline int16_t
0032 _Py_atomic_add_int16(int16_t *obj, int16_t value)
0033 {
0034 _Py_atomic_ASSERT_ARG_TYPE(short);
0035 return (int16_t)_InterlockedExchangeAdd16((volatile short *)obj, (short)value);
0036 }
0037
0038 static inline int32_t
0039 _Py_atomic_add_int32(int32_t *obj, int32_t value)
0040 {
0041 _Py_atomic_ASSERT_ARG_TYPE(long);
0042 return (int32_t)_InterlockedExchangeAdd((volatile long *)obj, (long)value);
0043 }
0044
0045 static inline int64_t
0046 _Py_atomic_add_int64(int64_t *obj, int64_t value)
0047 {
0048 #if defined(_M_X64) || defined(_M_ARM64)
0049 _Py_atomic_ASSERT_ARG_TYPE(__int64);
0050 return (int64_t)_InterlockedExchangeAdd64((volatile __int64 *)obj, (__int64)value);
0051 #else
0052 int64_t old_value = _Py_atomic_load_int64_relaxed(obj);
0053 for (;;) {
0054 int64_t new_value = old_value + value;
0055 if (_Py_atomic_compare_exchange_int64(obj, &old_value, new_value)) {
0056 return old_value;
0057 }
0058 }
0059 #endif
0060 }
0061
0062
0063 static inline uint8_t
0064 _Py_atomic_add_uint8(uint8_t *obj, uint8_t value)
0065 {
0066 return (uint8_t)_Py_atomic_add_int8((int8_t *)obj, (int8_t)value);
0067 }
0068
0069 static inline uint16_t
0070 _Py_atomic_add_uint16(uint16_t *obj, uint16_t value)
0071 {
0072 return (uint16_t)_Py_atomic_add_int16((int16_t *)obj, (int16_t)value);
0073 }
0074
0075 static inline uint32_t
0076 _Py_atomic_add_uint32(uint32_t *obj, uint32_t value)
0077 {
0078 return (uint32_t)_Py_atomic_add_int32((int32_t *)obj, (int32_t)value);
0079 }
0080
0081 static inline int
0082 _Py_atomic_add_int(int *obj, int value)
0083 {
0084 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
0085 return (int)_Py_atomic_add_int32((int32_t *)obj, (int32_t)value);
0086 }
0087
0088 static inline unsigned int
0089 _Py_atomic_add_uint(unsigned int *obj, unsigned int value)
0090 {
0091 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
0092 return (unsigned int)_Py_atomic_add_int32((int32_t *)obj, (int32_t)value);
0093 }
0094
0095 static inline uint64_t
0096 _Py_atomic_add_uint64(uint64_t *obj, uint64_t value)
0097 {
0098 return (uint64_t)_Py_atomic_add_int64((int64_t *)obj, (int64_t)value);
0099 }
0100
0101 static inline intptr_t
0102 _Py_atomic_add_intptr(intptr_t *obj, intptr_t value)
0103 {
0104 #if SIZEOF_VOID_P == 8
0105 _Py_atomic_ASSERT_ARG_TYPE(int64_t);
0106 return (intptr_t)_Py_atomic_add_int64((int64_t *)obj, (int64_t)value);
0107 #else
0108 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
0109 return (intptr_t)_Py_atomic_add_int32((int32_t *)obj, (int32_t)value);
0110 #endif
0111 }
0112
0113 static inline uintptr_t
0114 _Py_atomic_add_uintptr(uintptr_t *obj, uintptr_t value)
0115 {
0116 _Py_atomic_ASSERT_ARG_TYPE(intptr_t);
0117 return (uintptr_t)_Py_atomic_add_intptr((intptr_t *)obj, (intptr_t)value);
0118 }
0119
0120 static inline Py_ssize_t
0121 _Py_atomic_add_ssize(Py_ssize_t *obj, Py_ssize_t value)
0122 {
0123 _Py_atomic_ASSERT_ARG_TYPE(intptr_t);
0124 return (Py_ssize_t)_Py_atomic_add_intptr((intptr_t *)obj, (intptr_t)value);
0125 }
0126
0127
0128
0129
0130 static inline int
0131 _Py_atomic_compare_exchange_int8(int8_t *obj, int8_t *expected, int8_t value)
0132 {
0133 _Py_atomic_ASSERT_ARG_TYPE(char);
0134 int8_t initial = (int8_t)_InterlockedCompareExchange8(
0135 (volatile char *)obj,
0136 (char)value,
0137 (char)*expected);
0138 if (initial == *expected) {
0139 return 1;
0140 }
0141 *expected = initial;
0142 return 0;
0143 }
0144
0145 static inline int
0146 _Py_atomic_compare_exchange_int16(int16_t *obj, int16_t *expected, int16_t value)
0147 {
0148 _Py_atomic_ASSERT_ARG_TYPE(short);
0149 int16_t initial = (int16_t)_InterlockedCompareExchange16(
0150 (volatile short *)obj,
0151 (short)value,
0152 (short)*expected);
0153 if (initial == *expected) {
0154 return 1;
0155 }
0156 *expected = initial;
0157 return 0;
0158 }
0159
0160 static inline int
0161 _Py_atomic_compare_exchange_int32(int32_t *obj, int32_t *expected, int32_t value)
0162 {
0163 _Py_atomic_ASSERT_ARG_TYPE(long);
0164 int32_t initial = (int32_t)_InterlockedCompareExchange(
0165 (volatile long *)obj,
0166 (long)value,
0167 (long)*expected);
0168 if (initial == *expected) {
0169 return 1;
0170 }
0171 *expected = initial;
0172 return 0;
0173 }
0174
0175 static inline int
0176 _Py_atomic_compare_exchange_int64(int64_t *obj, int64_t *expected, int64_t value)
0177 {
0178 _Py_atomic_ASSERT_ARG_TYPE(__int64);
0179 int64_t initial = (int64_t)_InterlockedCompareExchange64(
0180 (volatile __int64 *)obj,
0181 (__int64)value,
0182 (__int64)*expected);
0183 if (initial == *expected) {
0184 return 1;
0185 }
0186 *expected = initial;
0187 return 0;
0188 }
0189
0190 static inline int
0191 _Py_atomic_compare_exchange_ptr(void *obj, void *expected, void *value)
0192 {
0193 void *initial = _InterlockedCompareExchangePointer(
0194 (void**)obj,
0195 value,
0196 *(void**)expected);
0197 if (initial == *(void**)expected) {
0198 return 1;
0199 }
0200 *(void**)expected = initial;
0201 return 0;
0202 }
0203
0204
0205 static inline int
0206 _Py_atomic_compare_exchange_uint8(uint8_t *obj, uint8_t *expected, uint8_t value)
0207 {
0208 return _Py_atomic_compare_exchange_int8((int8_t *)obj,
0209 (int8_t *)expected,
0210 (int8_t)value);
0211 }
0212
0213 static inline int
0214 _Py_atomic_compare_exchange_uint16(uint16_t *obj, uint16_t *expected, uint16_t value)
0215 {
0216 return _Py_atomic_compare_exchange_int16((int16_t *)obj,
0217 (int16_t *)expected,
0218 (int16_t)value);
0219 }
0220
0221 static inline int
0222 _Py_atomic_compare_exchange_uint32(uint32_t *obj, uint32_t *expected, uint32_t value)
0223 {
0224 return _Py_atomic_compare_exchange_int32((int32_t *)obj,
0225 (int32_t *)expected,
0226 (int32_t)value);
0227 }
0228
0229 static inline int
0230 _Py_atomic_compare_exchange_int(int *obj, int *expected, int value)
0231 {
0232 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
0233 return _Py_atomic_compare_exchange_int32((int32_t *)obj,
0234 (int32_t *)expected,
0235 (int32_t)value);
0236 }
0237
0238 static inline int
0239 _Py_atomic_compare_exchange_uint(unsigned int *obj, unsigned int *expected, unsigned int value)
0240 {
0241 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
0242 return _Py_atomic_compare_exchange_int32((int32_t *)obj,
0243 (int32_t *)expected,
0244 (int32_t)value);
0245 }
0246
0247 static inline int
0248 _Py_atomic_compare_exchange_uint64(uint64_t *obj, uint64_t *expected, uint64_t value)
0249 {
0250 return _Py_atomic_compare_exchange_int64((int64_t *)obj,
0251 (int64_t *)expected,
0252 (int64_t)value);
0253 }
0254
0255 static inline int
0256 _Py_atomic_compare_exchange_intptr(intptr_t *obj, intptr_t *expected, intptr_t value)
0257 {
0258 _Py_atomic_ASSERT_ARG_TYPE(void*);
0259 return _Py_atomic_compare_exchange_ptr((void**)obj,
0260 (void**)expected,
0261 (void*)value);
0262 }
0263
0264 static inline int
0265 _Py_atomic_compare_exchange_uintptr(uintptr_t *obj, uintptr_t *expected, uintptr_t value)
0266 {
0267 _Py_atomic_ASSERT_ARG_TYPE(void*);
0268 return _Py_atomic_compare_exchange_ptr((void**)obj,
0269 (void**)expected,
0270 (void*)value);
0271 }
0272
0273 static inline int
0274 _Py_atomic_compare_exchange_ssize(Py_ssize_t *obj, Py_ssize_t *expected, Py_ssize_t value)
0275 {
0276 _Py_atomic_ASSERT_ARG_TYPE(void*);
0277 return _Py_atomic_compare_exchange_ptr((void**)obj,
0278 (void**)expected,
0279 (void*)value);
0280 }
0281
0282
0283
0284
0285 static inline int8_t
0286 _Py_atomic_exchange_int8(int8_t *obj, int8_t value)
0287 {
0288 _Py_atomic_ASSERT_ARG_TYPE(char);
0289 return (int8_t)_InterlockedExchange8((volatile char *)obj, (char)value);
0290 }
0291
0292 static inline int16_t
0293 _Py_atomic_exchange_int16(int16_t *obj, int16_t value)
0294 {
0295 _Py_atomic_ASSERT_ARG_TYPE(short);
0296 return (int16_t)_InterlockedExchange16((volatile short *)obj, (short)value);
0297 }
0298
0299 static inline int32_t
0300 _Py_atomic_exchange_int32(int32_t *obj, int32_t value)
0301 {
0302 _Py_atomic_ASSERT_ARG_TYPE(long);
0303 return (int32_t)_InterlockedExchange((volatile long *)obj, (long)value);
0304 }
0305
0306 static inline int64_t
0307 _Py_atomic_exchange_int64(int64_t *obj, int64_t value)
0308 {
0309 #if defined(_M_X64) || defined(_M_ARM64)
0310 _Py_atomic_ASSERT_ARG_TYPE(__int64);
0311 return (int64_t)_InterlockedExchange64((volatile __int64 *)obj, (__int64)value);
0312 #else
0313 int64_t old_value = _Py_atomic_load_int64_relaxed(obj);
0314 for (;;) {
0315 if (_Py_atomic_compare_exchange_int64(obj, &old_value, value)) {
0316 return old_value;
0317 }
0318 }
0319 #endif
0320 }
0321
0322 static inline void*
0323 _Py_atomic_exchange_ptr(void *obj, void *value)
0324 {
0325 return (void*)_InterlockedExchangePointer((void * volatile *)obj, (void *)value);
0326 }
0327
0328
0329 static inline uint8_t
0330 _Py_atomic_exchange_uint8(uint8_t *obj, uint8_t value)
0331 {
0332 return (uint8_t)_Py_atomic_exchange_int8((int8_t *)obj,
0333 (int8_t)value);
0334 }
0335
0336 static inline uint16_t
0337 _Py_atomic_exchange_uint16(uint16_t *obj, uint16_t value)
0338 {
0339 return (uint16_t)_Py_atomic_exchange_int16((int16_t *)obj,
0340 (int16_t)value);
0341 }
0342
0343 static inline uint32_t
0344 _Py_atomic_exchange_uint32(uint32_t *obj, uint32_t value)
0345 {
0346 return (uint32_t)_Py_atomic_exchange_int32((int32_t *)obj,
0347 (int32_t)value);
0348 }
0349
0350 static inline int
0351 _Py_atomic_exchange_int(int *obj, int value)
0352 {
0353 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
0354 return (int)_Py_atomic_exchange_int32((int32_t *)obj,
0355 (int32_t)value);
0356 }
0357
0358 static inline unsigned int
0359 _Py_atomic_exchange_uint(unsigned int *obj, unsigned int value)
0360 {
0361 _Py_atomic_ASSERT_ARG_TYPE(int32_t);
0362 return (unsigned int)_Py_atomic_exchange_int32((int32_t *)obj,
0363 (int32_t)value);
0364 }
0365
0366 static inline uint64_t
0367 _Py_atomic_exchange_uint64(uint64_t *obj, uint64_t value)
0368 {
0369 return (uint64_t)_Py_atomic_exchange_int64((int64_t *)obj,
0370 (int64_t)value);
0371 }
0372
0373 static inline intptr_t
0374 _Py_atomic_exchange_intptr(intptr_t *obj, intptr_t value)
0375 {
0376 _Py_atomic_ASSERT_ARG_TYPE(void*);
0377 return (intptr_t)_Py_atomic_exchange_ptr((void**)obj,
0378 (void*)value);
0379 }
0380
0381 static inline uintptr_t
0382 _Py_atomic_exchange_uintptr(uintptr_t *obj, uintptr_t value)
0383 {
0384 _Py_atomic_ASSERT_ARG_TYPE(void*);
0385 return (uintptr_t)_Py_atomic_exchange_ptr((void**)obj,
0386 (void*)value);
0387 }
0388
0389 static inline Py_ssize_t
0390 _Py_atomic_exchange_ssize(Py_ssize_t *obj, Py_ssize_t value)
0391 {
0392 _Py_atomic_ASSERT_ARG_TYPE(void*);
0393 return (Py_ssize_t)_Py_atomic_exchange_ptr((void**)obj,
0394 (void*)value);
0395 }
0396
0397
0398
0399
0400 static inline uint8_t
0401 _Py_atomic_and_uint8(uint8_t *obj, uint8_t value)
0402 {
0403 _Py_atomic_ASSERT_ARG_TYPE(char);
0404 return (uint8_t)_InterlockedAnd8((volatile char *)obj, (char)value);
0405 }
0406
0407 static inline uint16_t
0408 _Py_atomic_and_uint16(uint16_t *obj, uint16_t value)
0409 {
0410 _Py_atomic_ASSERT_ARG_TYPE(short);
0411 return (uint16_t)_InterlockedAnd16((volatile short *)obj, (short)value);
0412 }
0413
0414 static inline uint32_t
0415 _Py_atomic_and_uint32(uint32_t *obj, uint32_t value)
0416 {
0417 _Py_atomic_ASSERT_ARG_TYPE(long);
0418 return (uint32_t)_InterlockedAnd((volatile long *)obj, (long)value);
0419 }
0420
0421 static inline uint64_t
0422 _Py_atomic_and_uint64(uint64_t *obj, uint64_t value)
0423 {
0424 #if defined(_M_X64) || defined(_M_ARM64)
0425 _Py_atomic_ASSERT_ARG_TYPE(__int64);
0426 return (uint64_t)_InterlockedAnd64((volatile __int64 *)obj, (__int64)value);
0427 #else
0428 uint64_t old_value = _Py_atomic_load_uint64_relaxed(obj);
0429 for (;;) {
0430 uint64_t new_value = old_value & value;
0431 if (_Py_atomic_compare_exchange_uint64(obj, &old_value, new_value)) {
0432 return old_value;
0433 }
0434 }
0435 #endif
0436 }
0437
0438 static inline uintptr_t
0439 _Py_atomic_and_uintptr(uintptr_t *obj, uintptr_t value)
0440 {
0441 #if SIZEOF_VOID_P == 8
0442 _Py_atomic_ASSERT_ARG_TYPE(uint64_t);
0443 return (uintptr_t)_Py_atomic_and_uint64((uint64_t *)obj,
0444 (uint64_t)value);
0445 #else
0446 _Py_atomic_ASSERT_ARG_TYPE(uint32_t);
0447 return (uintptr_t)_Py_atomic_and_uint32((uint32_t *)obj,
0448 (uint32_t)value);
0449 #endif
0450 }
0451
0452
0453
0454
0455 static inline uint8_t
0456 _Py_atomic_or_uint8(uint8_t *obj, uint8_t value)
0457 {
0458 _Py_atomic_ASSERT_ARG_TYPE(char);
0459 return (uint8_t)_InterlockedOr8((volatile char *)obj, (char)value);
0460 }
0461
0462 static inline uint16_t
0463 _Py_atomic_or_uint16(uint16_t *obj, uint16_t value)
0464 {
0465 _Py_atomic_ASSERT_ARG_TYPE(short);
0466 return (uint16_t)_InterlockedOr16((volatile short *)obj, (short)value);
0467 }
0468
0469 static inline uint32_t
0470 _Py_atomic_or_uint32(uint32_t *obj, uint32_t value)
0471 {
0472 _Py_atomic_ASSERT_ARG_TYPE(long);
0473 return (uint32_t)_InterlockedOr((volatile long *)obj, (long)value);
0474 }
0475
0476 static inline uint64_t
0477 _Py_atomic_or_uint64(uint64_t *obj, uint64_t value)
0478 {
0479 #if defined(_M_X64) || defined(_M_ARM64)
0480 _Py_atomic_ASSERT_ARG_TYPE(__int64);
0481 return (uint64_t)_InterlockedOr64((volatile __int64 *)obj, (__int64)value);
0482 #else
0483 uint64_t old_value = _Py_atomic_load_uint64_relaxed(obj);
0484 for (;;) {
0485 uint64_t new_value = old_value | value;
0486 if (_Py_atomic_compare_exchange_uint64(obj, &old_value, new_value)) {
0487 return old_value;
0488 }
0489 }
0490 #endif
0491 }
0492
0493
0494 static inline uintptr_t
0495 _Py_atomic_or_uintptr(uintptr_t *obj, uintptr_t value)
0496 {
0497 #if SIZEOF_VOID_P == 8
0498 _Py_atomic_ASSERT_ARG_TYPE(uint64_t);
0499 return (uintptr_t)_Py_atomic_or_uint64((uint64_t *)obj,
0500 (uint64_t)value);
0501 #else
0502 _Py_atomic_ASSERT_ARG_TYPE(uint32_t);
0503 return (uintptr_t)_Py_atomic_or_uint32((uint32_t *)obj,
0504 (uint32_t)value);
0505 #endif
0506 }
0507
0508
0509
0510
0511 static inline uint8_t
0512 _Py_atomic_load_uint8(const uint8_t *obj)
0513 {
0514 #if defined(_M_X64) || defined(_M_IX86)
0515 return *(volatile uint8_t *)obj;
0516 #elif defined(_M_ARM64)
0517 return (uint8_t)__ldar8((unsigned __int8 volatile *)obj);
0518 #else
0519 # error "no implementation of _Py_atomic_load_uint8"
0520 #endif
0521 }
0522
0523 static inline uint16_t
0524 _Py_atomic_load_uint16(const uint16_t *obj)
0525 {
0526 #if defined(_M_X64) || defined(_M_IX86)
0527 return *(volatile uint16_t *)obj;
0528 #elif defined(_M_ARM64)
0529 return (uint16_t)__ldar16((unsigned __int16 volatile *)obj);
0530 #else
0531 # error "no implementation of _Py_atomic_load_uint16"
0532 #endif
0533 }
0534
0535 static inline uint32_t
0536 _Py_atomic_load_uint32(const uint32_t *obj)
0537 {
0538 #if defined(_M_X64) || defined(_M_IX86)
0539 return *(volatile uint32_t *)obj;
0540 #elif defined(_M_ARM64)
0541 return (uint32_t)__ldar32((unsigned __int32 volatile *)obj);
0542 #else
0543 # error "no implementation of _Py_atomic_load_uint32"
0544 #endif
0545 }
0546
0547 static inline uint64_t
0548 _Py_atomic_load_uint64(const uint64_t *obj)
0549 {
0550 #if defined(_M_X64) || defined(_M_IX86)
0551 return *(volatile uint64_t *)obj;
0552 #elif defined(_M_ARM64)
0553 return (uint64_t)__ldar64((unsigned __int64 volatile *)obj);
0554 #else
0555 # error "no implementation of _Py_atomic_load_uint64"
0556 #endif
0557 }
0558
0559 static inline int8_t
0560 _Py_atomic_load_int8(const int8_t *obj)
0561 {
0562 return (int8_t)_Py_atomic_load_uint8((const uint8_t *)obj);
0563 }
0564
0565 static inline int16_t
0566 _Py_atomic_load_int16(const int16_t *obj)
0567 {
0568 return (int16_t)_Py_atomic_load_uint16((const uint16_t *)obj);
0569 }
0570
0571 static inline int32_t
0572 _Py_atomic_load_int32(const int32_t *obj)
0573 {
0574 return (int32_t)_Py_atomic_load_uint32((const uint32_t *)obj);
0575 }
0576
0577 static inline int
0578 _Py_atomic_load_int(const int *obj)
0579 {
0580 _Py_atomic_ASSERT_ARG_TYPE(uint32_t);
0581 return (int)_Py_atomic_load_uint32((uint32_t *)obj);
0582 }
0583
0584 static inline unsigned int
0585 _Py_atomic_load_uint(const unsigned int *obj)
0586 {
0587 _Py_atomic_ASSERT_ARG_TYPE(uint32_t);
0588 return (unsigned int)_Py_atomic_load_uint32((uint32_t *)obj);
0589 }
0590
0591 static inline int64_t
0592 _Py_atomic_load_int64(const int64_t *obj)
0593 {
0594 return (int64_t)_Py_atomic_load_uint64((const uint64_t *)obj);
0595 }
0596
0597 static inline void*
0598 _Py_atomic_load_ptr(const void *obj)
0599 {
0600 #if SIZEOF_VOID_P == 8
0601 return (void*)_Py_atomic_load_uint64((const uint64_t *)obj);
0602 #else
0603 return (void*)_Py_atomic_load_uint32((const uint32_t *)obj);
0604 #endif
0605 }
0606
0607 static inline intptr_t
0608 _Py_atomic_load_intptr(const intptr_t *obj)
0609 {
0610 _Py_atomic_ASSERT_ARG_TYPE(void*);
0611 return (intptr_t)_Py_atomic_load_ptr((void*)obj);
0612 }
0613
0614 static inline uintptr_t
0615 _Py_atomic_load_uintptr(const uintptr_t *obj)
0616 {
0617 _Py_atomic_ASSERT_ARG_TYPE(void*);
0618 return (uintptr_t)_Py_atomic_load_ptr((void*)obj);
0619 }
0620
0621 static inline Py_ssize_t
0622 _Py_atomic_load_ssize(const Py_ssize_t *obj)
0623 {
0624 _Py_atomic_ASSERT_ARG_TYPE(void*);
0625 return (Py_ssize_t)_Py_atomic_load_ptr((void*)obj);
0626 }
0627
0628
0629
0630
0631 static inline int
0632 _Py_atomic_load_int_relaxed(const int *obj)
0633 {
0634 return *(volatile int *)obj;
0635 }
0636
0637 static inline int8_t
0638 _Py_atomic_load_int8_relaxed(const int8_t *obj)
0639 {
0640 return *(volatile int8_t *)obj;
0641 }
0642
0643 static inline int16_t
0644 _Py_atomic_load_int16_relaxed(const int16_t *obj)
0645 {
0646 return *(volatile int16_t *)obj;
0647 }
0648
0649 static inline int32_t
0650 _Py_atomic_load_int32_relaxed(const int32_t *obj)
0651 {
0652 return *(volatile int32_t *)obj;
0653 }
0654
0655 static inline int64_t
0656 _Py_atomic_load_int64_relaxed(const int64_t *obj)
0657 {
0658 return *(volatile int64_t *)obj;
0659 }
0660
0661 static inline intptr_t
0662 _Py_atomic_load_intptr_relaxed(const intptr_t *obj)
0663 {
0664 return *(volatile intptr_t *)obj;
0665 }
0666
0667 static inline uint8_t
0668 _Py_atomic_load_uint8_relaxed(const uint8_t *obj)
0669 {
0670 return *(volatile uint8_t *)obj;
0671 }
0672
0673 static inline uint16_t
0674 _Py_atomic_load_uint16_relaxed(const uint16_t *obj)
0675 {
0676 return *(volatile uint16_t *)obj;
0677 }
0678
0679 static inline uint32_t
0680 _Py_atomic_load_uint32_relaxed(const uint32_t *obj)
0681 {
0682 return *(volatile uint32_t *)obj;
0683 }
0684
0685 static inline uint64_t
0686 _Py_atomic_load_uint64_relaxed(const uint64_t *obj)
0687 {
0688 return *(volatile uint64_t *)obj;
0689 }
0690
0691 static inline uintptr_t
0692 _Py_atomic_load_uintptr_relaxed(const uintptr_t *obj)
0693 {
0694 return *(volatile uintptr_t *)obj;
0695 }
0696
0697 static inline unsigned int
0698 _Py_atomic_load_uint_relaxed(const unsigned int *obj)
0699 {
0700 return *(volatile unsigned int *)obj;
0701 }
0702
0703 static inline Py_ssize_t
0704 _Py_atomic_load_ssize_relaxed(const Py_ssize_t *obj)
0705 {
0706 return *(volatile Py_ssize_t *)obj;
0707 }
0708
0709 static inline void*
0710 _Py_atomic_load_ptr_relaxed(const void *obj)
0711 {
0712 return *(void * volatile *)obj;
0713 }
0714
0715 static inline unsigned long long
0716 _Py_atomic_load_ullong_relaxed(const unsigned long long *obj)
0717 {
0718 return *(volatile unsigned long long *)obj;
0719 }
0720
0721
0722
0723
0724 static inline void
0725 _Py_atomic_store_int(int *obj, int value)
0726 {
0727 (void)_Py_atomic_exchange_int(obj, value);
0728 }
0729
0730 static inline void
0731 _Py_atomic_store_int8(int8_t *obj, int8_t value)
0732 {
0733 (void)_Py_atomic_exchange_int8(obj, value);
0734 }
0735
0736 static inline void
0737 _Py_atomic_store_int16(int16_t *obj, int16_t value)
0738 {
0739 (void)_Py_atomic_exchange_int16(obj, value);
0740 }
0741
0742 static inline void
0743 _Py_atomic_store_int32(int32_t *obj, int32_t value)
0744 {
0745 (void)_Py_atomic_exchange_int32(obj, value);
0746 }
0747
0748 static inline void
0749 _Py_atomic_store_int64(int64_t *obj, int64_t value)
0750 {
0751 (void)_Py_atomic_exchange_int64(obj, value);
0752 }
0753
0754 static inline void
0755 _Py_atomic_store_intptr(intptr_t *obj, intptr_t value)
0756 {
0757 (void)_Py_atomic_exchange_intptr(obj, value);
0758 }
0759
0760 static inline void
0761 _Py_atomic_store_uint8(uint8_t *obj, uint8_t value)
0762 {
0763 (void)_Py_atomic_exchange_uint8(obj, value);
0764 }
0765
0766 static inline void
0767 _Py_atomic_store_uint16(uint16_t *obj, uint16_t value)
0768 {
0769 (void)_Py_atomic_exchange_uint16(obj, value);
0770 }
0771
0772 static inline void
0773 _Py_atomic_store_uint32(uint32_t *obj, uint32_t value)
0774 {
0775 (void)_Py_atomic_exchange_uint32(obj, value);
0776 }
0777
0778 static inline void
0779 _Py_atomic_store_uint64(uint64_t *obj, uint64_t value)
0780 {
0781 (void)_Py_atomic_exchange_uint64(obj, value);
0782 }
0783
0784 static inline void
0785 _Py_atomic_store_uintptr(uintptr_t *obj, uintptr_t value)
0786 {
0787 (void)_Py_atomic_exchange_uintptr(obj, value);
0788 }
0789
0790 static inline void
0791 _Py_atomic_store_uint(unsigned int *obj, unsigned int value)
0792 {
0793 (void)_Py_atomic_exchange_uint(obj, value);
0794 }
0795
0796 static inline void
0797 _Py_atomic_store_ptr(void *obj, void *value)
0798 {
0799 (void)_Py_atomic_exchange_ptr(obj, value);
0800 }
0801
0802 static inline void
0803 _Py_atomic_store_ssize(Py_ssize_t *obj, Py_ssize_t value)
0804 {
0805 (void)_Py_atomic_exchange_ssize(obj, value);
0806 }
0807
0808
0809
0810
0811 static inline void
0812 _Py_atomic_store_int_relaxed(int *obj, int value)
0813 {
0814 *(volatile int *)obj = value;
0815 }
0816
0817 static inline void
0818 _Py_atomic_store_int8_relaxed(int8_t *obj, int8_t value)
0819 {
0820 *(volatile int8_t *)obj = value;
0821 }
0822
0823 static inline void
0824 _Py_atomic_store_int16_relaxed(int16_t *obj, int16_t value)
0825 {
0826 *(volatile int16_t *)obj = value;
0827 }
0828
0829 static inline void
0830 _Py_atomic_store_int32_relaxed(int32_t *obj, int32_t value)
0831 {
0832 *(volatile int32_t *)obj = value;
0833 }
0834
0835 static inline void
0836 _Py_atomic_store_int64_relaxed(int64_t *obj, int64_t value)
0837 {
0838 *(volatile int64_t *)obj = value;
0839 }
0840
0841 static inline void
0842 _Py_atomic_store_intptr_relaxed(intptr_t *obj, intptr_t value)
0843 {
0844 *(volatile intptr_t *)obj = value;
0845 }
0846
0847 static inline void
0848 _Py_atomic_store_uint8_relaxed(uint8_t *obj, uint8_t value)
0849 {
0850 *(volatile uint8_t *)obj = value;
0851 }
0852
0853 static inline void
0854 _Py_atomic_store_uint16_relaxed(uint16_t *obj, uint16_t value)
0855 {
0856 *(volatile uint16_t *)obj = value;
0857 }
0858
0859 static inline void
0860 _Py_atomic_store_uint32_relaxed(uint32_t *obj, uint32_t value)
0861 {
0862 *(volatile uint32_t *)obj = value;
0863 }
0864
0865 static inline void
0866 _Py_atomic_store_uint64_relaxed(uint64_t *obj, uint64_t value)
0867 {
0868 *(volatile uint64_t *)obj = value;
0869 }
0870
0871 static inline void
0872 _Py_atomic_store_uintptr_relaxed(uintptr_t *obj, uintptr_t value)
0873 {
0874 *(volatile uintptr_t *)obj = value;
0875 }
0876
0877 static inline void
0878 _Py_atomic_store_uint_relaxed(unsigned int *obj, unsigned int value)
0879 {
0880 *(volatile unsigned int *)obj = value;
0881 }
0882
0883 static inline void
0884 _Py_atomic_store_ptr_relaxed(void *obj, void* value)
0885 {
0886 *(void * volatile *)obj = value;
0887 }
0888
0889 static inline void
0890 _Py_atomic_store_ssize_relaxed(Py_ssize_t *obj, Py_ssize_t value)
0891 {
0892 *(volatile Py_ssize_t *)obj = value;
0893 }
0894
0895 static inline void
0896 _Py_atomic_store_ullong_relaxed(unsigned long long *obj,
0897 unsigned long long value)
0898 {
0899 *(volatile unsigned long long *)obj = value;
0900 }
0901
0902
0903
0904
0905 static inline void *
0906 _Py_atomic_load_ptr_acquire(const void *obj)
0907 {
0908 #if defined(_M_X64) || defined(_M_IX86)
0909 return *(void * volatile *)obj;
0910 #elif defined(_M_ARM64)
0911 return (void *)__ldar64((unsigned __int64 volatile *)obj);
0912 #else
0913 # error "no implementation of _Py_atomic_load_ptr_acquire"
0914 #endif
0915 }
0916
0917 static inline uintptr_t
0918 _Py_atomic_load_uintptr_acquire(const uintptr_t *obj)
0919 {
0920 #if defined(_M_X64) || defined(_M_IX86)
0921 return *(uintptr_t volatile *)obj;
0922 #elif defined(_M_ARM64)
0923 return (uintptr_t)__ldar64((unsigned __int64 volatile *)obj);
0924 #else
0925 # error "no implementation of _Py_atomic_load_uintptr_acquire"
0926 #endif
0927 }
0928
0929 static inline void
0930 _Py_atomic_store_ptr_release(void *obj, void *value)
0931 {
0932 #if defined(_M_X64) || defined(_M_IX86)
0933 *(void * volatile *)obj = value;
0934 #elif defined(_M_ARM64)
0935 __stlr64((unsigned __int64 volatile *)obj, (uintptr_t)value);
0936 #else
0937 # error "no implementation of _Py_atomic_store_ptr_release"
0938 #endif
0939 }
0940
0941 static inline void
0942 _Py_atomic_store_uintptr_release(uintptr_t *obj, uintptr_t value)
0943 {
0944 #if defined(_M_X64) || defined(_M_IX86)
0945 *(uintptr_t volatile *)obj = value;
0946 #elif defined(_M_ARM64)
0947 _Py_atomic_ASSERT_ARG_TYPE(unsigned __int64);
0948 __stlr64((unsigned __int64 volatile *)obj, (unsigned __int64)value);
0949 #else
0950 # error "no implementation of _Py_atomic_store_uintptr_release"
0951 #endif
0952 }
0953
0954 static inline void
0955 _Py_atomic_store_int_release(int *obj, int value)
0956 {
0957 #if defined(_M_X64) || defined(_M_IX86)
0958 *(int volatile *)obj = value;
0959 #elif defined(_M_ARM64)
0960 _Py_atomic_ASSERT_ARG_TYPE(unsigned __int32);
0961 __stlr32((unsigned __int32 volatile *)obj, (unsigned __int32)value);
0962 #else
0963 # error "no implementation of _Py_atomic_store_int_release"
0964 #endif
0965 }
0966
0967 static inline void
0968 _Py_atomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value)
0969 {
0970 #if defined(_M_X64) || defined(_M_IX86)
0971 *(Py_ssize_t volatile *)obj = value;
0972 #elif defined(_M_ARM64)
0973 __stlr64((unsigned __int64 volatile *)obj, (unsigned __int64)value);
0974 #else
0975 # error "no implementation of _Py_atomic_store_ssize_release"
0976 #endif
0977 }
0978
0979 static inline int
0980 _Py_atomic_load_int_acquire(const int *obj)
0981 {
0982 #if defined(_M_X64) || defined(_M_IX86)
0983 return *(int volatile *)obj;
0984 #elif defined(_M_ARM64)
0985 _Py_atomic_ASSERT_ARG_TYPE(unsigned __int32);
0986 return (int)__ldar32((unsigned __int32 volatile *)obj);
0987 #else
0988 # error "no implementation of _Py_atomic_load_int_acquire"
0989 #endif
0990 }
0991
0992 static inline void
0993 _Py_atomic_store_uint32_release(uint32_t *obj, uint32_t value)
0994 {
0995 #if defined(_M_X64) || defined(_M_IX86)
0996 *(uint32_t volatile *)obj = value;
0997 #elif defined(_M_ARM64)
0998 _Py_atomic_ASSERT_ARG_TYPE(unsigned __int32);
0999 __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
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
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
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
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
1056
1057 static inline 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
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
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