mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +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 */
							 |