Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Include/internal/pycore_atomic_funcs.h
12 views
1
/* Atomic functions: similar to pycore_atomic.h, but don't need
2
to declare variables as atomic.
3
4
Py_ssize_t type:
5
6
* value = _Py_atomic_size_get(&var)
7
* _Py_atomic_size_set(&var, value)
8
9
Use sequentially-consistent ordering (__ATOMIC_SEQ_CST memory order):
10
enforce total ordering with all other atomic functions.
11
*/
12
#ifndef Py_ATOMIC_FUNC_H
13
#define Py_ATOMIC_FUNC_H
14
#ifdef __cplusplus
15
extern "C" {
16
#endif
17
18
#ifndef Py_BUILD_CORE
19
# error "this header requires Py_BUILD_CORE define"
20
#endif
21
22
#if defined(_MSC_VER)
23
# include <intrin.h> // _InterlockedExchange()
24
#endif
25
26
27
// Use builtin atomic operations in GCC >= 4.7 and clang
28
#ifdef HAVE_BUILTIN_ATOMIC
29
30
static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var)
31
{
32
return __atomic_load_n(var, __ATOMIC_SEQ_CST);
33
}
34
35
static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value)
36
{
37
__atomic_store_n(var, value, __ATOMIC_SEQ_CST);
38
}
39
40
#elif defined(_MSC_VER)
41
42
static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var)
43
{
44
#if SIZEOF_VOID_P == 8
45
Py_BUILD_ASSERT(sizeof(__int64) == sizeof(*var));
46
volatile __int64 *volatile_var = (volatile __int64 *)var;
47
__int64 old;
48
do {
49
old = *volatile_var;
50
} while(_InterlockedCompareExchange64(volatile_var, old, old) != old);
51
#else
52
Py_BUILD_ASSERT(sizeof(long) == sizeof(*var));
53
volatile long *volatile_var = (volatile long *)var;
54
long old;
55
do {
56
old = *volatile_var;
57
} while(_InterlockedCompareExchange(volatile_var, old, old) != old);
58
#endif
59
return old;
60
}
61
62
static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value)
63
{
64
#if SIZEOF_VOID_P == 8
65
Py_BUILD_ASSERT(sizeof(__int64) == sizeof(*var));
66
volatile __int64 *volatile_var = (volatile __int64 *)var;
67
_InterlockedExchange64(volatile_var, value);
68
#else
69
Py_BUILD_ASSERT(sizeof(long) == sizeof(*var));
70
volatile long *volatile_var = (volatile long *)var;
71
_InterlockedExchange(volatile_var, value);
72
#endif
73
}
74
75
#else
76
// Fallback implementation using volatile
77
78
static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var)
79
{
80
volatile Py_ssize_t *volatile_var = (volatile Py_ssize_t *)var;
81
return *volatile_var;
82
}
83
84
static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value)
85
{
86
volatile Py_ssize_t *volatile_var = (volatile Py_ssize_t *)var;
87
*volatile_var = value;
88
}
89
#endif
90
91
#ifdef __cplusplus
92
}
93
#endif
94
#endif /* Py_ATOMIC_FUNC_H */
95
96