-
-
Notifications
You must be signed in to change notification settings - Fork 34.4k
Expand file tree
/
Copy paththreadsafety.dat
More file actions
177 lines (137 loc) · 5.41 KB
/
threadsafety.dat
File metadata and controls
177 lines (137 loc) · 5.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# Thread safety annotations for C API functions.
#
# Each line has the form:
# function_name : level
#
# Where level is one of:
# incompatible -- not safe even with external locking
# compatible -- safe if the caller serializes all access with external locks
# distinct -- safe on distinct objects without external synchronization
# shared -- safe for concurrent use on the same object
# atomic -- atomic
#
# Lines beginning with '#' are ignored.
# The function name must match the C domain identifier used in the documentation.
# Synchronization primitives (Doc/c-api/synchronization.rst)
PyMutex_Lock:shared:
PyMutex_Unlock:shared:
PyMutex_IsLocked:atomic:
# List objects (Doc/c-api/list.rst)
# Type checks - read ob_type pointer, always safe
PyList_Check:atomic:
PyList_CheckExact:atomic:
# Creation - pure allocation, no shared state
PyList_New:atomic:
# Size - uses atomic load on free-threaded builds
PyList_Size:atomic:
PyList_GET_SIZE:atomic:
# Strong-reference lookup - lock-free with atomic ops
PyList_GetItemRef:atomic:
# Borrowed-reference lookups - no locking; returned borrowed
# reference is unsafe in free-threaded builds without
# external synchronization
PyList_GetItem:compatible:
PyList_GET_ITEM:compatible:
# Single-item mutations - hold per-object lock for duration;
# appear atomic to lock-free readers
PyList_SetItem:atomic:
PyList_Append:atomic:
# Insert - protected by per-object critical section; shifts
# elements so lock-free readers may observe intermediate states
PyList_Insert:shared:
# Initialization macro - no synchronization; normally only used
# to fill in new lists where there is no previous content
PyList_SET_ITEM:compatible:
# Bulk operations - hold per-object lock for duration
PyList_GetSlice:atomic:
PyList_AsTuple:atomic:
PyList_Clear:atomic:
# Reverse - protected by per-object critical section; swaps
# elements so lock-free readers may observe intermediate states
PyList_Reverse:shared:
# Slice assignment - lock target list; also lock source when it
# is a list
PyList_SetSlice:shared:
# Sort - per-object lock held; the list is emptied before sorting
# so other threads may observe an empty list, but they won't see the
# intermediate states of the sort
PyList_Sort:shared:
# Extend - lock target list; also lock source when it is a
# list, set, or dict
PyList_Extend:shared:
# Creation - pure allocation, no shared state
PyBytes_FromString:atomic:
PyBytes_FromStringAndSize:atomic:
PyBytes_DecodeEscape:atomic:
# Creation from formatting C primitives - pure allocation, no shared state
PyBytes_FromFormat:atomic:
PyBytes_FromFormatV:atomic:
# Creation from object - uses buffer protocol so may call arbitrary code;
# safe as long as the buffer is not mutated by another thread during the operation
PyBytes_FromObject:shared:
# Size - uses atomic load on free-threaded builds
PyBytes_Size:atomic:
PyBytes_GET_SIZE:atomic:
# Raw data - no locking; mutating it is unsafe if the bytes object is shared between threads
PyBytes_AsString:compatible:
PyBytes_AS_STRING:compatible:
PyBytes_AsStringAndSize:compatible:
# Concatenation - uses buffer protocol; safe as long as buffer is not mutated by another thread during the operation
PyBytes_Concat:shared:
PyBytes_ConcatAndDel:shared:
PyBytes_Join:shared:
# Resizing - safe if the object is unique
_PyBytes_Resize:distinct:
# Repr - atomic as bytes are immutable
PyBytes_Repr:atomic:
# Creation from object - may call arbitrary code
PyByteArray_FromObject:shared:
# Creation - pure allocation, no shared state
PyByteArray_FromStringAndSize:atomic:
# Concatenation - uses buffer protocol; safe as long as buffer is not mutated by another thread during the operation
PyByteArray_Concat:shared:
# Size - uses atomic load on free-threaded builds
PyByteArray_Size:atomic:
PyByteArray_GET_SIZE:atomic:
# Raw data - no locking; mutating it is unsafe if the bytearray object is shared between threads
PyByteArray_AsString:compatible:
PyByteArray_AS_STRING:compatible:
# Creation - may iterate the iterable argument, calling arbitrary code
# atomic for sets, frozensets, dicts, and frozendicts.
PySet_New:shared:
PyFrozenSet_New:shared:
# Size - uses atomic load on free-threaded builds
PySet_Size:atomic:
PySet_GET_SIZE:atomic:
# Contains - lock-free, atomic with simple types
PySet_Contains:shared:
# Mutations - hold per-object lock for duration
# atomic with simple types
PySet_Add:shared:
PySet_Discard:shared:
# Pop - hold per-object lock for duration
PySet_Pop:atomic:
# Clear - empties the set before clearing
PySet_Clear:atomic:
# Capsule objects (Doc/c-api/capsule.rst)
# Type check - read ob_type pointer, always safe
PyCapsule_CheckExact:atomic:
# Creation - pure allocation, no shared state
PyCapsule_New:atomic:
# Validation - reads pointer and name fields; safe on distinct objects
PyCapsule_IsValid:distinct:
# Getters - read struct fields; safe on distinct objects but
# concurrent access to the same capsule requires external synchronization
PyCapsule_GetPointer:distinct:
PyCapsule_GetName:distinct:
PyCapsule_GetDestructor:distinct:
PyCapsule_GetContext:distinct:
# Setters - write struct fields; safe on distinct objects but
# concurrent access to the same capsule requires external synchronization
PyCapsule_SetPointer:distinct:
PyCapsule_SetName:distinct:
PyCapsule_SetDestructor:distinct:
PyCapsule_SetContext:distinct:
# Import - looks up a capsule from a module attribute and
# calls PyCapsule_GetPointer; may call arbitrary code
PyCapsule_Import:compatible: