@@ -67,8 +67,8 @@ typedef struct TaskObj {
6767 PyObject * task_context ;
6868 struct llist_node task_node ;
6969#ifdef Py_GIL_DISABLED
70- // thread id of the thread where this task was created
71- uintptr_t task_tid ;
70+ // unique id of the thread state where the task was registered
71+ uint64_t task_tstate_id ;
7272#endif
7373} TaskObj ;
7474
@@ -2209,6 +2209,9 @@ register_task(TaskObj *task)
22092209 return ;
22102210 }
22112211 _PyThreadStateImpl * tstate = (_PyThreadStateImpl * ) _PyThreadState_GET ();
2212+ #ifdef Py_GIL_DISABLED
2213+ task -> task_tstate_id = tstate -> base .id ;
2214+ #endif
22122215 struct llist_node * head = & tstate -> asyncio_tasks_head ;
22132216 llist_insert_tail (head , & task -> task_node );
22142217}
@@ -2228,15 +2231,15 @@ static void
22282231unregister_task (TaskObj * task )
22292232{
22302233#ifdef Py_GIL_DISABLED
2231- // check if we are in the same thread
2232- // if so, we can avoid locking
2233- if (task -> task_tid == _Py_ThreadId ()) {
2234+ PyThreadState * tstate = _PyThreadState_GET ();
2235+ // The task can only be on this thread's list if this thread state
2236+ // registered it, in which case no locking is needed.
2237+ if (task -> task_tstate_id == tstate -> id ) {
22342238 unregister_task_safe (task );
22352239 }
22362240 else {
2237- // we are in a different thread
2238- // stop the world then check and remove the task
2239- PyThreadState * tstate = _PyThreadState_GET ();
2241+ // The task is on another thread's list or on the interpreter's
2242+ // list of lingering tasks: stop the world to remove it.
22402243 _PyEval_StopTheWorld (tstate -> interp );
22412244 unregister_task_safe (task );
22422245 _PyEval_StartTheWorld (tstate -> interp );
@@ -2370,9 +2373,6 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
23702373 }
23712374
23722375 Py_CLEAR (self -> task_fut_waiter );
2373- #ifdef Py_GIL_DISABLED
2374- self -> task_tid = _Py_ThreadId ();
2375- #endif
23762376 self -> task_must_cancel = 0 ;
23772377 self -> task_log_destroy_pending = 1 ;
23782378 self -> task_num_cancels_requested = 0 ;
@@ -4009,7 +4009,6 @@ add_tasks_llist(struct llist_node *head, PyListObject *tasks)
40094009 struct llist_node * node ;
40104010 llist_for_each_safe (node , head ) {
40114011 TaskObj * task = llist_data (node , TaskObj , task_node );
4012- assert (task -> task_state == STATE_PENDING );
40134012 // The linked list holds borrowed references to task
40144013 // as such it is possible that the task is concurrently
40154014 // deallocated while added to this list.
0 commit comments