mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	
		
			
	
	
		
			95 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			95 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /* Atomic functions: similar to pycore_atomic.h, but don't need
 | ||
|  |    to declare variables as atomic. | ||
|  | 
 | ||
|  |    Py_ssize_t type: | ||
|  | 
 | ||
|  |    * value = _Py_atomic_size_get(&var) | ||
|  |    * _Py_atomic_size_set(&var, value) | ||
|  | 
 | ||
|  |    Use sequentially-consistent ordering (__ATOMIC_SEQ_CST memory order): | ||
|  |    enforce total ordering with all other atomic functions. | ||
|  | */ | ||
|  | #ifndef Py_ATOMIC_FUNC_H
 | ||
|  | #define Py_ATOMIC_FUNC_H
 | ||
|  | #ifdef __cplusplus
 | ||
|  | extern "C" { | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifndef Py_BUILD_CORE
 | ||
|  | #  error "this header requires Py_BUILD_CORE define"
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #if defined(_MSC_VER)
 | ||
|  | #  include <intrin.h>             // _InterlockedExchange()
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | 
 | ||
|  | // Use builtin atomic operations in GCC >= 4.7 and clang
 | ||
|  | #ifdef HAVE_BUILTIN_ATOMIC
 | ||
|  | 
 | ||
|  | static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var) | ||
|  | { | ||
|  |     return __atomic_load_n(var, __ATOMIC_SEQ_CST); | ||
|  | } | ||
|  | 
 | ||
|  | static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value) | ||
|  | { | ||
|  |     __atomic_store_n(var, value, __ATOMIC_SEQ_CST); | ||
|  | } | ||
|  | 
 | ||
|  | #elif defined(_MSC_VER)
 | ||
|  | 
 | ||
|  | static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var) | ||
|  | { | ||
|  | #if SIZEOF_VOID_P == 8
 | ||
|  |     Py_BUILD_ASSERT(sizeof(__int64) == sizeof(*var)); | ||
|  |     volatile __int64 *volatile_var = (volatile __int64 *)var; | ||
|  |     __int64 old; | ||
|  |     do { | ||
|  |         old = *volatile_var; | ||
|  |     } while(_InterlockedCompareExchange64(volatile_var, old, old) != old); | ||
|  | #else
 | ||
|  |     Py_BUILD_ASSERT(sizeof(long) == sizeof(*var)); | ||
|  |     volatile long *volatile_var = (volatile long *)var; | ||
|  |     long old; | ||
|  |     do { | ||
|  |         old = *volatile_var; | ||
|  |     } while(_InterlockedCompareExchange(volatile_var, old, old) != old); | ||
|  | #endif
 | ||
|  |     return old; | ||
|  | } | ||
|  | 
 | ||
|  | static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value) | ||
|  | { | ||
|  | #if SIZEOF_VOID_P == 8
 | ||
|  |     Py_BUILD_ASSERT(sizeof(__int64) == sizeof(*var)); | ||
|  |     volatile __int64 *volatile_var = (volatile __int64 *)var; | ||
|  |     _InterlockedExchange64(volatile_var, value); | ||
|  | #else
 | ||
|  |     Py_BUILD_ASSERT(sizeof(long) == sizeof(*var)); | ||
|  |     volatile long *volatile_var = (volatile long *)var; | ||
|  |     _InterlockedExchange(volatile_var, value); | ||
|  | #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | #else
 | ||
|  | // Fallback implementation using volatile
 | ||
|  | 
 | ||
|  | static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var) | ||
|  | { | ||
|  |     volatile Py_ssize_t *volatile_var = (volatile Py_ssize_t *)var; | ||
|  |     return *volatile_var; | ||
|  | } | ||
|  | 
 | ||
|  | static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value) | ||
|  | { | ||
|  |     volatile Py_ssize_t *volatile_var = (volatile Py_ssize_t *)var; | ||
|  |     *volatile_var = value; | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef __cplusplus
 | ||
|  | } | ||
|  | #endif
 | ||
|  | #endif  /* Py_ATOMIC_FUNC_H */
 |