Coverage Report

Created: 2025-07-04 06:49

/src/cpython-install/include/python3.15/cpython/lock.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef Py_CPYTHON_LOCK_H
2
#  error "this header file must not be included directly"
3
#endif
4
5
#define _Py_UNLOCKED    0
6
#define _Py_LOCKED      1
7
8
// A mutex that occupies one byte. The lock can be zero initialized to
9
// represent the unlocked state.
10
//
11
// Typical initialization:
12
//   PyMutex m = (PyMutex){0};
13
//
14
// Or initialize as global variables:
15
//   static PyMutex m;
16
//
17
// Typical usage:
18
//   PyMutex_Lock(&m);
19
//   ...
20
//   PyMutex_Unlock(&m);
21
//
22
// The contents of the PyMutex are not part of the public API, but are
23
// described to aid in understanding the implementation and debugging. Only
24
// the two least significant bits are used. The remaining bits are always zero:
25
// 0b00: unlocked
26
// 0b01: locked
27
// 0b10: unlocked and has parked threads
28
// 0b11: locked and has parked threads
29
typedef struct PyMutex {
30
    uint8_t _bits;  // (private)
31
} PyMutex;
32
33
// exported function for locking the mutex
34
PyAPI_FUNC(void) PyMutex_Lock(PyMutex *m);
35
36
// exported function for unlocking the mutex
37
PyAPI_FUNC(void) PyMutex_Unlock(PyMutex *m);
38
39
// exported function for checking if the mutex is locked
40
PyAPI_FUNC(int) PyMutex_IsLocked(PyMutex *m);
41
42
// Locks the mutex.
43
//
44
// If the mutex is currently locked, the calling thread will be parked until
45
// the mutex is unlocked. If the current thread holds the GIL, then the GIL
46
// will be released while the thread is parked.
47
static inline void
48
_PyMutex_Lock(PyMutex *m)
49
0
{
50
0
    uint8_t expected = _Py_UNLOCKED;
51
0
    if (!_Py_atomic_compare_exchange_uint8(&m->_bits, &expected, _Py_LOCKED)) {
52
0
        PyMutex_Lock(m);
53
0
    }
54
0
}
55
#define PyMutex_Lock _PyMutex_Lock
56
57
// Unlocks the mutex.
58
static inline void
59
_PyMutex_Unlock(PyMutex *m)
60
0
{
61
0
    uint8_t expected = _Py_LOCKED;
62
0
    if (!_Py_atomic_compare_exchange_uint8(&m->_bits, &expected, _Py_UNLOCKED)) {
63
0
        PyMutex_Unlock(m);
64
0
    }
65
0
}
66
#define PyMutex_Unlock _PyMutex_Unlock
67
68
// Checks if the mutex is currently locked.
69
static inline int
70
_PyMutex_IsLocked(PyMutex *m)
71
0
{
72
0
    return (_Py_atomic_load_uint8(&m->_bits) & _Py_LOCKED) != 0;
73
0
}
74
#define PyMutex_IsLocked _PyMutex_IsLocked