@@ -104,65 +104,42 @@ _PyMem_mi_page_clear_qsbr(mi_page_t *page)
104
104
#endif
105
105
}
106
106
107
- // Is the empty page safe to free? It's safe if there was a QSBR goal set and
108
- // the goal has been reached.
107
+ // Check if an empty, newly reclaimed page is safe to free now.
109
108
static bool
110
109
_PyMem_mi_page_is_safe_to_free (mi_page_t * page )
111
110
{
112
111
assert (mi_page_all_free (page ));
113
112
#ifdef Py_GIL_DISABLED
114
- if (page -> use_qsbr ) {
115
- if (page -> qsbr_goal == 0 ) {
116
- // No QSBR goal set, so we can't safely free the page yet.
117
- return false;
118
- }
113
+ assert (page -> qsbr_node .next == NULL );
114
+ if (page -> use_qsbr && page -> qsbr_goal != 0 ) {
119
115
_PyThreadStateImpl * tstate = (_PyThreadStateImpl * )_PyThreadState_GET ();
120
116
if (tstate == NULL ) {
121
117
return false;
122
118
}
123
- if (!_Py_qbsr_goal_reached (tstate -> qsbr , page -> qsbr_goal )) {
124
- return false;
125
- }
126
- _PyMem_mi_page_clear_qsbr (page );
127
- return true;
119
+ return _Py_qbsr_goal_reached (tstate -> qsbr , page -> qsbr_goal );
128
120
}
129
121
#endif
130
122
return true;
131
- }
132
-
133
- #ifdef Py_GIL_DISABLED
134
- // Enqueue a page to be freed later when it's safe to do so (using QSBR).
135
- // Note that we may still allocate from the page.
136
- static void
137
- enqueue_page_qsbr (mi_page_t * page , bool reclaimed )
138
- {
139
- assert (mi_page_all_free (page ));
140
- assert (reclaimed || page -> qsbr_goal == 0 );
141
-
142
- _PyThreadStateImpl * tstate = (_PyThreadStateImpl * )PyThreadState_GET ();
143
- page -> retire_expire = 0 ;
144
-
145
- // The goal may be set if we are reclaiming an empty abandoned page
146
- if (page -> qsbr_goal == 0 ) {
147
- page -> qsbr_goal = _Py_qsbr_deferred_advance (tstate -> qsbr );
148
- }
149
123
150
- llist_insert_tail (& tstate -> mimalloc .page_list , & page -> qsbr_node );
151
124
}
152
- #endif
153
125
154
126
static bool
155
127
_PyMem_mi_page_maybe_free (mi_page_t * page , mi_page_queue_t * pq , bool force )
156
128
{
157
129
#ifdef Py_GIL_DISABLED
158
- if (!_PyMem_mi_page_is_safe_to_free (page )) {
159
- // The page may already be in the QSBR linked list if we allocated from
160
- // it after all blocks were freed.
161
- if (page -> qsbr_node .next != NULL ) {
162
- llist_remove (& page -> qsbr_node );
163
- page -> qsbr_goal = 0 ;
130
+ assert (mi_page_all_free (page ));
131
+ if (page -> use_qsbr ) {
132
+ _PyThreadStateImpl * tstate = (_PyThreadStateImpl * )PyThreadState_GET ();
133
+ if (page -> qsbr_goal != 0 && _Py_qbsr_goal_reached (tstate -> qsbr , page -> qsbr_goal )) {
134
+ _PyMem_mi_page_clear_qsbr (page );
135
+ _mi_page_free (page , pq , force );
136
+ return true;
164
137
}
165
- enqueue_page_qsbr (page , false);
138
+
139
+ _PyMem_mi_page_clear_qsbr (page );
140
+ page -> retire_expire = 0 ;
141
+ page -> qsbr_goal = _Py_qsbr_deferred_advance (tstate -> qsbr );
142
+ llist_insert_tail (& tstate -> mimalloc .page_list , & page -> qsbr_node );
166
143
return false;
167
144
}
168
145
#endif
@@ -177,7 +154,10 @@ _PyMem_mi_page_reclaimed(mi_page_t *page)
177
154
assert (page -> qsbr_node .next == NULL );
178
155
if (page -> qsbr_goal != 0 ) {
179
156
if (mi_page_all_free (page )) {
180
- enqueue_page_qsbr (page , true);
157
+ assert (page -> qsbr_node .next == NULL );
158
+ _PyThreadStateImpl * tstate = (_PyThreadStateImpl * )PyThreadState_GET ();
159
+ page -> retire_expire = 0 ;
160
+ llist_insert_tail (& tstate -> mimalloc .page_list , & page -> qsbr_node );
181
161
}
182
162
else {
183
163
page -> qsbr_goal = 0 ;
@@ -205,17 +185,15 @@ _PyMem_mi_heap_collect_qsbr(mi_heap_t *heap)
205
185
mi_page_t * page = llist_data (node , mi_page_t , qsbr_node );
206
186
if (!mi_page_all_free (page )) {
207
187
// We allocated from this page some point after the delayed free
208
- page -> qsbr_goal = 0 ;
209
- llist_remove (node );
188
+ _PyMem_mi_page_clear_qsbr (page );
210
189
continue ;
211
190
}
212
191
213
192
if (!_Py_qsbr_poll (tstate -> qsbr , page -> qsbr_goal )) {
214
193
return ;
215
194
}
216
195
217
- page -> qsbr_goal = 0 ;
218
- llist_remove (node );
196
+ _PyMem_mi_page_clear_qsbr (page );
219
197
_mi_page_free (page , mi_page_queue_of (page ), false);
220
198
}
221
199
#endif
0 commit comments