mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 19:34:08 +00:00 
			
		
		
		
	Add pycore_atomic_funcs.h internal header file: similar to pycore_atomic.h but don't require to declare variables as atomic. Add _Py_atomic_size_get() and _Py_atomic_size_set() functions.
		
			
				
	
	
		
			94 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			94 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 */
 |