@@ -68,8 +68,8 @@ typedef struct TaskObj {
6868 PyObject * task_context ;
6969 struct llist_node task_node ;
7070#ifdef Py_GIL_DISABLED
71- // thread id of the thread where this task was created
72- uintptr_t task_tid ;
71+ // unique id of the thread state where the task was registered
72+ uint64_t task_tstate_id ;
7373#endif
7474} TaskObj ;
7575
@@ -2195,6 +2195,9 @@ register_task(_PyThreadStateImpl *ts, TaskObj *task)
21952195 assert (task -> task_node .prev != NULL );
21962196 return ;
21972197 }
2198+ #ifdef Py_GIL_DISABLED
2199+ task -> task_tstate_id = ts -> base .id ;
2200+ #endif
21982201 struct llist_node * head = & ts -> asyncio_tasks_head ;
21992202 llist_insert_tail (head , & task -> task_node );
22002203}
@@ -2214,15 +2217,15 @@ static void
22142217unregister_task (TaskObj * task )
22152218{
22162219#ifdef Py_GIL_DISABLED
2217- // check if we are in the same thread
2218- // if so, we can avoid locking
2219- if (task -> task_tid == _Py_ThreadId ()) {
2220+ PyThreadState * tstate = _PyThreadState_GET ();
2221+ // The task can only be on this thread's list if this thread state
2222+ // registered it, in which case no locking is needed.
2223+ if (task -> task_tstate_id == tstate -> id ) {
22202224 unregister_task_safe (task );
22212225 }
22222226 else {
2223- // we are in a different thread
2224- // stop the world then check and remove the task
2225- PyThreadState * tstate = _PyThreadState_GET ();
2227+ // The task is on another thread's list or on the interpreter's
2228+ // list of lingering tasks: stop the world to remove it.
22262229 _PyEval_StopTheWorld (tstate -> interp );
22272230 unregister_task_safe (task );
22282231 _PyEval_StartTheWorld (tstate -> interp );
@@ -2350,9 +2353,6 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
23502353 }
23512354
23522355 Py_CLEAR (self -> task_fut_waiter );
2353- #ifdef Py_GIL_DISABLED
2354- self -> task_tid = _Py_ThreadId ();
2355- #endif
23562356 self -> task_must_cancel = 0 ;
23572357 self -> task_log_destroy_pending = 1 ;
23582358 self -> task_num_cancels_requested = 0 ;
@@ -3994,7 +3994,6 @@ add_tasks_llist(struct llist_node *head, PyListObject *tasks)
39943994 struct llist_node * node ;
39953995 llist_for_each_safe (node , head ) {
39963996 TaskObj * task = llist_data (node , TaskObj , task_node );
3997- assert (task -> task_state == STATE_PENDING );
39983997 // The linked list holds borrowed references to task
39993998 // as such it is possible that the task is concurrently
40003999 // deallocated while added to this list.
0 commit comments