Created
April 9, 2026 15:58
-
-
Save Vizonex/17bbfe7e6bb6a36d82d0d99217eaa049 to your computer and use it in GitHub Desktop.
cyatomics is a fork of python's atomic stuff that has it's things renamed to prevent overlapping this is mostly just an idea for getting cython to someday support atomics. This was code I had left for around 3 months but was mostly just word rewriting of python's atomic structure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Contains a collection of pyatomic functions that have been exclusively modified for the use with | |
| # C Compiled sources for the sake of speed and needing less costly functionality | |
| # or having to deal with the annoying headaches of adding these in yourself. | |
| from libc.stdint cimport * | |
| cdef extern from "cyatomics.h" nogil: | |
| int _cyatomic_add_int(int *obj, int value) | |
| int8_t _cyatomic_add_int8(int8_t *obj, int8_t value) | |
| int16_t _cyatomic_add_int16(int16_t *obj, int16_t value) | |
| int32_t _cyatomic_add_int32(int32_t *obj, int32_t value) | |
| int64_t _cyatomic_add_int64(int64_t *obj, int64_t value) | |
| intptr_t _cyatomic_add_intptr(intptr_t *obj, intptr_t value) | |
| unsigned int _cyatomic_add_uint(unsigned int *obj, unsigned int value) | |
| uint8_t _cyatomic_add_uint8(uint8_t *obj, uint8_t value) | |
| uint16_t _cyatomic_add_uint16(uint16_t *obj, uint16_t value) | |
| uint32_t _cyatomic_add_uint32(uint32_t *obj, uint32_t value) | |
| uint64_t _cyatomic_add_uint64(uint64_t *obj, uint64_t value) | |
| uintptr_t _cyatomic_add_uintptr(uintptr_t *obj, uintptr_t value) | |
| Py_ssize_t _cyatomic_add_ssize(Py_ssize_t *obj, Py_ssize_t value) | |
| int _cyatomic_compare_exchange_int(int *obj, int *expected, int desired) | |
| int _cyatomic_compare_exchange_int8(int8_t *obj, int8_t *expected, int8_t desired) | |
| int _cyatomic_compare_exchange_int16(int16_t *obj, int16_t *expected, int16_t desired) | |
| int _cyatomic_compare_exchange_int32(int32_t *obj, int32_t *expected, int32_t desired) | |
| int _cyatomic_compare_exchange_int64(int64_t *obj, int64_t *expected, int64_t desired) | |
| int _cyatomic_compare_exchange_intptr(intptr_t *obj, intptr_t *expected, intptr_t desired) | |
| int _cyatomic_compare_exchange_uint(unsigned int *obj, unsigned int *expected, unsigned int desired) | |
| int _cyatomic_compare_exchange_uint8(uint8_t *obj, uint8_t *expected, uint8_t desired) | |
| int _cyatomic_compare_exchange_uint16(uint16_t *obj, uint16_t *expected, uint16_t desired) | |
| int _cyatomic_compare_exchange_uint32(uint32_t *obj, uint32_t *expected, uint32_t desired) | |
| int _cyatomic_compare_exchange_uint64(uint64_t *obj, uint64_t *expected, uint64_t desired) | |
| int _cyatomic_compare_exchange_uintptr(uintptr_t *obj, uintptr_t *expected, uintptr_t desired) | |
| int _cyatomic_compare_exchange_ssize(Py_ssize_t *obj, Py_ssize_t *expected, Py_ssize_t desired) | |
| int _cyatomic_compare_exchange_ptr(void *obj, void *expected, void *value) | |
| int _cyatomic_exchange_int(int *obj, int value) | |
| int8_t _cyatomic_exchange_int8(int8_t *obj, int8_t value) | |
| int16_t _cyatomic_exchange_int16(int16_t *obj, int16_t value) | |
| int32_t _cyatomic_exchange_int32(int32_t *obj, int32_t value) | |
| int64_t _cyatomic_exchange_int64(int64_t *obj, int64_t value) | |
| intptr_t _cyatomic_exchange_intptr(intptr_t *obj, intptr_t value) | |
| # unsigned int _cyatomic_exchange_uint(unsigned int *obj, unsigned int value) | |
| uint8_t _cyatomic_exchange_uint8(uint8_t *obj, uint8_t value) | |
| uint16_t _cyatomic_exchange_uint16(uint16_t *obj, uint16_t value) | |
| uint32_t _cyatomic_exchange_uint32(uint32_t *obj, uint32_t value) | |
| uint64_t _cyatomic_exchange_uint64(uint64_t *obj, uint64_t value) | |
| uintptr_t _cyatomic_exchange_uintptr(uintptr_t *obj, uintptr_t value) | |
| Py_ssize_t _cyatomic_exchange_ssize(Py_ssize_t *obj, Py_ssize_t value) | |
| void * _cyatomic_exchange_ptr(void *obj, void *value) | |
| uint8_t _cyatomic_and_uint8(uint8_t *obj, uint8_t value) | |
| uint16_t _cyatomic_and_uint16(uint16_t *obj, uint16_t value) | |
| uint32_t _cyatomic_and_uint32(uint32_t *obj, uint32_t value) | |
| uint64_t _cyatomic_and_uint64(uint64_t *obj, uint64_t value) | |
| uintptr_t _cyatomic_and_uintptr(uintptr_t *obj, uintptr_t value) | |
| uint8_t _cyatomic_or_uint8(uint8_t *obj, uint8_t value) | |
| uint16_t _cyatomic_or_uint16(uint16_t *obj, uint16_t value) | |
| uint32_t _cyatomic_or_uint32(uint32_t *obj, uint32_t value) | |
| uint64_t _cyatomic_or_uint64(uint64_t *obj, uint64_t value) | |
| uintptr_t _cyatomic_or_uintptr(uintptr_t *obj, uintptr_t value) | |
| int _cyatomic_load_int(const int *obj) | |
| int8_t _cyatomic_load_int8(const int8_t *obj) | |
| int16_t _cyatomic_load_int16(const int16_t *obj) | |
| int32_t _cyatomic_load_int32(const int32_t *obj) | |
| int64_t _cyatomic_load_int64(const int64_t *obj) | |
| intptr_t _cyatomic_load_intptr(const intptr_t *obj) | |
| uint8_t _cyatomic_load_uint8(const uint8_t *obj) | |
| uint16_t _cyatomic_load_uint16(const uint16_t *obj) | |
| uint32_t _cyatomic_load_uint32(const uint32_t *obj) | |
| uint64_t _cyatomic_load_uint64(const uint64_t *obj) | |
| uintptr_t _cyatomic_load_uintptr(const uintptr_t *obj) | |
| # unsigned int _cyatomic_load_uint(const unsigned int *obj) | |
| Py_ssize_t _cyatomic_load_ssize(const Py_ssize_t *obj) | |
| void * _cyatomic_load_ptr(const void *obj) | |
| int _cyatomic_load_int_relaxed(const int *obj) | |
| # char _cyatomic_load_char_relaxed(const char *obj) | |
| # unsigned char _cyatomic_load_uchar_relaxed(const unsigned char *obj) | |
| # short _cyatomic_load_short_relaxed(const short *obj) | |
| # unsigned short _cyatomic_load_ushort_relaxed(const unsigned short *obj) | |
| # long _cyatomic_load_long_relaxed(const long *obj) | |
| # double _cyatomic_load_double_relaxed(const double *obj) | |
| # long long _cyatomic_load_llong_relaxed(const long long *obj) | |
| int8_t _cyatomic_load_int8_relaxed(const int8_t *obj) | |
| int16_t _cyatomic_load_int16_relaxed(const int16_t *obj) | |
| int32_t _cyatomic_load_int32_relaxed(const int32_t *obj) | |
| int64_t _cyatomic_load_int64_relaxed(const int64_t *obj) | |
| intptr_t _cyatomic_load_intptr_relaxed(const intptr_t *obj) | |
| uint8_t _cyatomic_load_uint8_relaxed(const uint8_t *obj) | |
| uint16_t _cyatomic_load_uint16_relaxed(const uint16_t *obj) | |
| uint32_t _cyatomic_load_uint32_relaxed(const uint32_t *obj) | |
| uint64_t _cyatomic_load_uint64_relaxed(const uint64_t *obj) | |
| uintptr_t _cyatomic_load_uintptr_relaxed(const uintptr_t *obj) | |
| # unsigned int _cyatomic_load_uint_relaxed(const unsigned int *obj) | |
| Py_ssize_t _cyatomic_load_ssize_relaxed(const Py_ssize_t *obj) | |
| void * _cyatomic_load_ptr_relaxed(const void *obj) | |
| # unsigned long long _cyatomic_load_ullong_relaxed(const unsigned long long *obj) | |
| void _cyatomic_store_int(int *obj, int value) | |
| void _cyatomic_store_int8(int8_t *obj, int8_t value) | |
| void _cyatomic_store_int16(int16_t *obj, int16_t value) | |
| void _cyatomic_store_int32(int32_t *obj, int32_t value) | |
| void _cyatomic_store_int64(int64_t *obj, int64_t value) | |
| void _cyatomic_store_intptr(intptr_t *obj, intptr_t value) | |
| void _cyatomic_store_uint8(uint8_t *obj, uint8_t value) | |
| void _cyatomic_store_uint16(uint16_t *obj, uint16_t value) | |
| void _cyatomic_store_uint32(uint32_t *obj, uint32_t value) | |
| void _cyatomic_store_uint64(uint64_t *obj, uint64_t value) | |
| void _cyatomic_store_uintptr(uintptr_t *obj, uintptr_t value) | |
| void _cyatomic_store_uint(unsigned int *obj, unsigned int value) | |
| void _cyatomic_store_ptr(void *obj, void *value) | |
| void _cyatomic_store_ssize(Py_ssize_t* obj, Py_ssize_t value) | |
| void _cyatomic_store_int_relaxed(int *obj, int value) | |
| void _cyatomic_store_int8_relaxed(int8_t *obj, int8_t value) | |
| void _cyatomic_store_int16_relaxed(int16_t *obj, int16_t value) | |
| void _cyatomic_store_int32_relaxed(int32_t *obj, int32_t value) | |
| void _cyatomic_store_int64_relaxed(int64_t *obj, int64_t value) | |
| void _cyatomic_store_intptr_relaxed(intptr_t *obj, intptr_t value) | |
| void _cyatomic_store_uint8_relaxed(uint8_t* obj, uint8_t value) | |
| void _cyatomic_store_uint16_relaxed(uint16_t *obj, uint16_t value) | |
| void _cyatomic_store_uint32_relaxed(uint32_t *obj, uint32_t value) | |
| void _cyatomic_store_uint64_relaxed(uint64_t *obj, uint64_t value) | |
| void _cyatomic_store_uintptr_relaxed(uintptr_t *obj, uintptr_t value) | |
| void _cyatomic_store_uint_relaxed(unsigned int *obj, unsigned int value) | |
| void _cyatomic_store_ptr_relaxed(void *obj, void *value) | |
| void _cyatomic_store_ssize_relaxed(Py_ssize_t *obj, Py_ssize_t value) | |
| void _cyatomic_store_ullong_relaxed(unsigned long long *obj, | |
| unsigned long long value) | |
| void _cyatomic_store_char_relaxed(char *obj, char value) | |
| void _cyatomic_store_uchar_relaxed(unsigned char *obj, unsigned char value) | |
| void _cyatomic_store_short_relaxed(short *obj, short value) | |
| void _cyatomic_store_ushort_relaxed(unsigned short *obj, unsigned short value) | |
| void _cyatomic_store_long_relaxed(long *obj, long value) | |
| void _cyatomic_store_float_relaxed(float *obj, float value) | |
| void _cyatomic_store_double_relaxed(double *obj, double value) | |
| void _cyatomic_store_llong_relaxed(long long *obj, long long value) | |
| void * _cyatomic_load_ptr_acquire(const void *obj) | |
| uintptr_t _cyatomic_load_uintptr_acquire(const uintptr_t *obj) | |
| void _cyatomic_store_ptr_release(void *obj, void *value) | |
| void _cyatomic_store_uintptr_release(uintptr_t *obj, uintptr_t value) | |
| void _cyatomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value) | |
| void _cyatomic_store_int_release(int *obj, int value) | |
| int _cyatomic_load_int_acquire(const int *obj) | |
| void _cyatomic_store_uint32_release(uint32_t *obj, uint32_t value) | |
| void _cyatomic_store_uint64_release(uint64_t *obj, uint64_t value) | |
| uint64_t _cyatomic_load_uint64_acquire(const uint64_t *obj) | |
| uint32_t _cyatomic_load_uint32_acquire(const uint32_t *obj) | |
| Py_ssize_t _cyatomic_load_ssize_acquire(const Py_ssize_t *obj) | |
| unsigned long _cyatomic_load_ulong(unsigned long p) | |
| unsigned long _cyatomic_load_ulong_relaxed(unsigned long p) | |
| unsigned long _cyatomic_store_ulong(unsigned long p, unsigned long v) | |
| unsigned long _cyatomic_store_ulong_relaxed(unsigned long p, unsigned long v) | |
| # it's recommend using these and not the functions being externed | |
| # to prevent costly headaches and because it's a safer public interface. | |
| ctypedef void* ptr_t | |
| ctypedef fused atomic_type_t: | |
| int | |
| int8_t | |
| int16_t | |
| int32_t | |
| int64_t | |
| intptr_t | |
| uint8_t | |
| uint16_t | |
| uint32_t | |
| uint64_t | |
| uintptr_t | |
| Py_ssize_t | |
| # SEE: https://cython.readthedocs.io/en/latest/src/userguide/fusedtypes.html#type-checking-specializations | |
| # ctypedef fused bunch_of_types: | |
| # bytes | |
| # int | |
| # float | |
| # ctypedef fused string_t: | |
| # cython.p_char | |
| # bytes | |
| # unicode | |
| ctypedef fused atomic_type_t: | |
| int | |
| int8_t | |
| int16_t | |
| int32_t | |
| int64_t | |
| intptr_t | |
| uint8_t | |
| uint16_t | |
| uint32_t | |
| uint64_t | |
| uintptr_t | |
| Py_ssize_t | |
| ctypedef fused atomic_type_or_ptr_t: | |
| int | |
| int8_t | |
| int16_t | |
| int32_t | |
| int64_t | |
| intptr_t | |
| uint8_t | |
| uint16_t | |
| uint32_t | |
| uint64_t | |
| uintptr_t | |
| Py_ssize_t | |
| void | |
| ctypedef fused atomic_type_or_store_ptr_t: | |
| int | |
| int8_t | |
| int16_t | |
| int32_t | |
| int64_t | |
| intptr_t | |
| uint8_t | |
| uint16_t | |
| uint32_t | |
| uint64_t | |
| uintptr_t | |
| Py_ssize_t | |
| ptr_t | |
| cdef inline atomic_type_or_ptr_t atomic_load(const atomic_type_or_ptr_t *obj) noexcept nogil: | |
| if atomic_type_or_ptr_t is int: | |
| return _cyatomic_load_int(obj) | |
| elif atomic_type_or_ptr_t is int8_t: | |
| return _cyatomic_load_int8(obj) | |
| elif atomic_type_or_ptr_t is int16_t: | |
| return _cyatomic_load_int16(obj) | |
| elif atomic_type_or_ptr_t is int32_t: | |
| return _cyatomic_load_int32(obj) | |
| elif atomic_type_or_ptr_t is int64_t: | |
| return _cyatomic_load_int64(obj) | |
| elif atomic_type_or_ptr_t is intptr_t: | |
| return _cyatomic_load_intptr(obj) | |
| elif atomic_type_or_ptr_t is uint8_t: | |
| return _cyatomic_load_uint8(obj) | |
| elif atomic_type_or_ptr_t is uint16_t: | |
| return _cyatomic_load_uint16(obj) | |
| elif atomic_type_or_ptr_t is uint32_t: | |
| return _cyatomic_load_uint32(obj) | |
| elif atomic_type_or_ptr_t is uint64_t: | |
| return _cyatomic_load_uint64(obj) | |
| elif atomic_type_or_ptr_t is uintptr_t: | |
| return _cyatomic_load_uintptr(obj) | |
| elif atomic_type_or_ptr_t is void: | |
| return _cyatomic_load_ptr(obj) | |
| else: | |
| return _cyatomic_load_ssize(obj) | |
| cdef inline atomic_type_or_ptr_t atomic_load_relaxed(const atomic_type_or_ptr_t *obj) noexcept nogil: | |
| if atomic_type_or_ptr_t is int: | |
| return _cyatomic_load_int_relaxed(obj) | |
| elif atomic_type_or_ptr_t is int8_t: | |
| return _cyatomic_load_int8_relaxed(obj) | |
| elif atomic_type_or_ptr_t is int16_t: | |
| return _cyatomic_load_int16_relaxed(obj) | |
| elif atomic_type_or_ptr_t is int32_t: | |
| return _cyatomic_load_int32_relaxed(obj) | |
| elif atomic_type_or_ptr_t is int64_t: | |
| return _cyatomic_load_int64_relaxed(obj) | |
| elif atomic_type_or_ptr_t is intptr_t: | |
| return _cyatomic_load_intptr_relaxed(obj) | |
| elif atomic_type_or_ptr_t is uint8_t: | |
| return _cyatomic_load_uint8_relaxed(obj) | |
| elif atomic_type_or_ptr_t is uint16_t: | |
| return _cyatomic_load_uint16_relaxed(obj) | |
| elif atomic_type_or_ptr_t is uint32_t: | |
| return _cyatomic_load_uint32_relaxed(obj) | |
| elif atomic_type_or_ptr_t is uint64_t: | |
| return _cyatomic_load_uint64_relaxed(obj) | |
| elif atomic_type_or_ptr_t is uintptr_t: | |
| return _cyatomic_load_uintptr_relaxed(obj) | |
| elif atomic_type_or_ptr_t is void: | |
| return _cyatomic_load_ptr_relaxed(obj) | |
| else: | |
| return _cyatomic_load_ssize_relaxed(obj) | |
| cdef inline atomic_type_or_ptr_t atomic_store(atomic_type_or_ptr_t *obj, atomic_type_or_store_ptr_t value) noexcept nogil: | |
| if atomic_type_or_ptr_t is int: | |
| return _cyatomic_store_int(obj, value) | |
| elif atomic_type_or_ptr_t is int8_t: | |
| return _cyatomic_store_int8(obj, value) | |
| elif atomic_type_or_ptr_t is int16_t: | |
| return _cyatomic_store_int16(obj, value) | |
| elif atomic_type_or_ptr_t is int32_t: | |
| return _cyatomic_store_int32(obj, value) | |
| elif atomic_type_or_ptr_t is int64_t: | |
| return _cyatomic_store_int64(obj, value) | |
| elif atomic_type_or_ptr_t is intptr_t: | |
| return _cyatomic_store_intptr(obj, value) | |
| elif atomic_type_or_ptr_t is uint8_t: | |
| return _cyatomic_store_uint8(obj, value) | |
| elif atomic_type_or_ptr_t is uint16_t: | |
| return _cyatomic_store_uint16(obj, value) | |
| elif atomic_type_or_ptr_t is uint32_t: | |
| return _cyatomic_store_uint32(obj, value) | |
| elif atomic_type_or_ptr_t is uint64_t: | |
| return _cyatomic_store_uint64(obj, value) | |
| elif atomic_type_or_ptr_t is uintptr_t: | |
| return _cyatomic_store_uintptr(obj, value) | |
| elif atomic_type_or_ptr_t is void: | |
| return _cyatomic_store_ptr(obj, value) | |
| else: | |
| return _cyatomic_store_ssize(obj, value) | |
| cdef inline atomic_type_or_ptr_t atomic_store_relaxed(atomic_type_or_ptr_t *obj, atomic_type_or_store_ptr_t value) noexcept nogil: | |
| if atomic_type_or_ptr_t is int: | |
| return _cyatomic_store_int_relaxed(obj, value) | |
| elif atomic_type_or_ptr_t is int8_t: | |
| return _cyatomic_store_int8_relaxed(obj, value) | |
| elif atomic_type_or_ptr_t is int16_t: | |
| return _cyatomic_store_int16_relaxed(obj, value) | |
| elif atomic_type_or_ptr_t is int32_t: | |
| return _cyatomic_store_int32_relaxed(obj, value) | |
| elif atomic_type_or_ptr_t is int64_t: | |
| return _cyatomic_store_int64_relaxed(obj, value) | |
| elif atomic_type_or_ptr_t is intptr_t: | |
| return _cyatomic_store_intptr_relaxed(obj, value) | |
| elif atomic_type_or_ptr_t is uint8_t: | |
| return _cyatomic_store_uint8_relaxed(obj, value) | |
| elif atomic_type_or_ptr_t is uint16_t: | |
| return _cyatomic_store_uint16_relaxed(obj, value) | |
| elif atomic_type_or_ptr_t is uint32_t: | |
| return _cyatomic_store_uint32_relaxed(obj, value) | |
| elif atomic_type_or_ptr_t is uint64_t: | |
| return _cyatomic_store_uint64_relaxed(obj, value) | |
| elif atomic_type_or_ptr_t is uintptr_t: | |
| return _cyatomic_store_uintptr_relaxed(obj, value) | |
| elif atomic_type_or_ptr_t is void: | |
| return _cyatomic_store_ptr_relaxed(obj, value) | |
| else: | |
| return _cyatomic_store_ssize_relaxed(obj, value) | |
| cdef inline atomic_type_or_store_ptr_t atomic_exchange( | |
| atomic_type_or_ptr_t *obj, | |
| atomic_type_or_store_ptr_t value | |
| ) noexcept nogil: | |
| if atomic_type_or_ptr_t is int: | |
| return _cyatomic_exchange_int(obj, value) | |
| elif atomic_type_or_ptr_t is int8_t: | |
| return _cyatomic_exchange_int8(obj, value) | |
| elif atomic_type_or_ptr_t is int16_t: | |
| return _cyatomic_exchange_int16(obj, value) | |
| elif atomic_type_or_ptr_t is int32_t: | |
| return _cyatomic_exchange_int32(obj, value) | |
| elif atomic_type_or_ptr_t is int64_t: | |
| return _cyatomic_exchange_int64(obj, value) | |
| elif atomic_type_or_ptr_t is intptr_t: | |
| return _cyatomic_exchange_intptr(obj, value) | |
| elif atomic_type_or_ptr_t is uint8_t: | |
| return _cyatomic_exchange_uint8(obj, value) | |
| elif atomic_type_or_ptr_t is uint16_t: | |
| return _cyatomic_exchange_uint16(obj, value) | |
| elif atomic_type_or_ptr_t is uint32_t: | |
| return _cyatomic_exchange_uint32(obj, value) | |
| elif atomic_type_or_ptr_t is uint64_t: | |
| return _cyatomic_exchange_uint64(obj, value) | |
| elif atomic_type_or_ptr_t is uintptr_t: | |
| return _cyatomic_exchange_uintptr(obj, value) | |
| elif atomic_type_or_ptr_t is void: | |
| return _cyatomic_exchange_ptr(obj, value) | |
| else: | |
| return _cyatomic_exchange_ssize(obj, value) | |
| cdef inline int atomic_compare_exchange( | |
| atomic_type_or_ptr_t *obj, | |
| atomic_type_or_ptr_t *expected, | |
| atomic_type_or_store_ptr_t desired | |
| ) noexcept nogil: | |
| if atomic_type_or_ptr_t is int: | |
| return _cyatomic_compare_exchange_int(obj, expected, desired) | |
| elif atomic_type_or_ptr_t is int8_t: | |
| return _cyatomic_compare_exchange_int8(obj, expected, desired) | |
| elif atomic_type_or_ptr_t is int16_t: | |
| return _cyatomic_compare_exchange_int16(obj, expected, desired) | |
| elif atomic_type_or_ptr_t is int32_t: | |
| return _cyatomic_compare_exchange_int32(obj, expected, desired) | |
| elif atomic_type_or_ptr_t is int64_t: | |
| return _cyatomic_compare_exchange_int64(obj, expected, desired) | |
| elif atomic_type_or_ptr_t is intptr_t: | |
| return _cyatomic_compare_exchange_intptr(obj, expected, desired) | |
| elif atomic_type_or_ptr_t is uint8_t: | |
| return _cyatomic_compare_exchange_uint8(obj, expected, desired) | |
| elif atomic_type_or_ptr_t is uint16_t: | |
| return _cyatomic_compare_exchange_uint16(obj, expected, desired) | |
| elif atomic_type_or_ptr_t is uint32_t: | |
| return _cyatomic_compare_exchange_uint32(obj, expected, desired) | |
| elif atomic_type_or_ptr_t is uint64_t: | |
| return _cyatomic_compare_exchange_uint64(obj, expected, desired) | |
| elif atomic_type_or_ptr_t is uintptr_t: | |
| return _cyatomic_compare_exchange_uintptr(obj, expected, desired) | |
| elif atomic_type_or_ptr_t is void: | |
| return _cyatomic_compare_exchange_ptr(obj, expected, <void*>desired) | |
| else: | |
| return _cyatomic_compare_exchange_ssize(obj, expected, desired) | |
| cdef inline atomic_type_t atomic_add(atomic_type_t *obj, atomic_type_t value) noexcept nogil: | |
| if atomic_type_t is int: | |
| return _cyatomic_add_int(obj, value) | |
| elif atomic_type_t is int8_t: | |
| return _cyatomic_add_int8(obj, value) | |
| elif atomic_type_t is int16_t: | |
| return _cyatomic_add_int16(obj, value) | |
| elif atomic_type_t is int32_t: | |
| return _cyatomic_add_int32(obj, value) | |
| elif atomic_type_t is int64_t: | |
| return _cyatomic_add_int64(obj, value) | |
| elif atomic_type_t is intptr_t: | |
| return _cyatomic_add_intptr(obj, value) | |
| elif atomic_type_t is uint8_t: | |
| return _cyatomic_add_uint8(obj, value) | |
| elif atomic_type_t is uint16_t: | |
| return _cyatomic_add_uint16(obj, value) | |
| elif atomic_type_t is uint32_t: | |
| return _cyatomic_add_uint32(obj, value) | |
| elif atomic_type_t is uint64_t: | |
| return _cyatomic_add_uint64(obj, value) | |
| elif atomic_type_t is uintptr_t: | |
| return _cyatomic_add_uintptr(obj, value) | |
| else: | |
| return _cyatomic_add_ssize(obj, value) | |
| cdef inline atomic_type_t atomic_and(atomic_type_t *obj, atomic_type_t value) noexcept nogil: | |
| if atomic_type_t is uint8_t: | |
| return _cyatomic_and_uint8(obj, value) | |
| elif atomic_type_t is uint16_t: | |
| return _cyatomic_and_uint16(obj, value) | |
| elif atomic_type_t is uint32_t: | |
| return _cyatomic_and_uint32(obj, value) | |
| elif atomic_type_t is uint64_t: | |
| return _cyatomic_and_uint64(obj, value) | |
| else: | |
| return _cyatomic_and_uintptr(obj, value) | |
| cdef inline atomic_type_t atomic_or(atomic_type_t *obj, atomic_type_t value) noexcept nogil: | |
| if atomic_type_t is uint8_t: | |
| return _cyatomic_or_uint8(obj, value) | |
| elif atomic_type_t is uint16_t: | |
| return _cyatomic_or_uint16(obj, value) | |
| elif atomic_type_t is uint32_t: | |
| return _cyatomic_or_uint32(obj, value) | |
| elif atomic_type_t is uint64_t: | |
| return _cyatomic_or_uint64(obj, value) | |
| else: | |
| return _cyatomic_or_uintptr(obj, value) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef __CYATOMICS_GCC_H__ | |
| #define __CYATOMICS_GCC_H__ | |
| // This file was modified from pyatomic_gcc.h | |
| // This is the implementation of Python atomic operations using GCC's built-in | |
| // functions that match the C+11 memory model. This implementation is preferred | |
| // for GCC compatible compilers, such as Clang. These functions are available | |
| // in GCC 4.8+ without needing to compile with --std=c11 or --std=gnu11. | |
| #include <stdatomic.h> | |
| #ifdef __cplusplus | |
| extern "C" { | |
| #endif | |
| // --- _cyatomic_add -------------------------------------------------------- | |
| static inline int | |
| _cyatomic_add_int(int *obj, int value) | |
| { return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline int8_t | |
| _cyatomic_add_int8(int8_t *obj, int8_t value) | |
| { return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline int16_t | |
| _cyatomic_add_int16(int16_t *obj, int16_t value) | |
| { return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline int32_t | |
| _cyatomic_add_int32(int32_t *obj, int32_t value) | |
| { return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline int64_t | |
| _cyatomic_add_int64(int64_t *obj, int64_t value) | |
| { return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline intptr_t | |
| _cyatomic_add_intptr(intptr_t *obj, intptr_t value) | |
| { return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline unsigned int | |
| _cyatomic_add_uint(unsigned int *obj, unsigned int value) | |
| { return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint8_t | |
| _cyatomic_add_uint8(uint8_t *obj, uint8_t value) | |
| { return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint16_t | |
| _cyatomic_add_uint16(uint16_t *obj, uint16_t value) | |
| { return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint32_t | |
| _cyatomic_add_uint32(uint32_t *obj, uint32_t value) | |
| { return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint64_t | |
| _cyatomic_add_uint64(uint64_t *obj, uint64_t value) | |
| { return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uintptr_t | |
| _cyatomic_add_uintptr(uintptr_t *obj, uintptr_t value) | |
| { return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline Py_ssize_t | |
| _cyatomic_add_ssize(Py_ssize_t *obj, Py_ssize_t value) | |
| { return __atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST); } | |
| // --- _cyatomic_compare_exchange ------------------------------------------- | |
| static inline int | |
| _cyatomic_compare_exchange_int(int *obj, int *expected, int desired) | |
| { return __atomic_compare_exchange_n(obj, expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| static inline int | |
| _cyatomic_compare_exchange_int8(int8_t *obj, int8_t *expected, int8_t desired) | |
| { return __atomic_compare_exchange_n(obj, expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| static inline int | |
| _cyatomic_compare_exchange_int16(int16_t *obj, int16_t *expected, int16_t desired) | |
| { return __atomic_compare_exchange_n(obj, expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| static inline int | |
| _cyatomic_compare_exchange_int32(int32_t *obj, int32_t *expected, int32_t desired) | |
| { return __atomic_compare_exchange_n(obj, expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| static inline int | |
| _cyatomic_compare_exchange_int64(int64_t *obj, int64_t *expected, int64_t desired) | |
| { return __atomic_compare_exchange_n(obj, expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| static inline int | |
| _cyatomic_compare_exchange_intptr(intptr_t *obj, intptr_t *expected, intptr_t desired) | |
| { return __atomic_compare_exchange_n(obj, expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| static inline int | |
| _cyatomic_compare_exchange_uint(unsigned int *obj, unsigned int *expected, unsigned int desired) | |
| { return __atomic_compare_exchange_n(obj, expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| static inline int | |
| _cyatomic_compare_exchange_uint8(uint8_t *obj, uint8_t *expected, uint8_t desired) | |
| { return __atomic_compare_exchange_n(obj, expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| static inline int | |
| _cyatomic_compare_exchange_uint16(uint16_t *obj, uint16_t *expected, uint16_t desired) | |
| { return __atomic_compare_exchange_n(obj, expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| static inline int | |
| _cyatomic_compare_exchange_uint32(uint32_t *obj, uint32_t *expected, uint32_t desired) | |
| { return __atomic_compare_exchange_n(obj, expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| static inline int | |
| _cyatomic_compare_exchange_uint64(uint64_t *obj, uint64_t *expected, uint64_t desired) | |
| { return __atomic_compare_exchange_n(obj, expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| static inline int | |
| _cyatomic_compare_exchange_uintptr(uintptr_t *obj, uintptr_t *expected, uintptr_t desired) | |
| { return __atomic_compare_exchange_n(obj, expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| static inline int | |
| _cyatomic_compare_exchange_ssize(Py_ssize_t *obj, Py_ssize_t *expected, Py_ssize_t desired) | |
| { return __atomic_compare_exchange_n(obj, expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| static inline int | |
| _cyatomic_compare_exchange_ptr(void *obj, void *expected, void *desired) | |
| { return __atomic_compare_exchange_n((void **)obj, (void **)expected, desired, 0, | |
| __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } | |
| // --- _cyatomic_exchange --------------------------------------------------- | |
| static inline int | |
| _cyatomic_exchange_int(int *obj, int value) | |
| { return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline int8_t | |
| _cyatomic_exchange_int8(int8_t *obj, int8_t value) | |
| { return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline int16_t | |
| _cyatomic_exchange_int16(int16_t *obj, int16_t value) | |
| { return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline int32_t | |
| _cyatomic_exchange_int32(int32_t *obj, int32_t value) | |
| { return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline int64_t | |
| _cyatomic_exchange_int64(int64_t *obj, int64_t value) | |
| { return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline intptr_t | |
| _cyatomic_exchange_intptr(intptr_t *obj, intptr_t value) | |
| { return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline unsigned int | |
| _cyatomic_exchange_uint(unsigned int *obj, unsigned int value) | |
| { return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint8_t | |
| _cyatomic_exchange_uint8(uint8_t *obj, uint8_t value) | |
| { return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint16_t | |
| _cyatomic_exchange_uint16(uint16_t *obj, uint16_t value) | |
| { return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint32_t | |
| _cyatomic_exchange_uint32(uint32_t *obj, uint32_t value) | |
| { return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint64_t | |
| _cyatomic_exchange_uint64(uint64_t *obj, uint64_t value) | |
| { return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uintptr_t | |
| _cyatomic_exchange_uintptr(uintptr_t *obj, uintptr_t value) | |
| { return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline Py_ssize_t | |
| _cyatomic_exchange_ssize(Py_ssize_t *obj, Py_ssize_t value) | |
| { return __atomic_exchange_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void * | |
| _cyatomic_exchange_ptr(void *obj, void *value) | |
| { return __atomic_exchange_n((void **)obj, value, __ATOMIC_SEQ_CST); } | |
| // --- _cyatomic_and -------------------------------------------------------- | |
| static inline uint8_t | |
| _cyatomic_and_uint8(uint8_t *obj, uint8_t value) | |
| { return __atomic_fetch_and(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint16_t | |
| _cyatomic_and_uint16(uint16_t *obj, uint16_t value) | |
| { return __atomic_fetch_and(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint32_t | |
| _cyatomic_and_uint32(uint32_t *obj, uint32_t value) | |
| { return __atomic_fetch_and(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint64_t | |
| _cyatomic_and_uint64(uint64_t *obj, uint64_t value) | |
| { return __atomic_fetch_and(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uintptr_t | |
| _cyatomic_and_uintptr(uintptr_t *obj, uintptr_t value) | |
| { return __atomic_fetch_and(obj, value, __ATOMIC_SEQ_CST); } | |
| // --- _cyatomic_or --------------------------------------------------------- | |
| static inline uint8_t | |
| _cyatomic_or_uint8(uint8_t *obj, uint8_t value) | |
| { return __atomic_fetch_or(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint16_t | |
| _cyatomic_or_uint16(uint16_t *obj, uint16_t value) | |
| { return __atomic_fetch_or(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint32_t | |
| _cyatomic_or_uint32(uint32_t *obj, uint32_t value) | |
| { return __atomic_fetch_or(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uint64_t | |
| _cyatomic_or_uint64(uint64_t *obj, uint64_t value) | |
| { return __atomic_fetch_or(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline uintptr_t | |
| _cyatomic_or_uintptr(uintptr_t *obj, uintptr_t value) | |
| { return __atomic_fetch_or(obj, value, __ATOMIC_SEQ_CST); } | |
| // --- _cyatomic_load ------------------------------------------------------- | |
| static inline int | |
| _cyatomic_load_int(const int *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } | |
| static inline int8_t | |
| _cyatomic_load_int8(const int8_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } | |
| static inline int16_t | |
| _cyatomic_load_int16(const int16_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } | |
| static inline int32_t | |
| _cyatomic_load_int32(const int32_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } | |
| static inline int64_t | |
| _cyatomic_load_int64(const int64_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } | |
| static inline intptr_t | |
| _cyatomic_load_intptr(const intptr_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } | |
| static inline uint8_t | |
| _cyatomic_load_uint8(const uint8_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } | |
| static inline uint16_t | |
| _cyatomic_load_uint16(const uint16_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } | |
| static inline uint32_t | |
| _cyatomic_load_uint32(const uint32_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } | |
| static inline uint64_t | |
| _cyatomic_load_uint64(const uint64_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } | |
| static inline uintptr_t | |
| _cyatomic_load_uintptr(const uintptr_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } | |
| static inline unsigned int | |
| _cyatomic_load_uint(const unsigned int *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } | |
| static inline Py_ssize_t | |
| _cyatomic_load_ssize(const Py_ssize_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_SEQ_CST); } | |
| static inline void * | |
| _cyatomic_load_ptr(const void *obj) | |
| { return (void *)__atomic_load_n((void * const *)obj, __ATOMIC_SEQ_CST); } | |
| // --- _cyatomic_load_relaxed ----------------------------------------------- | |
| static inline int | |
| _cyatomic_load_int_relaxed(const int *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline char | |
| _cyatomic_load_char_relaxed(const char *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline unsigned char | |
| _cyatomic_load_uchar_relaxed(const unsigned char *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline short | |
| _cyatomic_load_short_relaxed(const short *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline unsigned short | |
| _cyatomic_load_ushort_relaxed(const unsigned short *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline long | |
| _cyatomic_load_long_relaxed(const long *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline float | |
| _cyatomic_load_float_relaxed(const float *obj) | |
| { float ret; __atomic_load(obj, &ret, __ATOMIC_RELAXED); return ret; } | |
| static inline double | |
| _cyatomic_load_double_relaxed(const double *obj) | |
| { double ret; __atomic_load(obj, &ret, __ATOMIC_RELAXED); return ret; } | |
| static inline int8_t | |
| _cyatomic_load_int8_relaxed(const int8_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline int16_t | |
| _cyatomic_load_int16_relaxed(const int16_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline int32_t | |
| _cyatomic_load_int32_relaxed(const int32_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline int64_t | |
| _cyatomic_load_int64_relaxed(const int64_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline intptr_t | |
| _cyatomic_load_intptr_relaxed(const intptr_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline uint8_t | |
| _cyatomic_load_uint8_relaxed(const uint8_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline uint16_t | |
| _cyatomic_load_uint16_relaxed(const uint16_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline uint32_t | |
| _cyatomic_load_uint32_relaxed(const uint32_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline uint64_t | |
| _cyatomic_load_uint64_relaxed(const uint64_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline uintptr_t | |
| _cyatomic_load_uintptr_relaxed(const uintptr_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline unsigned int | |
| _cyatomic_load_uint_relaxed(const unsigned int *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline Py_ssize_t | |
| _cyatomic_load_ssize_relaxed(const Py_ssize_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline void * | |
| _cyatomic_load_ptr_relaxed(const void *obj) | |
| { return (void *)__atomic_load_n((void * const *)obj, __ATOMIC_RELAXED); } | |
| static inline unsigned long long | |
| _cyatomic_load_ullong_relaxed(const unsigned long long *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| static inline long long | |
| _cyatomic_load_llong_relaxed(const long long *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_RELAXED); } | |
| // --- _cyatomic_store ------------------------------------------------------ | |
| static inline void | |
| _cyatomic_store_int(int *obj, int value) | |
| { __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_store_int8(int8_t *obj, int8_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_store_int16(int16_t *obj, int16_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_store_int32(int32_t *obj, int32_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_store_int64(int64_t *obj, int64_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_store_intptr(intptr_t *obj, intptr_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_store_uint8(uint8_t *obj, uint8_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_store_uint16(uint16_t *obj, uint16_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_store_uint32(uint32_t *obj, uint32_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_store_uint64(uint64_t *obj, uint64_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_store_uintptr(uintptr_t *obj, uintptr_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_store_uint(unsigned int *obj, unsigned int value) | |
| { __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_store_ptr(void *obj, void *value) | |
| { __atomic_store_n((void **)obj, value, __ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_store_ssize(Py_ssize_t *obj, Py_ssize_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_SEQ_CST); } | |
| // --- _cyatomic_store_relaxed ---------------------------------------------- | |
| static inline void | |
| _cyatomic_store_int_relaxed(int *obj, int value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_int8_relaxed(int8_t *obj, int8_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_int16_relaxed(int16_t *obj, int16_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_int32_relaxed(int32_t *obj, int32_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_int64_relaxed(int64_t *obj, int64_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_intptr_relaxed(intptr_t *obj, intptr_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_uint8_relaxed(uint8_t *obj, uint8_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_uint16_relaxed(uint16_t *obj, uint16_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_uint32_relaxed(uint32_t *obj, uint32_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_uint64_relaxed(uint64_t *obj, uint64_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_uintptr_relaxed(uintptr_t *obj, uintptr_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_uint_relaxed(unsigned int *obj, unsigned int value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_ptr_relaxed(void *obj, void *value) | |
| { __atomic_store_n((void **)obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_ssize_relaxed(Py_ssize_t *obj, Py_ssize_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_ullong_relaxed(unsigned long long *obj, | |
| unsigned long long value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_char_relaxed(char *obj, char value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_uchar_relaxed(unsigned char *obj, unsigned char value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_short_relaxed(short *obj, short value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_ushort_relaxed(unsigned short *obj, unsigned short value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_long_relaxed(long *obj, long value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_float_relaxed(float *obj, float value) | |
| { __atomic_store(obj, &value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_double_relaxed(double *obj, double value) | |
| { __atomic_store(obj, &value, __ATOMIC_RELAXED); } | |
| static inline void | |
| _cyatomic_store_llong_relaxed(long long *obj, long long value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELAXED); } | |
| // --- _cyatomic_load_ptr_acquire / _cyatomic_store_ptr_release ------------ | |
| static inline void * | |
| _cyatomic_load_ptr_acquire(const void *obj) | |
| { return (void *)__atomic_load_n((void * const *)obj, __ATOMIC_ACQUIRE); } | |
| static inline uintptr_t | |
| _cyatomic_load_uintptr_acquire(const uintptr_t *obj) | |
| { return (uintptr_t)__atomic_load_n(obj, __ATOMIC_ACQUIRE); } | |
| static inline void | |
| _cyatomic_store_ptr_release(void *obj, void *value) | |
| { __atomic_store_n((void **)obj, value, __ATOMIC_RELEASE); } | |
| static inline void | |
| _cyatomic_store_uintptr_release(uintptr_t *obj, uintptr_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELEASE); } | |
| static inline void | |
| _cyatomic_store_int_release(int *obj, int value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELEASE); } | |
| static inline void | |
| _cyatomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELEASE); } | |
| static inline int | |
| _cyatomic_load_int_acquire(const int *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_ACQUIRE); } | |
| static inline void | |
| _cyatomic_store_uint32_release(uint32_t *obj, uint32_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELEASE); } | |
| static inline void | |
| _cyatomic_store_uint64_release(uint64_t *obj, uint64_t value) | |
| { __atomic_store_n(obj, value, __ATOMIC_RELEASE); } | |
| static inline uint64_t | |
| _cyatomic_load_uint64_acquire(const uint64_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_ACQUIRE); } | |
| static inline uint32_t | |
| _cyatomic_load_uint32_acquire(const uint32_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_ACQUIRE); } | |
| static inline Py_ssize_t | |
| _cyatomic_load_ssize_acquire(const Py_ssize_t *obj) | |
| { return __atomic_load_n(obj, __ATOMIC_ACQUIRE); } | |
| // --- _cyatomic_fence ------------------------------------------------------ | |
| static inline void | |
| _cyatomic_fence_seq_cst(void) | |
| { __atomic_thread_fence(__ATOMIC_SEQ_CST); } | |
| static inline void | |
| _cyatomic_fence_acquire(void) | |
| { __atomic_thread_fence(__ATOMIC_ACQUIRE); } | |
| static inline void | |
| _cyatomic_fence_release(void) | |
| { __atomic_thread_fence(__ATOMIC_RELEASE); } | |
| #ifdef __cplusplus | |
| } | |
| #endif | |
| #endif // __CYATOMICS_GCC_H__ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef __CYATOMICS_STD_H__ | |
| #define __CYATOMICS_STD_H__ | |
| // This file was modified from pyatomic_std.h as mostly a rename to prevent redefinitions. | |
| // This is the implementation of Python atomic operations using C++11 or C11 | |
| // atomics. Note that the pyatomic_gcc.h implementation is preferred for GCC | |
| // compatible compilers, even if they support C++11 atomics. | |
| #include <Python.h> | |
| #ifdef __cplusplus | |
| extern "C++" { | |
| # include <atomic> | |
| } | |
| # define _Py_USING_STD using namespace std | |
| # define _Atomic(tp) atomic<tp> | |
| #else | |
| # define _Py_USING_STD | |
| # include <stdatomic.h> | |
| #endif | |
| // --- _cyatomic_add -------------------------------------------------------- | |
| static inline int | |
| _cyatomic_add_int(int *obj, int value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_add((_Atomic(int)*)obj, value); | |
| } | |
| static inline int8_t | |
| _cyatomic_add_int8(int8_t *obj, int8_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_add((_Atomic(int8_t)*)obj, value); | |
| } | |
| static inline int16_t | |
| _cyatomic_add_int16(int16_t *obj, int16_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_add((_Atomic(int16_t)*)obj, value); | |
| } | |
| static inline int32_t | |
| _cyatomic_add_int32(int32_t *obj, int32_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_add((_Atomic(int32_t)*)obj, value); | |
| } | |
| static inline int64_t | |
| _cyatomic_add_int64(int64_t *obj, int64_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_add((_Atomic(int64_t)*)obj, value); | |
| } | |
| static inline intptr_t | |
| _cyatomic_add_intptr(intptr_t *obj, intptr_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_add((_Atomic(intptr_t)*)obj, value); | |
| } | |
| static inline unsigned int | |
| _cyatomic_add_uint(unsigned int *obj, unsigned int value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_add((_Atomic(unsigned int)*)obj, value); | |
| } | |
| static inline uint8_t | |
| _cyatomic_add_uint8(uint8_t *obj, uint8_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_add((_Atomic(uint8_t)*)obj, value); | |
| } | |
| static inline uint16_t | |
| _cyatomic_add_uint16(uint16_t *obj, uint16_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_add((_Atomic(uint16_t)*)obj, value); | |
| } | |
| static inline uint32_t | |
| _cyatomic_add_uint32(uint32_t *obj, uint32_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_add((_Atomic(uint32_t)*)obj, value); | |
| } | |
| static inline uint64_t | |
| _cyatomic_add_uint64(uint64_t *obj, uint64_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_add((_Atomic(uint64_t)*)obj, value); | |
| } | |
| static inline uintptr_t | |
| _cyatomic_add_uintptr(uintptr_t *obj, uintptr_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_add((_Atomic(uintptr_t)*)obj, value); | |
| } | |
| static inline Py_ssize_t | |
| _cyatomic_add_ssize(Py_ssize_t *obj, Py_ssize_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_add((_Atomic(Py_ssize_t)*)obj, value); | |
| } | |
| // --- _cyatomic_compare_exchange ------------------------------------------- | |
| static inline int | |
| _cyatomic_compare_exchange_int(int *obj, int *expected, int desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(int)*)obj, | |
| expected, desired); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_int8(int8_t *obj, int8_t *expected, int8_t desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(int8_t)*)obj, | |
| expected, desired); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_int16(int16_t *obj, int16_t *expected, int16_t desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(int16_t)*)obj, | |
| expected, desired); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_int32(int32_t *obj, int32_t *expected, int32_t desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(int32_t)*)obj, | |
| expected, desired); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_int64(int64_t *obj, int64_t *expected, int64_t desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(int64_t)*)obj, | |
| expected, desired); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_intptr(intptr_t *obj, intptr_t *expected, intptr_t desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(intptr_t)*)obj, | |
| expected, desired); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_uint(unsigned int *obj, unsigned int *expected, unsigned int desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(unsigned int)*)obj, | |
| expected, desired); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_uint8(uint8_t *obj, uint8_t *expected, uint8_t desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(uint8_t)*)obj, | |
| expected, desired); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_uint16(uint16_t *obj, uint16_t *expected, uint16_t desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(uint16_t)*)obj, | |
| expected, desired); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_uint32(uint32_t *obj, uint32_t *expected, uint32_t desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(uint32_t)*)obj, | |
| expected, desired); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_uint64(uint64_t *obj, uint64_t *expected, uint64_t desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(uint64_t)*)obj, | |
| expected, desired); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_uintptr(uintptr_t *obj, uintptr_t *expected, uintptr_t desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(uintptr_t)*)obj, | |
| expected, desired); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_ssize(Py_ssize_t *obj, Py_ssize_t *expected, Py_ssize_t desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(Py_ssize_t)*)obj, | |
| expected, desired); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_ptr(void *obj, void *expected, void *desired) | |
| { | |
| _Py_USING_STD; | |
| return atomic_compare_exchange_strong((_Atomic(void *)*)obj, | |
| (void **)expected, desired); | |
| } | |
| // --- _cyatomic_exchange --------------------------------------------------- | |
| static inline int | |
| _cyatomic_exchange_int(int *obj, int value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(int)*)obj, value); | |
| } | |
| static inline int8_t | |
| _cyatomic_exchange_int8(int8_t *obj, int8_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(int8_t)*)obj, value); | |
| } | |
| static inline int16_t | |
| _cyatomic_exchange_int16(int16_t *obj, int16_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(int16_t)*)obj, value); | |
| } | |
| static inline int32_t | |
| _cyatomic_exchange_int32(int32_t *obj, int32_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(int32_t)*)obj, value); | |
| } | |
| static inline int64_t | |
| _cyatomic_exchange_int64(int64_t *obj, int64_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(int64_t)*)obj, value); | |
| } | |
| static inline intptr_t | |
| _cyatomic_exchange_intptr(intptr_t *obj, intptr_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(intptr_t)*)obj, value); | |
| } | |
| static inline unsigned int | |
| _cyatomic_exchange_uint(unsigned int *obj, unsigned int value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(unsigned int)*)obj, value); | |
| } | |
| static inline uint8_t | |
| _cyatomic_exchange_uint8(uint8_t *obj, uint8_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(uint8_t)*)obj, value); | |
| } | |
| static inline uint16_t | |
| _cyatomic_exchange_uint16(uint16_t *obj, uint16_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(uint16_t)*)obj, value); | |
| } | |
| static inline uint32_t | |
| _cyatomic_exchange_uint32(uint32_t *obj, uint32_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(uint32_t)*)obj, value); | |
| } | |
| static inline uint64_t | |
| _cyatomic_exchange_uint64(uint64_t *obj, uint64_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(uint64_t)*)obj, value); | |
| } | |
| static inline uintptr_t | |
| _cyatomic_exchange_uintptr(uintptr_t *obj, uintptr_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(uintptr_t)*)obj, value); | |
| } | |
| static inline Py_ssize_t | |
| _cyatomic_exchange_ssize(Py_ssize_t *obj, Py_ssize_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(Py_ssize_t)*)obj, value); | |
| } | |
| static inline void* | |
| _cyatomic_exchange_ptr(void *obj, void *value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_exchange((_Atomic(void *)*)obj, value); | |
| } | |
| // --- _cyatomic_and -------------------------------------------------------- | |
| static inline uint8_t | |
| _cyatomic_and_uint8(uint8_t *obj, uint8_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_and((_Atomic(uint8_t)*)obj, value); | |
| } | |
| static inline uint16_t | |
| _cyatomic_and_uint16(uint16_t *obj, uint16_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_and((_Atomic(uint16_t)*)obj, value); | |
| } | |
| static inline uint32_t | |
| _cyatomic_and_uint32(uint32_t *obj, uint32_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_and((_Atomic(uint32_t)*)obj, value); | |
| } | |
| static inline uint64_t | |
| _cyatomic_and_uint64(uint64_t *obj, uint64_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_and((_Atomic(uint64_t)*)obj, value); | |
| } | |
| static inline uintptr_t | |
| _cyatomic_and_uintptr(uintptr_t *obj, uintptr_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_and((_Atomic(uintptr_t)*)obj, value); | |
| } | |
| // --- _cyatomic_or --------------------------------------------------------- | |
| static inline uint8_t | |
| _cyatomic_or_uint8(uint8_t *obj, uint8_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_or((_Atomic(uint8_t)*)obj, value); | |
| } | |
| static inline uint16_t | |
| _cyatomic_or_uint16(uint16_t *obj, uint16_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_or((_Atomic(uint16_t)*)obj, value); | |
| } | |
| static inline uint32_t | |
| _cyatomic_or_uint32(uint32_t *obj, uint32_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_or((_Atomic(uint32_t)*)obj, value); | |
| } | |
| static inline uint64_t | |
| _cyatomic_or_uint64(uint64_t *obj, uint64_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_or((_Atomic(uint64_t)*)obj, value); | |
| } | |
| static inline uintptr_t | |
| _cyatomic_or_uintptr(uintptr_t *obj, uintptr_t value) | |
| { | |
| _Py_USING_STD; | |
| return atomic_fetch_or((_Atomic(uintptr_t)*)obj, value); | |
| } | |
| // --- _cyatomic_load ------------------------------------------------------- | |
| static inline int | |
| _cyatomic_load_int(const int *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(int)*)obj); | |
| } | |
| static inline int8_t | |
| _cyatomic_load_int8(const int8_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(int8_t)*)obj); | |
| } | |
| static inline int16_t | |
| _cyatomic_load_int16(const int16_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(int16_t)*)obj); | |
| } | |
| static inline int32_t | |
| _cyatomic_load_int32(const int32_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(int32_t)*)obj); | |
| } | |
| static inline int64_t | |
| _cyatomic_load_int64(const int64_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(int64_t)*)obj); | |
| } | |
| static inline intptr_t | |
| _cyatomic_load_intptr(const intptr_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(intptr_t)*)obj); | |
| } | |
| static inline uint8_t | |
| _cyatomic_load_uint8(const uint8_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(uint8_t)*)obj); | |
| } | |
| static inline uint16_t | |
| _cyatomic_load_uint16(const uint16_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(uint32_t)*)obj); | |
| } | |
| static inline uint32_t | |
| _cyatomic_load_uint32(const uint32_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(uint32_t)*)obj); | |
| } | |
| static inline uint64_t | |
| _cyatomic_load_uint64(const uint64_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(uint64_t)*)obj); | |
| } | |
| static inline uintptr_t | |
| _cyatomic_load_uintptr(const uintptr_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(uintptr_t)*)obj); | |
| } | |
| static inline unsigned int | |
| _cyatomic_load_uint(const unsigned int *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(unsigned int)*)obj); | |
| } | |
| static inline Py_ssize_t | |
| _cyatomic_load_ssize(const Py_ssize_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(Py_ssize_t)*)obj); | |
| } | |
| static inline void* | |
| _cyatomic_load_ptr(const void *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load((const _Atomic(void*)*)obj); | |
| } | |
| // --- _cyatomic_load_relaxed ----------------------------------------------- | |
| static inline int | |
| _cyatomic_load_int_relaxed(const int *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(int)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline char | |
| _cyatomic_load_char_relaxed(const char *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(char)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline unsigned char | |
| _cyatomic_load_uchar_relaxed(const unsigned char *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(unsigned char)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline short | |
| _cyatomic_load_short_relaxed(const short *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(short)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline unsigned short | |
| _cyatomic_load_ushort_relaxed(const unsigned short *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(unsigned short)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline long | |
| _cyatomic_load_long_relaxed(const long *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(long)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline float | |
| _cyatomic_load_float_relaxed(const float *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(float)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline double | |
| _cyatomic_load_double_relaxed(const double *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(double)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline int8_t | |
| _cyatomic_load_int8_relaxed(const int8_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(int8_t)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline int16_t | |
| _cyatomic_load_int16_relaxed(const int16_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(int16_t)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline int32_t | |
| _cyatomic_load_int32_relaxed(const int32_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(int32_t)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline int64_t | |
| _cyatomic_load_int64_relaxed(const int64_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(int64_t)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline intptr_t | |
| _cyatomic_load_intptr_relaxed(const intptr_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(intptr_t)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline uint8_t | |
| _cyatomic_load_uint8_relaxed(const uint8_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(uint8_t)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline uint16_t | |
| _cyatomic_load_uint16_relaxed(const uint16_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(uint16_t)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline uint32_t | |
| _cyatomic_load_uint32_relaxed(const uint32_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(uint32_t)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline uint64_t | |
| _cyatomic_load_uint64_relaxed(const uint64_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(uint64_t)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline uintptr_t | |
| _cyatomic_load_uintptr_relaxed(const uintptr_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(uintptr_t)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline unsigned int | |
| _cyatomic_load_uint_relaxed(const unsigned int *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(unsigned int)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline Py_ssize_t | |
| _cyatomic_load_ssize_relaxed(const Py_ssize_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(Py_ssize_t)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline void* | |
| _cyatomic_load_ptr_relaxed(const void *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(void*)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline unsigned long long | |
| _cyatomic_load_ullong_relaxed(const unsigned long long *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(unsigned long long)*)obj, | |
| memory_order_relaxed); | |
| } | |
| static inline long long | |
| _cyatomic_load_llong_relaxed(const long long *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(long long)*)obj, | |
| memory_order_relaxed); | |
| } | |
| // --- _cyatomic_store ------------------------------------------------------ | |
| static inline void | |
| _cyatomic_store_int(int *obj, int value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(int)*)obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_int8(int8_t *obj, int8_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(int8_t)*)obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_int16(int16_t *obj, int16_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(int16_t)*)obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_int32(int32_t *obj, int32_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(int32_t)*)obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_int64(int64_t *obj, int64_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(int64_t)*)obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_intptr(intptr_t *obj, intptr_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(intptr_t)*)obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_uint8(uint8_t *obj, uint8_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(uint8_t)*)obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_uint16(uint16_t *obj, uint16_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(uint16_t)*)obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_uint32(uint32_t *obj, uint32_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(uint32_t)*)obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_uint64(uint64_t *obj, uint64_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(uint64_t)*)obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_uintptr(uintptr_t *obj, uintptr_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(uintptr_t)*)obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_uint(unsigned int *obj, unsigned int value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(unsigned int)*)obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_ptr(void *obj, void *value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(void*)*)obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_ssize(Py_ssize_t *obj, Py_ssize_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store((_Atomic(Py_ssize_t)*)obj, value); | |
| } | |
| // --- _cyatomic_store_relaxed ---------------------------------------------- | |
| static inline void | |
| _cyatomic_store_int_relaxed(int *obj, int value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(int)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_int8_relaxed(int8_t *obj, int8_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(int8_t)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_int16_relaxed(int16_t *obj, int16_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(int16_t)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_int32_relaxed(int32_t *obj, int32_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(int32_t)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_int64_relaxed(int64_t *obj, int64_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(int64_t)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_intptr_relaxed(intptr_t *obj, intptr_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(intptr_t)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_uint8_relaxed(uint8_t *obj, uint8_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(uint8_t)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_uint16_relaxed(uint16_t *obj, uint16_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(uint16_t)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_uint32_relaxed(uint32_t *obj, uint32_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(uint32_t)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_uint64_relaxed(uint64_t *obj, uint64_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(uint64_t)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_uintptr_relaxed(uintptr_t *obj, uintptr_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(uintptr_t)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_uint_relaxed(unsigned int *obj, unsigned int value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(unsigned int)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_ptr_relaxed(void *obj, void *value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(void*)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_ssize_relaxed(Py_ssize_t *obj, Py_ssize_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(Py_ssize_t)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_ullong_relaxed(unsigned long long *obj, | |
| unsigned long long value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(unsigned long long)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_char_relaxed(char *obj, char value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(char)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_uchar_relaxed(unsigned char *obj, unsigned char value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(unsigned char)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_short_relaxed(short *obj, short value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(short)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_ushort_relaxed(unsigned short *obj, unsigned short value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(unsigned short)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_uint_release(unsigned int *obj, unsigned int value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(unsigned int)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_long_relaxed(long *obj, long value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(long)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_float_relaxed(float *obj, float value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(float)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_double_relaxed(double *obj, double value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(double)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| static inline void | |
| _cyatomic_store_llong_relaxed(long long *obj, long long value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(long long)*)obj, value, | |
| memory_order_relaxed); | |
| } | |
| // --- _cyatomic_load_ptr_acquire / _cyatomic_store_ptr_release ------------ | |
| static inline void * | |
| _cyatomic_load_ptr_acquire(const void *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(void*)*)obj, | |
| memory_order_acquire); | |
| } | |
| static inline uintptr_t | |
| _cyatomic_load_uintptr_acquire(const uintptr_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(uintptr_t)*)obj, | |
| memory_order_acquire); | |
| } | |
| static inline void | |
| _cyatomic_store_ptr_release(void *obj, void *value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(void*)*)obj, value, | |
| memory_order_release); | |
| } | |
| static inline void | |
| _cyatomic_store_uintptr_release(uintptr_t *obj, uintptr_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(uintptr_t)*)obj, value, | |
| memory_order_release); | |
| } | |
| static inline void | |
| _cyatomic_store_int_release(int *obj, int value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(int)*)obj, value, | |
| memory_order_release); | |
| } | |
| static inline void | |
| _cyatomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(Py_ssize_t)*)obj, value, | |
| memory_order_release); | |
| } | |
| static inline int | |
| _cyatomic_load_int_acquire(const int *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(int)*)obj, | |
| memory_order_acquire); | |
| } | |
| static inline void | |
| _cyatomic_store_uint32_release(uint32_t *obj, uint32_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(uint32_t)*)obj, value, | |
| memory_order_release); | |
| } | |
| static inline void | |
| _cyatomic_store_uint64_release(uint64_t *obj, uint64_t value) | |
| { | |
| _Py_USING_STD; | |
| atomic_store_explicit((_Atomic(uint64_t)*)obj, value, | |
| memory_order_release); | |
| } | |
| static inline uint64_t | |
| _cyatomic_load_uint64_acquire(const uint64_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(uint64_t)*)obj, | |
| memory_order_acquire); | |
| } | |
| static inline uint32_t | |
| _cyatomic_load_uint32_acquire(const uint32_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(uint32_t)*)obj, | |
| memory_order_acquire); | |
| } | |
| static inline Py_ssize_t | |
| _cyatomic_load_ssize_acquire(const Py_ssize_t *obj) | |
| { | |
| _Py_USING_STD; | |
| return atomic_load_explicit((const _Atomic(Py_ssize_t)*)obj, | |
| memory_order_acquire); | |
| } | |
| // --- _cyatomic_fence ------------------------------------------------------ | |
| static inline void | |
| _cyatomic_fence_seq_cst(void) | |
| { | |
| _Py_USING_STD; | |
| atomic_thread_fence(memory_order_seq_cst); | |
| } | |
| static inline void | |
| _cyatomic_fence_acquire(void) | |
| { | |
| _Py_USING_STD; | |
| atomic_thread_fence(memory_order_acquire); | |
| } | |
| static inline void | |
| _cyatomic_fence_release(void) | |
| { | |
| _Py_USING_STD; | |
| atomic_thread_fence(memory_order_release); | |
| } | |
| #endif // __CYATOMICS_STD_H__ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef __CYATOMICS_H__ | |
| #define __CYATOMICS_H__ | |
| #ifdef __cplusplus | |
| extern "C" { | |
| #endif | |
| // This file was renamed to prevent overlapping with the Python verison. | |
| // we use these files for older versions of python mainly so | |
| // that we have backwards compatability for low level C atomic-like | |
| // types which are useful in low level implementations that | |
| // don't require the GIL. | |
| // This header provides cross-platform low-level atomic operations | |
| // similar to C11 atomics. | |
| // | |
| // Operations are sequentially consistent unless they have a suffix indicating | |
| // otherwise. If in doubt, prefer the sequentially consistent operations. | |
| // | |
| // The "_relaxed" suffix for load and store operations indicates the "relaxed" | |
| // memory order. They don't provide synchronization, but (roughly speaking) | |
| // guarantee somewhat sane behavior for races instead of undefined behavior. | |
| // In practice, they correspond to "normal" hardware load and store | |
| // instructions, so they are almost as inexpensive as plain loads and stores | |
| // in C. | |
| // | |
| // Note that atomic read-modify-write operations like _cyatomic_add_* return | |
| // the previous value of the atomic variable, not the new value. | |
| // | |
| // See https://en.cppreference.com/w/c/atomic for more information on C11 | |
| // atomics. | |
| // See https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2055r0.pdf | |
| // "A Relaxed Guide to memory_order_relaxed" for discussion of and common usage | |
| // or relaxed atomics. | |
| // | |
| // Functions with pseudo Python code: | |
| // | |
| // def _cyatomic_load(obj): | |
| // return obj # sequential consistency | |
| // | |
| // def _cyatomic_load_relaxed(obj): | |
| // return obj # relaxed consistency | |
| // | |
| // def _cyatomic_store(obj, value): | |
| // obj = value # sequential consistency | |
| // | |
| // def _cyatomic_store_relaxed(obj, value): | |
| // obj = value # relaxed consistency | |
| // | |
| // def _cyatomic_exchange(obj, value): | |
| // # sequential consistency | |
| // old_obj = obj | |
| // obj = value | |
| // return old_obj | |
| // | |
| // def _cyatomic_compare_exchange(obj, expected, desired): | |
| // # sequential consistency | |
| // if obj == expected: | |
| // obj = desired | |
| // return True | |
| // else: | |
| // expected = obj | |
| // return False | |
| // | |
| // def _cyatomic_add(obj, value): | |
| // # sequential consistency | |
| // old_obj = obj | |
| // obj += value | |
| // return old_obj | |
| // | |
| // def _cyatomic_and(obj, value): | |
| // # sequential consistency | |
| // old_obj = obj | |
| // obj &= value | |
| // return old_obj | |
| // | |
| // def _cyatomic_or(obj, value): | |
| // # sequential consistency | |
| // old_obj = obj | |
| // obj |= value | |
| // return old_obj | |
| // | |
| // Other functions: | |
| // | |
| // def _cyatomic_load_ptr_acquire(obj): | |
| // return obj # acquire | |
| // | |
| // def _cyatomic_store_ptr_release(obj): | |
| // return obj # release | |
| // | |
| // def _cyatomic_fence_seq_cst(): | |
| // # sequential consistency | |
| // ... | |
| // | |
| // def _cyatomic_fence_release(): | |
| // # release | |
| // ... | |
| #include <Python.h> | |
| // --- _cyatomic_add -------------------------------------------------------- | |
| // Atomically adds `value` to `obj` and returns the previous value | |
| static inline int | |
| _cyatomic_add_int(int *obj, int value); | |
| static inline int8_t | |
| _cyatomic_add_int8(int8_t *obj, int8_t value); | |
| static inline int16_t | |
| _cyatomic_add_int16(int16_t *obj, int16_t value); | |
| static inline int32_t | |
| _cyatomic_add_int32(int32_t *obj, int32_t value); | |
| static inline int64_t | |
| _cyatomic_add_int64(int64_t *obj, int64_t value); | |
| static inline intptr_t | |
| _cyatomic_add_intptr(intptr_t *obj, intptr_t value); | |
| static inline unsigned int | |
| _cyatomic_add_uint(unsigned int *obj, unsigned int value); | |
| static inline uint8_t | |
| _cyatomic_add_uint8(uint8_t *obj, uint8_t value); | |
| static inline uint16_t | |
| _cyatomic_add_uint16(uint16_t *obj, uint16_t value); | |
| static inline uint32_t | |
| _cyatomic_add_uint32(uint32_t *obj, uint32_t value); | |
| static inline uint64_t | |
| _cyatomic_add_uint64(uint64_t *obj, uint64_t value); | |
| static inline uintptr_t | |
| _cyatomic_add_uintptr(uintptr_t *obj, uintptr_t value); | |
| static inline Py_ssize_t | |
| _cyatomic_add_ssize(Py_ssize_t *obj, Py_ssize_t value); | |
| // --- _cyatomic_compare_exchange ------------------------------------------- | |
| // Performs an atomic compare-and-exchange. | |
| // | |
| // - If `*obj` and `*expected` are equal, store `desired` into `*obj` | |
| // and return 1 (success). | |
| // - Otherwise, store the `*obj` current value into `*expected` | |
| // and return 0 (failure). | |
| // | |
| // These correspond to the C11 atomic_compare_exchange_strong() function. | |
| static inline int | |
| _cyatomic_compare_exchange_int(int *obj, int *expected, int desired); | |
| static inline int | |
| _cyatomic_compare_exchange_int8(int8_t *obj, int8_t *expected, int8_t desired); | |
| static inline int | |
| _cyatomic_compare_exchange_int16(int16_t *obj, int16_t *expected, int16_t desired); | |
| static inline int | |
| _cyatomic_compare_exchange_int32(int32_t *obj, int32_t *expected, int32_t desired); | |
| static inline int | |
| _cyatomic_compare_exchange_int64(int64_t *obj, int64_t *expected, int64_t desired); | |
| static inline int | |
| _cyatomic_compare_exchange_intptr(intptr_t *obj, intptr_t *expected, intptr_t desired); | |
| static inline int | |
| _cyatomic_compare_exchange_uint(unsigned int *obj, unsigned int *expected, unsigned int desired); | |
| static inline int | |
| _cyatomic_compare_exchange_uint8(uint8_t *obj, uint8_t *expected, uint8_t desired); | |
| static inline int | |
| _cyatomic_compare_exchange_uint16(uint16_t *obj, uint16_t *expected, uint16_t desired); | |
| static inline int | |
| _cyatomic_compare_exchange_uint32(uint32_t *obj, uint32_t *expected, uint32_t desired); | |
| static inline int | |
| _cyatomic_compare_exchange_uint64(uint64_t *obj, uint64_t *expected, uint64_t desired); | |
| static inline int | |
| _cyatomic_compare_exchange_uintptr(uintptr_t *obj, uintptr_t *expected, uintptr_t desired); | |
| static inline int | |
| _cyatomic_compare_exchange_ssize(Py_ssize_t *obj, Py_ssize_t *expected, Py_ssize_t desired); | |
| // NOTE: `obj` and `expected` are logically `void**` types, but we use `void*` | |
| // so that we can pass types like `PyObject**` without a cast. | |
| static inline int | |
| _cyatomic_compare_exchange_ptr(void *obj, void *expected, void *value); | |
| // --- _cyatomic_exchange --------------------------------------------------- | |
| // Atomically replaces `*obj` with `value` and returns the previous value of `*obj`. | |
| static inline int | |
| _cyatomic_exchange_int(int *obj, int value); | |
| static inline int8_t | |
| _cyatomic_exchange_int8(int8_t *obj, int8_t value); | |
| static inline int16_t | |
| _cyatomic_exchange_int16(int16_t *obj, int16_t value); | |
| static inline int32_t | |
| _cyatomic_exchange_int32(int32_t *obj, int32_t value); | |
| static inline int64_t | |
| _cyatomic_exchange_int64(int64_t *obj, int64_t value); | |
| static inline intptr_t | |
| _cyatomic_exchange_intptr(intptr_t *obj, intptr_t value); | |
| static inline unsigned int | |
| _cyatomic_exchange_uint(unsigned int *obj, unsigned int value); | |
| static inline uint8_t | |
| _cyatomic_exchange_uint8(uint8_t *obj, uint8_t value); | |
| static inline uint16_t | |
| _cyatomic_exchange_uint16(uint16_t *obj, uint16_t value); | |
| static inline uint32_t | |
| _cyatomic_exchange_uint32(uint32_t *obj, uint32_t value); | |
| static inline uint64_t | |
| _cyatomic_exchange_uint64(uint64_t *obj, uint64_t value); | |
| static inline uintptr_t | |
| _cyatomic_exchange_uintptr(uintptr_t *obj, uintptr_t value); | |
| static inline Py_ssize_t | |
| _cyatomic_exchange_ssize(Py_ssize_t *obj, Py_ssize_t value); | |
| static inline void * | |
| _cyatomic_exchange_ptr(void *obj, void *value); | |
| // --- _cyatomic_and -------------------------------------------------------- | |
| // Performs `*obj &= value` atomically and returns the previous value of `*obj`. | |
| static inline uint8_t | |
| _cyatomic_and_uint8(uint8_t *obj, uint8_t value); | |
| static inline uint16_t | |
| _cyatomic_and_uint16(uint16_t *obj, uint16_t value); | |
| static inline uint32_t | |
| _cyatomic_and_uint32(uint32_t *obj, uint32_t value); | |
| static inline uint64_t | |
| _cyatomic_and_uint64(uint64_t *obj, uint64_t value); | |
| static inline uintptr_t | |
| _cyatomic_and_uintptr(uintptr_t *obj, uintptr_t value); | |
| // --- _cyatomic_or --------------------------------------------------------- | |
| // Performs `*obj |= value` atomically and returns the previous value of `*obj`. | |
| static inline uint8_t | |
| _cyatomic_or_uint8(uint8_t *obj, uint8_t value); | |
| static inline uint16_t | |
| _cyatomic_or_uint16(uint16_t *obj, uint16_t value); | |
| static inline uint32_t | |
| _cyatomic_or_uint32(uint32_t *obj, uint32_t value); | |
| static inline uint64_t | |
| _cyatomic_or_uint64(uint64_t *obj, uint64_t value); | |
| static inline uintptr_t | |
| _cyatomic_or_uintptr(uintptr_t *obj, uintptr_t value); | |
| // --- _cyatomic_load ------------------------------------------------------- | |
| // Atomically loads `*obj` (sequential consistency) | |
| static inline int | |
| _cyatomic_load_int(const int *obj); | |
| static inline int8_t | |
| _cyatomic_load_int8(const int8_t *obj); | |
| static inline int16_t | |
| _cyatomic_load_int16(const int16_t *obj); | |
| static inline int32_t | |
| _cyatomic_load_int32(const int32_t *obj); | |
| static inline int64_t | |
| _cyatomic_load_int64(const int64_t *obj); | |
| static inline intptr_t | |
| _cyatomic_load_intptr(const intptr_t *obj); | |
| static inline uint8_t | |
| _cyatomic_load_uint8(const uint8_t *obj); | |
| static inline uint16_t | |
| _cyatomic_load_uint16(const uint16_t *obj); | |
| static inline uint32_t | |
| _cyatomic_load_uint32(const uint32_t *obj); | |
| static inline uint64_t | |
| _cyatomic_load_uint64(const uint64_t *obj); | |
| static inline uintptr_t | |
| _cyatomic_load_uintptr(const uintptr_t *obj); | |
| static inline unsigned int | |
| _cyatomic_load_uint(const unsigned int *obj); | |
| static inline Py_ssize_t | |
| _cyatomic_load_ssize(const Py_ssize_t *obj); | |
| static inline void * | |
| _cyatomic_load_ptr(const void *obj); | |
| // --- _cyatomic_load_relaxed ----------------------------------------------- | |
| // Loads `*obj` (relaxed consistency, i.e., no ordering) | |
| static inline int | |
| _cyatomic_load_int_relaxed(const int *obj); | |
| static inline char | |
| _cyatomic_load_char_relaxed(const char *obj); | |
| static inline unsigned char | |
| _cyatomic_load_uchar_relaxed(const unsigned char *obj); | |
| static inline short | |
| _cyatomic_load_short_relaxed(const short *obj); | |
| static inline unsigned short | |
| _cyatomic_load_ushort_relaxed(const unsigned short *obj); | |
| static inline long | |
| _cyatomic_load_long_relaxed(const long *obj); | |
| static inline double | |
| _cyatomic_load_double_relaxed(const double *obj); | |
| static inline long long | |
| _cyatomic_load_llong_relaxed(const long long *obj); | |
| static inline int8_t | |
| _cyatomic_load_int8_relaxed(const int8_t *obj); | |
| static inline int16_t | |
| _cyatomic_load_int16_relaxed(const int16_t *obj); | |
| static inline int32_t | |
| _cyatomic_load_int32_relaxed(const int32_t *obj); | |
| static inline int64_t | |
| _cyatomic_load_int64_relaxed(const int64_t *obj); | |
| static inline intptr_t | |
| _cyatomic_load_intptr_relaxed(const intptr_t *obj); | |
| static inline uint8_t | |
| _cyatomic_load_uint8_relaxed(const uint8_t *obj); | |
| static inline uint16_t | |
| _cyatomic_load_uint16_relaxed(const uint16_t *obj); | |
| static inline uint32_t | |
| _cyatomic_load_uint32_relaxed(const uint32_t *obj); | |
| static inline uint64_t | |
| _cyatomic_load_uint64_relaxed(const uint64_t *obj); | |
| static inline uintptr_t | |
| _cyatomic_load_uintptr_relaxed(const uintptr_t *obj); | |
| static inline unsigned int | |
| _cyatomic_load_uint_relaxed(const unsigned int *obj); | |
| static inline Py_ssize_t | |
| _cyatomic_load_ssize_relaxed(const Py_ssize_t *obj); | |
| static inline void * | |
| _cyatomic_load_ptr_relaxed(const void *obj); | |
| static inline unsigned long long | |
| _cyatomic_load_ullong_relaxed(const unsigned long long *obj); | |
| // --- _cyatomic_store ------------------------------------------------------ | |
| // Atomically performs `*obj = value` (sequential consistency) | |
| static inline void | |
| _cyatomic_store_int(int *obj, int value); | |
| static inline void | |
| _cyatomic_store_int8(int8_t *obj, int8_t value); | |
| static inline void | |
| _cyatomic_store_int16(int16_t *obj, int16_t value); | |
| static inline void | |
| _cyatomic_store_int32(int32_t *obj, int32_t value); | |
| static inline void | |
| _cyatomic_store_int64(int64_t *obj, int64_t value); | |
| static inline void | |
| _cyatomic_store_intptr(intptr_t *obj, intptr_t value); | |
| static inline void | |
| _cyatomic_store_uint8(uint8_t *obj, uint8_t value); | |
| static inline void | |
| _cyatomic_store_uint16(uint16_t *obj, uint16_t value); | |
| static inline void | |
| _cyatomic_store_uint32(uint32_t *obj, uint32_t value); | |
| static inline void | |
| _cyatomic_store_uint64(uint64_t *obj, uint64_t value); | |
| static inline void | |
| _cyatomic_store_uintptr(uintptr_t *obj, uintptr_t value); | |
| static inline void | |
| _cyatomic_store_uint(unsigned int *obj, unsigned int value); | |
| static inline void | |
| _cyatomic_store_ptr(void *obj, void *value); | |
| static inline void | |
| _cyatomic_store_ssize(Py_ssize_t* obj, Py_ssize_t value); | |
| // --- _cyatomic_store_relaxed ---------------------------------------------- | |
| // Stores `*obj = value` (relaxed consistency, i.e., no ordering) | |
| static inline void | |
| _cyatomic_store_int_relaxed(int *obj, int value); | |
| static inline void | |
| _cyatomic_store_int8_relaxed(int8_t *obj, int8_t value); | |
| static inline void | |
| _cyatomic_store_int16_relaxed(int16_t *obj, int16_t value); | |
| static inline void | |
| _cyatomic_store_int32_relaxed(int32_t *obj, int32_t value); | |
| static inline void | |
| _cyatomic_store_int64_relaxed(int64_t *obj, int64_t value); | |
| static inline void | |
| _cyatomic_store_intptr_relaxed(intptr_t *obj, intptr_t value); | |
| static inline void | |
| _cyatomic_store_uint8_relaxed(uint8_t* obj, uint8_t value); | |
| static inline void | |
| _cyatomic_store_uint16_relaxed(uint16_t *obj, uint16_t value); | |
| static inline void | |
| _cyatomic_store_uint32_relaxed(uint32_t *obj, uint32_t value); | |
| static inline void | |
| _cyatomic_store_uint64_relaxed(uint64_t *obj, uint64_t value); | |
| static inline void | |
| _cyatomic_store_uintptr_relaxed(uintptr_t *obj, uintptr_t value); | |
| static inline void | |
| _cyatomic_store_uint_relaxed(unsigned int *obj, unsigned int value); | |
| static inline void | |
| _cyatomic_store_ptr_relaxed(void *obj, void *value); | |
| static inline void | |
| _cyatomic_store_ssize_relaxed(Py_ssize_t *obj, Py_ssize_t value); | |
| static inline void | |
| _cyatomic_store_ullong_relaxed(unsigned long long *obj, | |
| unsigned long long value); | |
| static inline void | |
| _cyatomic_store_char_relaxed(char *obj, char value); | |
| static inline void | |
| _cyatomic_store_uchar_relaxed(unsigned char *obj, unsigned char value); | |
| static inline void | |
| _cyatomic_store_short_relaxed(short *obj, short value); | |
| static inline void | |
| _cyatomic_store_ushort_relaxed(unsigned short *obj, unsigned short value); | |
| static inline void | |
| _cyatomic_store_long_relaxed(long *obj, long value); | |
| static inline void | |
| _cyatomic_store_float_relaxed(float *obj, float value); | |
| static inline void | |
| _cyatomic_store_double_relaxed(double *obj, double value); | |
| static inline void | |
| _cyatomic_store_llong_relaxed(long long *obj, long long value); | |
| // --- _cyatomic_load_ptr_acquire / _cyatomic_store_ptr_release ------------ | |
| // Loads `*obj` (acquire operation) | |
| static inline void * | |
| _cyatomic_load_ptr_acquire(const void *obj); | |
| static inline uintptr_t | |
| _cyatomic_load_uintptr_acquire(const uintptr_t *obj); | |
| // Stores `*obj = value` (release operation) | |
| static inline void | |
| _cyatomic_store_ptr_release(void *obj, void *value); | |
| static inline void | |
| _cyatomic_store_uintptr_release(uintptr_t *obj, uintptr_t value); | |
| static inline void | |
| _cyatomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value); | |
| static inline void | |
| _cyatomic_store_int_release(int *obj, int value); | |
| static inline int | |
| _cyatomic_load_int_acquire(const int *obj); | |
| static inline void | |
| _cyatomic_store_uint32_release(uint32_t *obj, uint32_t value); | |
| static inline void | |
| _cyatomic_store_uint64_release(uint64_t *obj, uint64_t value); | |
| static inline uint64_t | |
| _cyatomic_load_uint64_acquire(const uint64_t *obj); | |
| static inline uint32_t | |
| _cyatomic_load_uint32_acquire(const uint32_t *obj); | |
| static inline Py_ssize_t | |
| _cyatomic_load_ssize_acquire(const Py_ssize_t *obj); | |
| // --- _cyatomic_fence ------------------------------------------------------ | |
| // Sequential consistency fence. C11 fences have complex semantics. When | |
| // possible, use the atomic operations on variables defined above, which | |
| // generally do not require explicit use of a fence. | |
| // See https://en.cppreference.com/w/cpp/atomic/atomic_thread_fence | |
| static inline void _cyatomic_fence_seq_cst(void); | |
| // Acquire fence | |
| static inline void _cyatomic_fence_acquire(void); | |
| // Release fence | |
| static inline void _cyatomic_fence_release(void); | |
| #ifndef CYATOMIC_USE_GCC_BUILTIN_ATOMICS | |
| # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) | |
| # define CYATOMIC_USE_GCC_BUILTIN_ATOMICS 1 | |
| # elif defined(__clang__) | |
| # if __has_builtin(__atomic_load) | |
| # define CYATOMIC_USE_GCC_BUILTIN_ATOMICS 1 | |
| # endif | |
| # endif | |
| #endif | |
| #if CYATOMIC_USE_GCC_BUILTIN_ATOMICS | |
| # define Py_ATOMIC_GCC_H | |
| # include "cyatomics_gcc.h" | |
| # undef Py_ATOMIC_GCC_H | |
| #elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__) | |
| # define Py_ATOMIC_STD_H | |
| # include "cyatomics_std.h" | |
| # undef Py_ATOMIC_STD_H | |
| #elif defined(_MSC_VER) | |
| # define Py_ATOMIC_MSC_H | |
| # include "cyatomics_msvc.h" | |
| # undef Py_ATOMIC_MSC_H | |
| #else | |
| # error "no available cyatomic implementation for this platform/compiler" | |
| #endif | |
| // --- aliases --------------------------------------------------------------- | |
| #if SIZEOF_LONG == 8 | |
| # define _cyatomic_load_ulong(p) \ | |
| _cyatomic_load_uint64((uint64_t *)p) | |
| # define _cyatomic_load_ulong_relaxed(p) \ | |
| _cyatomic_load_uint64_relaxed((uint64_t *)p) | |
| # define _cyatomic_store_ulong(p, v) \ | |
| _cyatomic_store_uint64((uint64_t *)p, v) | |
| # define _cyatomic_store_ulong_relaxed(p, v) \ | |
| _cyatomic_store_uint64_relaxed((uint64_t *)p, v) | |
| #elif SIZEOF_LONG == 4 | |
| # define _cyatomic_load_ulong(p) \ | |
| _cyatomic_load_uint32((uint32_t *)p) | |
| # define _cyatomic_load_ulong_relaxed(p) \ | |
| _cyatomic_load_uint32_relaxed((uint32_t *)p) | |
| # define _cyatomic_store_ulong(p, v) \ | |
| _cyatomic_store_uint32((uint32_t *)p, v) | |
| # define _cyatomic_store_ulong_relaxed(p, v) \ | |
| _cyatomic_store_uint32_relaxed((uint32_t *)p, v) | |
| #else | |
| # error "long must be 4 or 8 bytes in size" | |
| #endif // SIZEOF_LONG | |
| #ifdef __cplusplus | |
| } | |
| #endif | |
| #endif // __CYATOMICS_H__ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef __CYATOMICS_MSVC_H__ | |
| #define __CYATOMICS_MSVC_H__ | |
| // NOTE: This file has been modified for our use-cases from pyatomic_msc.h | |
| // This is the implementation of Python atomic operations for MSVC if the | |
| // compiler does not support C11 or C++11 atomics. | |
| // | |
| // MSVC intrinsics are defined on char, short, long, __int64, and pointer | |
| // types. Note that long and int are both 32-bits even on 64-bit Windows, | |
| // so operations on int are cast to long. | |
| // | |
| // The volatile keyword has additional memory ordering semantics on MSVC. On | |
| // x86 and x86-64, volatile accesses have acquire-release semantics. On ARM64, | |
| // volatile accesses behave like C11's memory_order_relaxed. | |
| // #ifndef Py_ATOMIC_MSC_H | |
| // # error "this header file must not be included directly" | |
| // #endif | |
| #ifdef __cplusplus | |
| extern "C" { | |
| #endif | |
| #include <Python.h> | |
| #include <intrin.h> | |
| #include <stdint.h> | |
| #define _cyatomic_ASSERT_ARG_TYPE(TYPE) | |
| // #define _cyatomic_ASSERT_ARG_TYPE(TYPE) | |
| // Py_BUILD_ASSERT(sizeof(*obj) == sizeof(TYPE)) | |
| // --- _cyatomic_add -------------------------------------------------------- | |
| static inline int8_t | |
| _cyatomic_add_int8(int8_t *obj, int8_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(char); | |
| return (int8_t)_InterlockedExchangeAdd8((volatile char *)obj, (char)value); | |
| } | |
| static inline int16_t | |
| _cyatomic_add_int16(int16_t *obj, int16_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(short); | |
| return (int16_t)_InterlockedExchangeAdd16((volatile short *)obj, (short)value); | |
| } | |
| static inline int32_t | |
| _cyatomic_add_int32(int32_t *obj, int32_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(long); | |
| return (int32_t)_InterlockedExchangeAdd((volatile long *)obj, (long)value); | |
| } | |
| static inline int64_t | |
| _cyatomic_add_int64(int64_t *obj, int64_t value) | |
| { | |
| #if defined(_M_X64) || defined(_M_ARM64) | |
| _cyatomic_ASSERT_ARG_TYPE(__int64); | |
| return (int64_t)_InterlockedExchangeAdd64((volatile __int64 *)obj, (__int64)value); | |
| #else | |
| int64_t old_value = _cyatomic_load_int64_relaxed(obj); | |
| for (;;) { | |
| int64_t new_value = old_value + value; | |
| if (_cyatomic_compare_exchange_int64(obj, &old_value, new_value)) { | |
| return old_value; | |
| } | |
| } | |
| #endif | |
| } | |
| static inline uint8_t | |
| _cyatomic_add_uint8(uint8_t *obj, uint8_t value) | |
| { | |
| return (uint8_t)_cyatomic_add_int8((int8_t *)obj, (int8_t)value); | |
| } | |
| static inline uint16_t | |
| _cyatomic_add_uint16(uint16_t *obj, uint16_t value) | |
| { | |
| return (uint16_t)_cyatomic_add_int16((int16_t *)obj, (int16_t)value); | |
| } | |
| static inline uint32_t | |
| _cyatomic_add_uint32(uint32_t *obj, uint32_t value) | |
| { | |
| return (uint32_t)_cyatomic_add_int32((int32_t *)obj, (int32_t)value); | |
| } | |
| static inline int | |
| _cyatomic_add_int(int *obj, int value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(int32_t); | |
| return (int)_cyatomic_add_int32((int32_t *)obj, (int32_t)value); | |
| } | |
| static inline unsigned int | |
| _cyatomic_add_uint(unsigned int *obj, unsigned int value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(int32_t); | |
| return (unsigned int)_cyatomic_add_int32((int32_t *)obj, (int32_t)value); | |
| } | |
| static inline uint64_t | |
| _cyatomic_add_uint64(uint64_t *obj, uint64_t value) | |
| { | |
| return (uint64_t)_cyatomic_add_int64((int64_t *)obj, (int64_t)value); | |
| } | |
| static inline intptr_t | |
| _cyatomic_add_intptr(intptr_t *obj, intptr_t value) | |
| { | |
| #if SIZEOF_VOID_P == 8 | |
| _cyatomic_ASSERT_ARG_TYPE(int64_t); | |
| return (intptr_t)_cyatomic_add_int64((int64_t *)obj, (int64_t)value); | |
| #else | |
| _cyatomic_ASSERT_ARG_TYPE(int32_t); | |
| return (intptr_t)_cyatomic_add_int32((int32_t *)obj, (int32_t)value); | |
| #endif | |
| } | |
| static inline uintptr_t | |
| _cyatomic_add_uintptr(uintptr_t *obj, uintptr_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(intptr_t); | |
| return (uintptr_t)_cyatomic_add_intptr((intptr_t *)obj, (intptr_t)value); | |
| } | |
| static inline Py_ssize_t | |
| _cyatomic_add_ssize(Py_ssize_t *obj, Py_ssize_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(intptr_t); | |
| return (Py_ssize_t)_cyatomic_add_intptr((intptr_t *)obj, (intptr_t)value); | |
| } | |
| // --- _cyatomic_compare_exchange ------------------------------------------- | |
| static inline int | |
| _cyatomic_compare_exchange_int8(int8_t *obj, int8_t *expected, int8_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(char); | |
| int8_t initial = (int8_t)_InterlockedCompareExchange8( | |
| (volatile char *)obj, | |
| (char)value, | |
| (char)*expected); | |
| if (initial == *expected) { | |
| return 1; | |
| } | |
| *expected = initial; | |
| return 0; | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_int16(int16_t *obj, int16_t *expected, int16_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(short); | |
| int16_t initial = (int16_t)_InterlockedCompareExchange16( | |
| (volatile short *)obj, | |
| (short)value, | |
| (short)*expected); | |
| if (initial == *expected) { | |
| return 1; | |
| } | |
| *expected = initial; | |
| return 0; | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_int32(int32_t *obj, int32_t *expected, int32_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(long); | |
| int32_t initial = (int32_t)_InterlockedCompareExchange( | |
| (volatile long *)obj, | |
| (long)value, | |
| (long)*expected); | |
| if (initial == *expected) { | |
| return 1; | |
| } | |
| *expected = initial; | |
| return 0; | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_int64(int64_t *obj, int64_t *expected, int64_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(__int64); | |
| int64_t initial = (int64_t)_InterlockedCompareExchange64( | |
| (volatile __int64 *)obj, | |
| (__int64)value, | |
| (__int64)*expected); | |
| if (initial == *expected) { | |
| return 1; | |
| } | |
| *expected = initial; | |
| return 0; | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_ptr(void *obj, void *expected, void *value) | |
| { | |
| void *initial = _InterlockedCompareExchangePointer( | |
| (void**)obj, | |
| value, | |
| *(void**)expected); | |
| if (initial == *(void**)expected) { | |
| return 1; | |
| } | |
| *(void**)expected = initial; | |
| return 0; | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_uint8(uint8_t *obj, uint8_t *expected, uint8_t value) | |
| { | |
| return _cyatomic_compare_exchange_int8((int8_t *)obj, | |
| (int8_t *)expected, | |
| (int8_t)value); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_uint16(uint16_t *obj, uint16_t *expected, uint16_t value) | |
| { | |
| return _cyatomic_compare_exchange_int16((int16_t *)obj, | |
| (int16_t *)expected, | |
| (int16_t)value); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_uint32(uint32_t *obj, uint32_t *expected, uint32_t value) | |
| { | |
| return _cyatomic_compare_exchange_int32((int32_t *)obj, | |
| (int32_t *)expected, | |
| (int32_t)value); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_int(int *obj, int *expected, int value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(int32_t); | |
| return _cyatomic_compare_exchange_int32((int32_t *)obj, | |
| (int32_t *)expected, | |
| (int32_t)value); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_uint(unsigned int *obj, unsigned int *expected, unsigned int value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(int32_t); | |
| return _cyatomic_compare_exchange_int32((int32_t *)obj, | |
| (int32_t *)expected, | |
| (int32_t)value); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_uint64(uint64_t *obj, uint64_t *expected, uint64_t value) | |
| { | |
| return _cyatomic_compare_exchange_int64((int64_t *)obj, | |
| (int64_t *)expected, | |
| (int64_t)value); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_intptr(intptr_t *obj, intptr_t *expected, intptr_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(void*); | |
| return _cyatomic_compare_exchange_ptr((void**)obj, | |
| (void**)expected, | |
| (void*)value); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_uintptr(uintptr_t *obj, uintptr_t *expected, uintptr_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(void*); | |
| return _cyatomic_compare_exchange_ptr((void**)obj, | |
| (void**)expected, | |
| (void*)value); | |
| } | |
| static inline int | |
| _cyatomic_compare_exchange_ssize(Py_ssize_t *obj, Py_ssize_t *expected, Py_ssize_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(void*); | |
| return _cyatomic_compare_exchange_ptr((void**)obj, | |
| (void**)expected, | |
| (void*)value); | |
| } | |
| // --- _cyatomic_exchange --------------------------------------------------- | |
| static inline int8_t | |
| _cyatomic_exchange_int8(int8_t *obj, int8_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(char); | |
| return (int8_t)_InterlockedExchange8((volatile char *)obj, (char)value); | |
| } | |
| static inline int16_t | |
| _cyatomic_exchange_int16(int16_t *obj, int16_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(short); | |
| return (int16_t)_InterlockedExchange16((volatile short *)obj, (short)value); | |
| } | |
| static inline int32_t | |
| _cyatomic_exchange_int32(int32_t *obj, int32_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(long); | |
| return (int32_t)_InterlockedExchange((volatile long *)obj, (long)value); | |
| } | |
| static inline int64_t | |
| _cyatomic_exchange_int64(int64_t *obj, int64_t value) | |
| { | |
| #if defined(_M_X64) || defined(_M_ARM64) | |
| _cyatomic_ASSERT_ARG_TYPE(__int64); | |
| return (int64_t)_InterlockedExchange64((volatile __int64 *)obj, (__int64)value); | |
| #else | |
| int64_t old_value = _cyatomic_load_int64_relaxed(obj); | |
| for (;;) { | |
| if (_cyatomic_compare_exchange_int64(obj, &old_value, value)) { | |
| return old_value; | |
| } | |
| } | |
| #endif | |
| } | |
| static inline void* | |
| _cyatomic_exchange_ptr(void *obj, void *value) | |
| { | |
| return (void*)_InterlockedExchangePointer((void * volatile *)obj, (void *)value); | |
| } | |
| static inline uint8_t | |
| _cyatomic_exchange_uint8(uint8_t *obj, uint8_t value) | |
| { | |
| return (uint8_t)_cyatomic_exchange_int8((int8_t *)obj, | |
| (int8_t)value); | |
| } | |
| static inline uint16_t | |
| _cyatomic_exchange_uint16(uint16_t *obj, uint16_t value) | |
| { | |
| return (uint16_t)_cyatomic_exchange_int16((int16_t *)obj, | |
| (int16_t)value); | |
| } | |
| static inline uint32_t | |
| _cyatomic_exchange_uint32(uint32_t *obj, uint32_t value) | |
| { | |
| return (uint32_t)_cyatomic_exchange_int32((int32_t *)obj, | |
| (int32_t)value); | |
| } | |
| static inline int | |
| _cyatomic_exchange_int(int *obj, int value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(int32_t); | |
| return (int)_cyatomic_exchange_int32((int32_t *)obj, | |
| (int32_t)value); | |
| } | |
| static inline unsigned int | |
| _cyatomic_exchange_uint(unsigned int *obj, unsigned int value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(int32_t); | |
| return (unsigned int)_cyatomic_exchange_int32((int32_t *)obj, | |
| (int32_t)value); | |
| } | |
| static inline uint64_t | |
| _cyatomic_exchange_uint64(uint64_t *obj, uint64_t value) | |
| { | |
| return (uint64_t)_cyatomic_exchange_int64((int64_t *)obj, | |
| (int64_t)value); | |
| } | |
| static inline intptr_t | |
| _cyatomic_exchange_intptr(intptr_t *obj, intptr_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(void*); | |
| return (intptr_t)_cyatomic_exchange_ptr((void**)obj, | |
| (void*)value); | |
| } | |
| static inline uintptr_t | |
| _cyatomic_exchange_uintptr(uintptr_t *obj, uintptr_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(void*); | |
| return (uintptr_t)_cyatomic_exchange_ptr((void**)obj, | |
| (void*)value); | |
| } | |
| static inline Py_ssize_t | |
| _cyatomic_exchange_ssize(Py_ssize_t *obj, Py_ssize_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(void*); | |
| return (Py_ssize_t)_cyatomic_exchange_ptr((void**)obj, | |
| (void*)value); | |
| } | |
| // --- _cyatomic_and -------------------------------------------------------- | |
| static inline uint8_t | |
| _cyatomic_and_uint8(uint8_t *obj, uint8_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(char); | |
| return (uint8_t)_InterlockedAnd8((volatile char *)obj, (char)value); | |
| } | |
| static inline uint16_t | |
| _cyatomic_and_uint16(uint16_t *obj, uint16_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(short); | |
| return (uint16_t)_InterlockedAnd16((volatile short *)obj, (short)value); | |
| } | |
| static inline uint32_t | |
| _cyatomic_and_uint32(uint32_t *obj, uint32_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(long); | |
| return (uint32_t)_InterlockedAnd((volatile long *)obj, (long)value); | |
| } | |
| static inline uint64_t | |
| _cyatomic_and_uint64(uint64_t *obj, uint64_t value) | |
| { | |
| #if defined(_M_X64) || defined(_M_ARM64) | |
| _cyatomic_ASSERT_ARG_TYPE(__int64); | |
| return (uint64_t)_InterlockedAnd64((volatile __int64 *)obj, (__int64)value); | |
| #else | |
| uint64_t old_value = _cyatomic_load_uint64_relaxed(obj); | |
| for (;;) { | |
| uint64_t new_value = old_value & value; | |
| if (_cyatomic_compare_exchange_uint64(obj, &old_value, new_value)) { | |
| return old_value; | |
| } | |
| } | |
| #endif | |
| } | |
| static inline uintptr_t | |
| _cyatomic_and_uintptr(uintptr_t *obj, uintptr_t value) | |
| { | |
| #if SIZEOF_VOID_P == 8 | |
| _cyatomic_ASSERT_ARG_TYPE(uint64_t); | |
| return (uintptr_t)_cyatomic_and_uint64((uint64_t *)obj, | |
| (uint64_t)value); | |
| #else | |
| _cyatomic_ASSERT_ARG_TYPE(uint32_t); | |
| return (uintptr_t)_cyatomic_and_uint32((uint32_t *)obj, | |
| (uint32_t)value); | |
| #endif | |
| } | |
| // --- _cyatomic_or --------------------------------------------------------- | |
| static inline uint8_t | |
| _cyatomic_or_uint8(uint8_t *obj, uint8_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(char); | |
| return (uint8_t)_InterlockedOr8((volatile char *)obj, (char)value); | |
| } | |
| static inline uint16_t | |
| _cyatomic_or_uint16(uint16_t *obj, uint16_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(short); | |
| return (uint16_t)_InterlockedOr16((volatile short *)obj, (short)value); | |
| } | |
| static inline uint32_t | |
| _cyatomic_or_uint32(uint32_t *obj, uint32_t value) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(long); | |
| return (uint32_t)_InterlockedOr((volatile long *)obj, (long)value); | |
| } | |
| static inline uint64_t | |
| _cyatomic_or_uint64(uint64_t *obj, uint64_t value) | |
| { | |
| #if defined(_M_X64) || defined(_M_ARM64) | |
| _cyatomic_ASSERT_ARG_TYPE(__int64); | |
| return (uint64_t)_InterlockedOr64((volatile __int64 *)obj, (__int64)value); | |
| #else | |
| uint64_t old_value = _cyatomic_load_uint64_relaxed(obj); | |
| for (;;) { | |
| uint64_t new_value = old_value | value; | |
| if (_cyatomic_compare_exchange_uint64(obj, &old_value, new_value)) { | |
| return old_value; | |
| } | |
| } | |
| #endif | |
| } | |
| static inline uintptr_t | |
| _cyatomic_or_uintptr(uintptr_t *obj, uintptr_t value) | |
| { | |
| #if SIZEOF_VOID_P == 8 | |
| _cyatomic_ASSERT_ARG_TYPE(uint64_t); | |
| return (uintptr_t)_cyatomic_or_uint64((uint64_t *)obj, | |
| (uint64_t)value); | |
| #else | |
| _cyatomic_ASSERT_ARG_TYPE(uint32_t); | |
| return (uintptr_t)_cyatomic_or_uint32((uint32_t *)obj, | |
| (uint32_t)value); | |
| #endif | |
| } | |
| // --- _cyatomic_load ------------------------------------------------------- | |
| static inline uint8_t | |
| _cyatomic_load_uint8(const uint8_t *obj) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| return *(volatile uint8_t *)obj; | |
| #elif defined(_M_ARM64) | |
| return (uint8_t)__ldar8((unsigned __int8 volatile *)obj); | |
| #else | |
| # error "no implementation of _cyatomic_load_uint8" | |
| #endif | |
| } | |
| static inline uint16_t | |
| _cyatomic_load_uint16(const uint16_t *obj) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| return *(volatile uint16_t *)obj; | |
| #elif defined(_M_ARM64) | |
| return (uint16_t)__ldar16((unsigned __int16 volatile *)obj); | |
| #else | |
| # error "no implementation of _cyatomic_load_uint16" | |
| #endif | |
| } | |
| static inline uint32_t | |
| _cyatomic_load_uint32(const uint32_t *obj) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| return *(volatile uint32_t *)obj; | |
| #elif defined(_M_ARM64) | |
| return (uint32_t)__ldar32((unsigned __int32 volatile *)obj); | |
| #else | |
| # error "no implementation of _cyatomic_load_uint32" | |
| #endif | |
| } | |
| static inline uint64_t | |
| _cyatomic_load_uint64(const uint64_t *obj) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| return *(volatile uint64_t *)obj; | |
| #elif defined(_M_ARM64) | |
| return (uint64_t)__ldar64((unsigned __int64 volatile *)obj); | |
| #else | |
| # error "no implementation of _cyatomic_load_uint64" | |
| #endif | |
| } | |
| static inline int8_t | |
| _cyatomic_load_int8(const int8_t *obj) | |
| { | |
| return (int8_t)_cyatomic_load_uint8((const uint8_t *)obj); | |
| } | |
| static inline int16_t | |
| _cyatomic_load_int16(const int16_t *obj) | |
| { | |
| return (int16_t)_cyatomic_load_uint16((const uint16_t *)obj); | |
| } | |
| static inline int32_t | |
| _cyatomic_load_int32(const int32_t *obj) | |
| { | |
| return (int32_t)_cyatomic_load_uint32((const uint32_t *)obj); | |
| } | |
| static inline int | |
| _cyatomic_load_int(const int *obj) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(uint32_t); | |
| return (int)_cyatomic_load_uint32((uint32_t *)obj); | |
| } | |
| static inline unsigned int | |
| _cyatomic_load_uint(const unsigned int *obj) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(uint32_t); | |
| return (unsigned int)_cyatomic_load_uint32((uint32_t *)obj); | |
| } | |
| static inline int64_t | |
| _cyatomic_load_int64(const int64_t *obj) | |
| { | |
| return (int64_t)_cyatomic_load_uint64((const uint64_t *)obj); | |
| } | |
| static inline void* | |
| _cyatomic_load_ptr(const void *obj) | |
| { | |
| #if SIZEOF_VOID_P == 8 | |
| return (void*)_cyatomic_load_uint64((const uint64_t *)obj); | |
| #else | |
| return (void*)_cyatomic_load_uint32((const uint32_t *)obj); | |
| #endif | |
| } | |
| static inline intptr_t | |
| _cyatomic_load_intptr(const intptr_t *obj) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(void*); | |
| return (intptr_t)_cyatomic_load_ptr((void*)obj); | |
| } | |
| static inline uintptr_t | |
| _cyatomic_load_uintptr(const uintptr_t *obj) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(void*); | |
| return (uintptr_t)_cyatomic_load_ptr((void*)obj); | |
| } | |
| static inline Py_ssize_t | |
| _cyatomic_load_ssize(const Py_ssize_t *obj) | |
| { | |
| _cyatomic_ASSERT_ARG_TYPE(void*); | |
| return (Py_ssize_t)_cyatomic_load_ptr((void*)obj); | |
| } | |
| // --- _cyatomic_load_relaxed ----------------------------------------------- | |
| static inline int | |
| _cyatomic_load_int_relaxed(const int *obj) | |
| { | |
| return *(volatile int *)obj; | |
| } | |
| static inline char | |
| _cyatomic_load_char_relaxed(const char *obj) | |
| { | |
| return *(volatile char *)obj; | |
| } | |
| static inline unsigned char | |
| _cyatomic_load_uchar_relaxed(const unsigned char *obj) | |
| { | |
| return *(volatile unsigned char *)obj; | |
| } | |
| static inline short | |
| _cyatomic_load_short_relaxed(const short *obj) | |
| { | |
| return *(volatile short *)obj; | |
| } | |
| static inline unsigned short | |
| _cyatomic_load_ushort_relaxed(const unsigned short *obj) | |
| { | |
| return *(volatile unsigned short *)obj; | |
| } | |
| static inline long | |
| _cyatomic_load_long_relaxed(const long *obj) | |
| { | |
| return *(volatile long *)obj; | |
| } | |
| static inline float | |
| _cyatomic_load_float_relaxed(const float *obj) | |
| { | |
| return *(volatile float *)obj; | |
| } | |
| static inline double | |
| _cyatomic_load_double_relaxed(const double *obj) | |
| { | |
| return *(volatile double *)obj; | |
| } | |
| static inline int8_t | |
| _cyatomic_load_int8_relaxed(const int8_t *obj) | |
| { | |
| return *(volatile int8_t *)obj; | |
| } | |
| static inline int16_t | |
| _cyatomic_load_int16_relaxed(const int16_t *obj) | |
| { | |
| return *(volatile int16_t *)obj; | |
| } | |
| static inline int32_t | |
| _cyatomic_load_int32_relaxed(const int32_t *obj) | |
| { | |
| return *(volatile int32_t *)obj; | |
| } | |
| static inline int64_t | |
| _cyatomic_load_int64_relaxed(const int64_t *obj) | |
| { | |
| return *(volatile int64_t *)obj; | |
| } | |
| static inline intptr_t | |
| _cyatomic_load_intptr_relaxed(const intptr_t *obj) | |
| { | |
| return *(volatile intptr_t *)obj; | |
| } | |
| static inline uint8_t | |
| _cyatomic_load_uint8_relaxed(const uint8_t *obj) | |
| { | |
| return *(volatile uint8_t *)obj; | |
| } | |
| static inline uint16_t | |
| _cyatomic_load_uint16_relaxed(const uint16_t *obj) | |
| { | |
| return *(volatile uint16_t *)obj; | |
| } | |
| static inline uint32_t | |
| _cyatomic_load_uint32_relaxed(const uint32_t *obj) | |
| { | |
| return *(volatile uint32_t *)obj; | |
| } | |
| static inline uint64_t | |
| _cyatomic_load_uint64_relaxed(const uint64_t *obj) | |
| { | |
| return *(volatile uint64_t *)obj; | |
| } | |
| static inline uintptr_t | |
| _cyatomic_load_uintptr_relaxed(const uintptr_t *obj) | |
| { | |
| return *(volatile uintptr_t *)obj; | |
| } | |
| static inline unsigned int | |
| _cyatomic_load_uint_relaxed(const unsigned int *obj) | |
| { | |
| return *(volatile unsigned int *)obj; | |
| } | |
| static inline Py_ssize_t | |
| _cyatomic_load_ssize_relaxed(const Py_ssize_t *obj) | |
| { | |
| return *(volatile Py_ssize_t *)obj; | |
| } | |
| static inline void* | |
| _cyatomic_load_ptr_relaxed(const void *obj) | |
| { | |
| return *(void * volatile *)obj; | |
| } | |
| static inline unsigned long long | |
| _cyatomic_load_ullong_relaxed(const unsigned long long *obj) | |
| { | |
| return *(volatile unsigned long long *)obj; | |
| } | |
| static inline long long | |
| _cyatomic_load_llong_relaxed(const long long *obj) | |
| { | |
| return *(volatile long long *)obj; | |
| } | |
| // --- _cyatomic_store ------------------------------------------------------ | |
| static inline void | |
| _cyatomic_store_int(int *obj, int value) | |
| { | |
| (void)_cyatomic_exchange_int(obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_int8(int8_t *obj, int8_t value) | |
| { | |
| (void)_cyatomic_exchange_int8(obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_int16(int16_t *obj, int16_t value) | |
| { | |
| (void)_cyatomic_exchange_int16(obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_int32(int32_t *obj, int32_t value) | |
| { | |
| (void)_cyatomic_exchange_int32(obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_int64(int64_t *obj, int64_t value) | |
| { | |
| (void)_cyatomic_exchange_int64(obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_intptr(intptr_t *obj, intptr_t value) | |
| { | |
| (void)_cyatomic_exchange_intptr(obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_uint8(uint8_t *obj, uint8_t value) | |
| { | |
| (void)_cyatomic_exchange_uint8(obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_uint16(uint16_t *obj, uint16_t value) | |
| { | |
| (void)_cyatomic_exchange_uint16(obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_uint32(uint32_t *obj, uint32_t value) | |
| { | |
| (void)_cyatomic_exchange_uint32(obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_uint64(uint64_t *obj, uint64_t value) | |
| { | |
| (void)_cyatomic_exchange_uint64(obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_uintptr(uintptr_t *obj, uintptr_t value) | |
| { | |
| (void)_cyatomic_exchange_uintptr(obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_uint(unsigned int *obj, unsigned int value) | |
| { | |
| (void)_cyatomic_exchange_uint(obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_ptr(void *obj, void *value) | |
| { | |
| (void)_cyatomic_exchange_ptr(obj, value); | |
| } | |
| static inline void | |
| _cyatomic_store_ssize(Py_ssize_t *obj, Py_ssize_t value) | |
| { | |
| (void)_cyatomic_exchange_ssize(obj, value); | |
| } | |
| // --- _cyatomic_store_relaxed ---------------------------------------------- | |
| static inline void | |
| _cyatomic_store_int_relaxed(int *obj, int value) | |
| { | |
| *(volatile int *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_int8_relaxed(int8_t *obj, int8_t value) | |
| { | |
| *(volatile int8_t *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_int16_relaxed(int16_t *obj, int16_t value) | |
| { | |
| *(volatile int16_t *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_int32_relaxed(int32_t *obj, int32_t value) | |
| { | |
| *(volatile int32_t *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_int64_relaxed(int64_t *obj, int64_t value) | |
| { | |
| *(volatile int64_t *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_intptr_relaxed(intptr_t *obj, intptr_t value) | |
| { | |
| *(volatile intptr_t *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_uint8_relaxed(uint8_t *obj, uint8_t value) | |
| { | |
| *(volatile uint8_t *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_uint16_relaxed(uint16_t *obj, uint16_t value) | |
| { | |
| *(volatile uint16_t *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_uint32_relaxed(uint32_t *obj, uint32_t value) | |
| { | |
| *(volatile uint32_t *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_uint64_relaxed(uint64_t *obj, uint64_t value) | |
| { | |
| *(volatile uint64_t *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_uintptr_relaxed(uintptr_t *obj, uintptr_t value) | |
| { | |
| *(volatile uintptr_t *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_uint_relaxed(unsigned int *obj, unsigned int value) | |
| { | |
| *(volatile unsigned int *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_ptr_relaxed(void *obj, void* value) | |
| { | |
| *(void * volatile *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_ssize_relaxed(Py_ssize_t *obj, Py_ssize_t value) | |
| { | |
| *(volatile Py_ssize_t *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_ullong_relaxed(unsigned long long *obj, | |
| unsigned long long value) | |
| { | |
| *(volatile unsigned long long *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_char_relaxed(char *obj, char value) | |
| { | |
| *(volatile char *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_uchar_relaxed(unsigned char *obj, unsigned char value) | |
| { | |
| *(volatile unsigned char *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_short_relaxed(short *obj, short value) | |
| { | |
| *(volatile short *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_ushort_relaxed(unsigned short *obj, unsigned short value) | |
| { | |
| *(volatile unsigned short *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_uint_release(unsigned int *obj, unsigned int value) | |
| { | |
| *(volatile unsigned int *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_long_relaxed(long *obj, long value) | |
| { | |
| *(volatile long *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_float_relaxed(float *obj, float value) | |
| { | |
| *(volatile float *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_double_relaxed(double *obj, double value) | |
| { | |
| *(volatile double *)obj = value; | |
| } | |
| static inline void | |
| _cyatomic_store_llong_relaxed(long long *obj, long long value) | |
| { | |
| *(volatile long long *)obj = value; | |
| } | |
| // --- _cyatomic_load_ptr_acquire / _cyatomic_store_ptr_release ------------ | |
| static inline void * | |
| _cyatomic_load_ptr_acquire(const void *obj) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| return *(void * volatile *)obj; | |
| #elif defined(_M_ARM64) | |
| return (void *)__ldar64((unsigned __int64 volatile *)obj); | |
| #else | |
| # error "no implementation of _cyatomic_load_ptr_acquire" | |
| #endif | |
| } | |
| static inline uintptr_t | |
| _cyatomic_load_uintptr_acquire(const uintptr_t *obj) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| return *(uintptr_t volatile *)obj; | |
| #elif defined(_M_ARM64) | |
| return (uintptr_t)__ldar64((unsigned __int64 volatile *)obj); | |
| #else | |
| # error "no implementation of _cyatomic_load_uintptr_acquire" | |
| #endif | |
| } | |
| static inline void | |
| _cyatomic_store_ptr_release(void *obj, void *value) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| *(void * volatile *)obj = value; | |
| #elif defined(_M_ARM64) | |
| __stlr64((unsigned __int64 volatile *)obj, (uintptr_t)value); | |
| #else | |
| # error "no implementation of _cyatomic_store_ptr_release" | |
| #endif | |
| } | |
| static inline void | |
| _cyatomic_store_uintptr_release(uintptr_t *obj, uintptr_t value) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| *(uintptr_t volatile *)obj = value; | |
| #elif defined(_M_ARM64) | |
| _cyatomic_ASSERT_ARG_TYPE(unsigned __int64); | |
| __stlr64((unsigned __int64 volatile *)obj, (unsigned __int64)value); | |
| #else | |
| # error "no implementation of _cyatomic_store_uintptr_release" | |
| #endif | |
| } | |
| static inline void | |
| _cyatomic_store_int_release(int *obj, int value) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| *(int volatile *)obj = value; | |
| #elif defined(_M_ARM64) | |
| _cyatomic_ASSERT_ARG_TYPE(unsigned __int32); | |
| __stlr32((unsigned __int32 volatile *)obj, (unsigned __int32)value); | |
| #else | |
| # error "no implementation of _cyatomic_store_int_release" | |
| #endif | |
| } | |
| static inline void | |
| _cyatomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| *(Py_ssize_t volatile *)obj = value; | |
| #elif defined(_M_ARM64) | |
| __stlr64((unsigned __int64 volatile *)obj, (unsigned __int64)value); | |
| #else | |
| # error "no implementation of _cyatomic_store_ssize_release" | |
| #endif | |
| } | |
| static inline int | |
| _cyatomic_load_int_acquire(const int *obj) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| return *(int volatile *)obj; | |
| #elif defined(_M_ARM64) | |
| _cyatomic_ASSERT_ARG_TYPE(unsigned __int32); | |
| return (int)__ldar32((unsigned __int32 volatile *)obj); | |
| #else | |
| # error "no implementation of _cyatomic_load_int_acquire" | |
| #endif | |
| } | |
| static inline void | |
| _cyatomic_store_uint32_release(uint32_t *obj, uint32_t value) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| *(uint32_t volatile *)obj = value; | |
| #elif defined(_M_ARM64) | |
| _cyatomic_ASSERT_ARG_TYPE(unsigned __int32); | |
| __stlr32((unsigned __int32 volatile *)obj, (unsigned __int32)value); | |
| #else | |
| # error "no implementation of _cyatomic_store_uint32_release" | |
| #endif | |
| } | |
| static inline void | |
| _cyatomic_store_uint64_release(uint64_t *obj, uint64_t value) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| *(uint64_t volatile *)obj = value; | |
| #elif defined(_M_ARM64) | |
| _cyatomic_ASSERT_ARG_TYPE(unsigned __int64); | |
| __stlr64((unsigned __int64 volatile *)obj, (unsigned __int64)value); | |
| #else | |
| # error "no implementation of _cyatomic_store_uint64_release" | |
| #endif | |
| } | |
| static inline uint64_t | |
| _cyatomic_load_uint64_acquire(const uint64_t *obj) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| return *(uint64_t volatile *)obj; | |
| #elif defined(_M_ARM64) | |
| _cyatomic_ASSERT_ARG_TYPE(__int64); | |
| return (uint64_t)__ldar64((unsigned __int64 volatile *)obj); | |
| #else | |
| # error "no implementation of _cyatomic_load_uint64_acquire" | |
| #endif | |
| } | |
| static inline uint32_t | |
| _cyatomic_load_uint32_acquire(const uint32_t *obj) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| return *(uint32_t volatile *)obj; | |
| #elif defined(_M_ARM64) | |
| return (uint32_t)__ldar32((uint32_t volatile *)obj); | |
| #else | |
| # error "no implementation of _cyatomic_load_uint32_acquire" | |
| #endif | |
| } | |
| static inline Py_ssize_t | |
| _cyatomic_load_ssize_acquire(const Py_ssize_t *obj) | |
| { | |
| #if defined(_M_X64) || defined(_M_IX86) | |
| return *(Py_ssize_t volatile *)obj; | |
| #elif defined(_M_ARM64) | |
| return (Py_ssize_t)__ldar64((unsigned __int64 volatile *)obj); | |
| #else | |
| # error "no implementation of _cyatomic_load_ssize_acquire" | |
| #endif | |
| } | |
| // --- _cyatomic_fence ------------------------------------------------------ | |
| static inline void | |
| _cyatomic_fence_seq_cst(void) | |
| { | |
| #if defined(_M_ARM64) | |
| __dmb(_ARM64_BARRIER_ISH); | |
| #elif defined(_M_X64) | |
| __faststorefence(); | |
| #elif defined(_M_IX86) | |
| _mm_mfence(); | |
| #else | |
| # error "no implementation of _cyatomic_fence_seq_cst" | |
| #endif | |
| } | |
| static inline void | |
| _cyatomic_fence_acquire(void) | |
| { | |
| #if defined(_M_ARM64) | |
| __dmb(_ARM64_BARRIER_ISHLD); | |
| #elif defined(_M_X64) || defined(_M_IX86) | |
| _ReadBarrier(); | |
| #else | |
| # error "no implementation of _cyatomic_fence_acquire" | |
| #endif | |
| } | |
| static inline void | |
| _cyatomic_fence_release(void) | |
| { | |
| #if defined(_M_ARM64) | |
| __dmb(_ARM64_BARRIER_ISH); | |
| #elif defined(_M_X64) || defined(_M_IX86) | |
| _ReadWriteBarrier(); | |
| #else | |
| # error "no implementation of _cyatomic_fence_release" | |
| #endif | |
| } | |
| #ifdef __cplusplus | |
| } | |
| #endif | |
| #endif // __CYATOMICS_MSVC_H__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment