@@ -244,6 +244,7 @@ _Py_ClearExecutorDeletionList(PyInterpreterState *interp)
244244 ts = PyThreadState_Next (ts );
245245 HEAD_UNLOCK (runtime );
246246 }
247+ EXECUTOR_LIST_LOCK (interp );
247248 _PyExecutorObject * * prev_to_next_ptr = & interp -> executor_deletion_list_head ;
248249 _PyExecutorObject * exec = * prev_to_next_ptr ;
249250 while (exec != NULL ) {
@@ -259,12 +260,14 @@ _Py_ClearExecutorDeletionList(PyInterpreterState *interp)
259260 exec = * prev_to_next_ptr ;
260261 }
261262 interp -> executor_deletion_list_remaining_capacity = EXECUTOR_DELETE_LIST_MAX ;
263+ EXECUTOR_LIST_UNLOCK (interp );
262264}
263265
264266static void
265267add_to_pending_deletion_list (_PyExecutorObject * self )
266268{
267269 PyInterpreterState * interp = PyInterpreterState_Get ();
270+ EXECUTOR_LIST_LOCK (interp );
268271 self -> vm_data .links .next = interp -> executor_deletion_list_head ;
269272 interp -> executor_deletion_list_head = self ;
270273 if (interp -> executor_deletion_list_remaining_capacity > 0 ) {
@@ -273,6 +276,7 @@ add_to_pending_deletion_list(_PyExecutorObject *self)
273276 else {
274277 _Py_ClearExecutorDeletionList (interp );
275278 }
279+ EXECUTOR_LIST_UNLOCK (interp );
276280}
277281
278282static void
@@ -1441,6 +1445,7 @@ static void
14411445link_executor (_PyExecutorObject * executor )
14421446{
14431447 PyInterpreterState * interp = _PyInterpreterState_GET ();
1448+ EXECUTOR_LIST_LOCK (interp );
14441449 _PyExecutorLinkListNode * links = & executor -> vm_data .links ;
14451450 _PyExecutorObject * head = interp -> executor_list_head ;
14461451 if (head == NULL ) {
@@ -1458,6 +1463,7 @@ link_executor(_PyExecutorObject *executor)
14581463 executor -> vm_data .linked = true;
14591464 /* executor_list_head must be first in list */
14601465 assert (interp -> executor_list_head -> vm_data .links .previous == NULL );
1466+ EXECUTOR_LIST_UNLOCK (interp );
14611467}
14621468
14631469static void
@@ -1466,6 +1472,8 @@ unlink_executor(_PyExecutorObject *executor)
14661472 if (!executor -> vm_data .linked ) {
14671473 return ;
14681474 }
1475+ PyInterpreterState * interp = PyInterpreterState_Get ();
1476+ EXECUTOR_LIST_LOCK (interp );
14691477 _PyExecutorLinkListNode * links = & executor -> vm_data .links ;
14701478 assert (executor -> vm_data .valid );
14711479 _PyExecutorObject * next = links -> next ;
@@ -1478,11 +1486,11 @@ unlink_executor(_PyExecutorObject *executor)
14781486 }
14791487 else {
14801488 // prev == NULL implies that executor is the list head
1481- PyInterpreterState * interp = PyInterpreterState_Get ();
14821489 assert (interp -> executor_list_head == executor );
14831490 interp -> executor_list_head = next ;
14841491 }
14851492 executor -> vm_data .linked = false;
1493+ EXECUTOR_LIST_UNLOCK (interp );
14861494}
14871495
14881496/* This must be called by optimizers before using the executor */
@@ -1607,16 +1615,19 @@ _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is
16071615 }
16081616 /* Clearing an executor can deallocate others, so we need to make a list of
16091617 * executors to invalidate first */
1618+ EXECUTOR_LIST_LOCK (interp );
16101619 for (_PyExecutorObject * exec = interp -> executor_list_head ; exec != NULL ;) {
16111620 assert (exec -> vm_data .valid );
16121621 _PyExecutorObject * next = exec -> vm_data .links .next ;
16131622 if (bloom_filter_may_contain (& exec -> vm_data .bloom , & obj_filter ) &&
16141623 PyList_Append (invalidate , (PyObject * )exec ))
16151624 {
1625+ EXECUTOR_LIST_UNLOCK (interp );
16161626 goto error ;
16171627 }
16181628 exec = next ;
16191629 }
1630+ EXECUTOR_LIST_UNLOCK (interp );
16201631 for (Py_ssize_t i = 0 ; i < PyList_GET_SIZE (invalidate ); i ++ ) {
16211632 PyObject * exec = PyList_GET_ITEM (invalidate , i );
16221633 executor_clear (exec );
@@ -1637,6 +1648,7 @@ _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is
16371648void
16381649_Py_Executors_InvalidateAll (PyInterpreterState * interp , int is_invalidation )
16391650{
1651+ EXECUTOR_LIST_LOCK (interp );
16401652 while (interp -> executor_list_head ) {
16411653 _PyExecutorObject * executor = interp -> executor_list_head ;
16421654 assert (executor -> vm_data .valid == 1 && executor -> vm_data .linked == 1 );
@@ -1651,6 +1663,7 @@ _Py_Executors_InvalidateAll(PyInterpreterState *interp, int is_invalidation)
16511663 OPT_STAT_INC (executors_invalidated );
16521664 }
16531665 }
1666+ EXECUTOR_LIST_UNLOCK (interp );
16541667}
16551668
16561669void
@@ -1665,11 +1678,13 @@ _Py_Executors_InvalidateCold(PyInterpreterState *interp)
16651678
16661679 /* Clearing an executor can deallocate others, so we need to make a list of
16671680 * executors to invalidate first */
1681+ EXECUTOR_LIST_LOCK (interp );
16681682 for (_PyExecutorObject * exec = interp -> executor_list_head ; exec != NULL ;) {
16691683 assert (exec -> vm_data .valid );
16701684 _PyExecutorObject * next = exec -> vm_data .links .next ;
16711685
16721686 if (!exec -> vm_data .warm && PyList_Append (invalidate , (PyObject * )exec ) < 0 ) {
1687+ EXECUTOR_LIST_UNLOCK (interp );
16731688 goto error ;
16741689 }
16751690 else {
@@ -1678,6 +1693,7 @@ _Py_Executors_InvalidateCold(PyInterpreterState *interp)
16781693
16791694 exec = next ;
16801695 }
1696+ EXECUTOR_LIST_UNLOCK (interp );
16811697 for (Py_ssize_t i = 0 ; i < PyList_GET_SIZE (invalidate ); i ++ ) {
16821698 PyObject * exec = PyList_GET_ITEM (invalidate , i );
16831699 executor_clear (exec );
@@ -1801,10 +1817,12 @@ _PyDumpExecutors(FILE *out)
18011817 fprintf (out , "digraph ideal {\n\n" );
18021818 fprintf (out , " rankdir = \"LR\"\n\n" );
18031819 PyInterpreterState * interp = PyInterpreterState_Get ();
1820+ EXECUTOR_LIST_LOCK (interp );
18041821 for (_PyExecutorObject * exec = interp -> executor_list_head ; exec != NULL ;) {
18051822 executor_to_gv (exec , out );
18061823 exec = exec -> vm_data .links .next ;
18071824 }
1825+ EXECUTOR_LIST_UNLOCK (interp );
18081826 fprintf (out , "}\n\n" );
18091827 return 0 ;
18101828}
0 commit comments