Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:06:42

0001 /* Atomic functions: similar to pycore_atomic.h, but don't need
0002    to declare variables as atomic.
0003 
0004    Py_ssize_t type:
0005 
0006    * value = _Py_atomic_size_get(&var)
0007    * _Py_atomic_size_set(&var, value)
0008 
0009    Use sequentially-consistent ordering (__ATOMIC_SEQ_CST memory order):
0010    enforce total ordering with all other atomic functions.
0011 */
0012 #ifndef Py_ATOMIC_FUNC_H
0013 #define Py_ATOMIC_FUNC_H
0014 #ifdef __cplusplus
0015 extern "C" {
0016 #endif
0017 
0018 #ifndef Py_BUILD_CORE
0019 #  error "this header requires Py_BUILD_CORE define"
0020 #endif
0021 
0022 #if defined(_MSC_VER)
0023 #  include <intrin.h>             // _InterlockedExchange()
0024 #endif
0025 
0026 
0027 // Use builtin atomic operations in GCC >= 4.7 and clang
0028 #ifdef HAVE_BUILTIN_ATOMIC
0029 
0030 static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var)
0031 {
0032     return __atomic_load_n(var, __ATOMIC_SEQ_CST);
0033 }
0034 
0035 static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value)
0036 {
0037     __atomic_store_n(var, value, __ATOMIC_SEQ_CST);
0038 }
0039 
0040 #elif defined(_MSC_VER)
0041 
0042 static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var)
0043 {
0044 #if SIZEOF_VOID_P == 8
0045     Py_BUILD_ASSERT(sizeof(__int64) == sizeof(*var));
0046     volatile __int64 *volatile_var = (volatile __int64 *)var;
0047     __int64 old;
0048     do {
0049         old = *volatile_var;
0050     } while(_InterlockedCompareExchange64(volatile_var, old, old) != old);
0051 #else
0052     Py_BUILD_ASSERT(sizeof(long) == sizeof(*var));
0053     volatile long *volatile_var = (volatile long *)var;
0054     long old;
0055     do {
0056         old = *volatile_var;
0057     } while(_InterlockedCompareExchange(volatile_var, old, old) != old);
0058 #endif
0059     return old;
0060 }
0061 
0062 static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value)
0063 {
0064 #if SIZEOF_VOID_P == 8
0065     Py_BUILD_ASSERT(sizeof(__int64) == sizeof(*var));
0066     volatile __int64 *volatile_var = (volatile __int64 *)var;
0067     _InterlockedExchange64(volatile_var, value);
0068 #else
0069     Py_BUILD_ASSERT(sizeof(long) == sizeof(*var));
0070     volatile long *volatile_var = (volatile long *)var;
0071     _InterlockedExchange(volatile_var, value);
0072 #endif
0073 }
0074 
0075 #else
0076 // Fallback implementation using volatile
0077 
0078 static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var)
0079 {
0080     volatile Py_ssize_t *volatile_var = (volatile Py_ssize_t *)var;
0081     return *volatile_var;
0082 }
0083 
0084 static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value)
0085 {
0086     volatile Py_ssize_t *volatile_var = (volatile Py_ssize_t *)var;
0087     *volatile_var = value;
0088 }
0089 #endif
0090 
0091 #ifdef __cplusplus
0092 }
0093 #endif
0094 #endif  /* Py_ATOMIC_FUNC_H */