mirror of
https://github.com/python/cpython.git
synced 2025-08-23 10:16:01 +00:00
gh-114940: Add _Py_FOR_EACH_TSTATE_UNLOCKED(), and Friends (gh-127077)
This is a precursor to the actual fix for gh-114940, where we will change these macros to use the new lock. This change is almost entirely mechanical; the exceptions are the loops in codeobject.c and ceval.c, which now hold the "head" lock. Note that almost all of the uses of _Py_FOR_EACH_TSTATE_UNLOCKED() here will change to _Py_FOR_EACH_TSTATE_BEGIN() once we add the new per-interpreter lock.
This commit is contained in:
parent
bf542f8bb9
commit
9dabace39d
9 changed files with 79 additions and 87 deletions
|
@ -304,7 +304,7 @@ gc_visit_heaps_lock_held(PyInterpreterState *interp, mi_block_visit_fun *visitor
|
|||
Py_ssize_t offset_pre = offset_base + 2 * sizeof(PyObject*);
|
||||
|
||||
// visit each thread's heaps for GC objects
|
||||
for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) {
|
||||
_Py_FOR_EACH_TSTATE_UNLOCKED(interp, p) {
|
||||
struct _mimalloc_thread_state *m = &((_PyThreadStateImpl *)p)->mimalloc;
|
||||
if (!_Py_atomic_load_int(&m->initialized)) {
|
||||
// The thread may not have called tstate_mimalloc_bind() yet.
|
||||
|
@ -374,8 +374,7 @@ gc_visit_stackref(_PyStackRef stackref)
|
|||
static void
|
||||
gc_visit_thread_stacks(PyInterpreterState *interp)
|
||||
{
|
||||
HEAD_LOCK(&_PyRuntime);
|
||||
for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) {
|
||||
_Py_FOR_EACH_TSTATE_BEGIN(interp, p) {
|
||||
for (_PyInterpreterFrame *f = p->current_frame; f != NULL; f = f->previous) {
|
||||
PyObject *executable = PyStackRef_AsPyObjectBorrow(f->f_executable);
|
||||
if (executable == NULL || !PyCode_Check(executable)) {
|
||||
|
@ -390,7 +389,7 @@ gc_visit_thread_stacks(PyInterpreterState *interp)
|
|||
}
|
||||
}
|
||||
}
|
||||
HEAD_UNLOCK(&_PyRuntime);
|
||||
_Py_FOR_EACH_TSTATE_END(interp);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -444,14 +443,13 @@ process_delayed_frees(PyInterpreterState *interp, struct collection_state *state
|
|||
|
||||
// Merge the queues from other threads into our own queue so that we can
|
||||
// process all of the pending delayed free requests at once.
|
||||
HEAD_LOCK(&_PyRuntime);
|
||||
for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) {
|
||||
_Py_FOR_EACH_TSTATE_BEGIN(interp, p) {
|
||||
_PyThreadStateImpl *other = (_PyThreadStateImpl *)p;
|
||||
if (other != current_tstate) {
|
||||
llist_concat(¤t_tstate->mem_free_queue, &other->mem_free_queue);
|
||||
}
|
||||
}
|
||||
HEAD_UNLOCK(&_PyRuntime);
|
||||
_Py_FOR_EACH_TSTATE_END(interp);
|
||||
|
||||
_PyMem_ProcessDelayedNoDealloc((PyThreadState *)current_tstate, queue_freed_object, state);
|
||||
}
|
||||
|
@ -1234,8 +1232,7 @@ gc_collect_internal(PyInterpreterState *interp, struct collection_state *state,
|
|||
state->gcstate->old[i-1].count = 0;
|
||||
}
|
||||
|
||||
HEAD_LOCK(&_PyRuntime);
|
||||
for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) {
|
||||
_Py_FOR_EACH_TSTATE_BEGIN(interp, p) {
|
||||
_PyThreadStateImpl *tstate = (_PyThreadStateImpl *)p;
|
||||
|
||||
// merge per-thread refcount for types into the type's actual refcount
|
||||
|
@ -1244,7 +1241,7 @@ gc_collect_internal(PyInterpreterState *interp, struct collection_state *state,
|
|||
// merge refcounts for all queued objects
|
||||
merge_queued_objects(tstate, state);
|
||||
}
|
||||
HEAD_UNLOCK(&_PyRuntime);
|
||||
_Py_FOR_EACH_TSTATE_END(interp);
|
||||
|
||||
process_delayed_frees(interp, state);
|
||||
|
||||
|
@ -1993,13 +1990,11 @@ PyUnstable_GC_VisitObjects(gcvisitobjects_t callback, void *arg)
|
|||
void
|
||||
_PyGC_ClearAllFreeLists(PyInterpreterState *interp)
|
||||
{
|
||||
HEAD_LOCK(&_PyRuntime);
|
||||
_PyThreadStateImpl *tstate = (_PyThreadStateImpl *)interp->threads.head;
|
||||
while (tstate != NULL) {
|
||||
_Py_FOR_EACH_TSTATE_BEGIN(interp, p) {
|
||||
_PyThreadStateImpl *tstate = (_PyThreadStateImpl *)p;
|
||||
_PyObject_ClearFreeLists(&tstate->freelists, 0);
|
||||
tstate = (_PyThreadStateImpl *)tstate->base.next;
|
||||
}
|
||||
HEAD_UNLOCK(&_PyRuntime);
|
||||
_Py_FOR_EACH_TSTATE_END(interp);
|
||||
}
|
||||
|
||||
#endif // Py_GIL_DISABLED
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue