Coverage Report

Created: 2022-07-08 09:39

/home/mdboom/Work/builds/cpython/Include/internal/pycore_atomic_funcs.h
Line
Count
Source
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 */