From 482219028d32794fe2d727a7a6059068c63377b7 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Thu, 11 Jul 2024 20:20:01 +0800 Subject: [PATCH 1/9] Use PyMutex for writes to asyncio state --- Modules/_asynciomodule.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 87ad236cdbb39f..02a8cfa00950e7 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -81,6 +81,7 @@ typedef struct futureiterobject futureiterobject; /* State of the _asyncio module */ typedef struct { + PyMutex mutex; PyTypeObject *FutureIterType; PyTypeObject *TaskStepMethWrapper_Type; PyTypeObject *FutureType; @@ -341,8 +342,10 @@ get_running_loop(asyncio_state *state, PyObject **loop) } } + PyMutex_Lock(&state->mutex); state->cached_running_loop = rl; state->cached_running_loop_tsid = ts_id; + PyMutex_Unlock(&state->mutex); } @@ -384,8 +387,10 @@ set_running_loop(asyncio_state *state, PyObject *loop) return -1; } + PyMutex_Lock(&state->mutex); state->cached_running_loop = loop; // borrowed, kept alive by ts_dict state->cached_running_loop_tsid = PyThreadState_GetID(tstate); + PyMutex_Unlock(&state->mutex); return 0; } @@ -1668,9 +1673,11 @@ FutureIter_dealloc(futureiterobject *it) } if (state && state->fi_freelist_len < FI_FREELIST_MAXLEN) { + PyMutex_Lock(&state->mutex); state->fi_freelist_len++; it->future = (FutureObj*) state->fi_freelist; state->fi_freelist = it; + PyMutex_Unlock(&state->mutex); } else { PyObject_GC_Del(it); @@ -1877,9 +1884,11 @@ future_new_iter(PyObject *fut) ENSURE_FUTURE_ALIVE(state, fut) if (state->fi_freelist_len) { + PyMutex_Lock(&state->mutex); state->fi_freelist_len--; it = state->fi_freelist; state->fi_freelist = (futureiterobject*) it->future; + PyMutex_Unlock(&state->mutex); it->future = NULL; _Py_NewReference((PyObject*) it); } @@ -2028,8 +2037,10 @@ register_task(asyncio_state *state, TaskObj *task) assert(state->asyncio_tasks.head != NULL); task->next = state->asyncio_tasks.head; + PyMutex_Lock(&state->mutex); state->asyncio_tasks.head->prev = task; state->asyncio_tasks.head = task; + PyMutex_Unlock(&state->mutex); } static int @@ -2052,7 +2063,9 @@ unregister_task(asyncio_state *state, TaskObj *task) task->next->prev = task->prev; if (task->prev == NULL) { assert(state->asyncio_tasks.head == task); + PyMutex_Lock(&state->mutex); state->asyncio_tasks.head = task->next; + PyMutex_Unlock(&state->mutex); } else { task->prev->next = task->next; } @@ -2213,7 +2226,9 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop, // optimization: defer task name formatting // store the task counter as PyLong in the name // for deferred formatting in get_name + PyMutex_Lock(&state->mutex); name = PyLong_FromUnsignedLongLong(++state->task_name_counter); + PyMutex_Unlock(&state->mutex); } else if (!PyUnicode_CheckExact(name)) { name = PyObject_Str(name); } else { @@ -3750,6 +3765,7 @@ module_free_freelists(asyncio_state *state) PyObject *current; next = (PyObject*) state->fi_freelist; + PyMutex_Lock(&state->mutex); while (next != NULL) { assert(state->fi_freelist_len > 0); state->fi_freelist_len--; @@ -3760,6 +3776,7 @@ module_free_freelists(asyncio_state *state) } assert(state->fi_freelist_len == 0); state->fi_freelist = NULL; + PyMutex_Unlock(&state->mutex); } static int @@ -3844,6 +3861,7 @@ module_init(asyncio_state *state) { PyObject *module = NULL; + PyMutex_Lock(&state->mutex); state->asyncio_mod = PyImport_ImportModule("asyncio"); if (state->asyncio_mod == NULL) { goto fail; @@ -3913,10 +3931,13 @@ module_init(asyncio_state *state) goto fail; } + PyMutex_Unlock(&state->mutex); + Py_DECREF(module); return 0; fail: + PyMutex_Unlock(&state->mutex); Py_CLEAR(module); return -1; @@ -3947,9 +3968,12 @@ static int module_exec(PyObject *mod) { asyncio_state *state = get_asyncio_state(mod); + + PyMutex_Lock(&state->mutex); Py_SET_TYPE(&state->asyncio_tasks.tail, state->TaskType); _Py_SetImmortalUntracked((PyObject *)&state->asyncio_tasks.tail); state->asyncio_tasks.head = &state->asyncio_tasks.tail; + PyMutex_Unlock(&state->mutex); #define CREATE_TYPE(m, tp, spec, base) \ do { \ From 143747b8a011c3403bb78d0a1afcdeb8d01711da Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Fri, 12 Jul 2024 22:54:34 +0800 Subject: [PATCH 2/9] Address review --- .../internal/pycore_pyatomic_ft_wrappers.h | 2 + Modules/_asynciomodule.c | 46 +++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Include/internal/pycore_pyatomic_ft_wrappers.h b/Include/internal/pycore_pyatomic_ft_wrappers.h index a1bb383bcd22e9..d0426ec700fa1e 100644 --- a/Include/internal/pycore_pyatomic_ft_wrappers.h +++ b/Include/internal/pycore_pyatomic_ft_wrappers.h @@ -20,6 +20,7 @@ extern "C" { #endif #ifdef Py_GIL_DISABLED +#define FT_ATOMIC_ADD_UINT64(value, new_value) _Py_atomic_add_uint64(&value, new_value) #define FT_ATOMIC_LOAD_PTR(value) _Py_atomic_load_ptr(&value) #define FT_ATOMIC_STORE_PTR(value, new_value) _Py_atomic_store_ptr(&value, new_value) #define FT_ATOMIC_LOAD_SSIZE(value) _Py_atomic_load_ssize(&value) @@ -63,6 +64,7 @@ extern "C" { _Py_atomic_store_uint32_relaxed(&value, new_value) #else +#define FT_ATOMIC_ADD_UINT64(value, new_value) value += new_value #define FT_ATOMIC_LOAD_PTR(value) value #define FT_ATOMIC_STORE_PTR(value, new_value) value = new_value #define FT_ATOMIC_LOAD_SSIZE(value) value diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 02a8cfa00950e7..6cf36597c89dc5 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -77,11 +77,21 @@ typedef struct { #define FI_FREELIST_MAXLEN 255 +#ifdef Py_GIL_DISABLED +# define ASYNCIO_STATE_LOCK(state) PyMutex_Lock(&state->mutex) +# define ASYNCIO_STATE_UNLOCK(state) PyMutex_Unlock(&state->mutex) +#else +# define ASYNCIO_STATE_LOCK(state) (void(state)) +# define ASYNCIO_STATE_UNLOCK(state) (void(state)) +#endif + typedef struct futureiterobject futureiterobject; /* State of the _asyncio module */ typedef struct { +#ifdef Py_GIL_DISABLED PyMutex mutex; +#endif PyTypeObject *FutureIterType; PyTypeObject *TaskStepMethWrapper_Type; PyTypeObject *FutureType; @@ -342,10 +352,10 @@ get_running_loop(asyncio_state *state, PyObject **loop) } } - PyMutex_Lock(&state->mutex); + // TODO GH-121621: The should be moved to PyThreadState + // for easier and quicker access. state->cached_running_loop = rl; state->cached_running_loop_tsid = ts_id; - PyMutex_Unlock(&state->mutex); } @@ -387,11 +397,11 @@ set_running_loop(asyncio_state *state, PyObject *loop) return -1; } - PyMutex_Lock(&state->mutex); + + // TODO GH-121621: The should be moved to PyThreadState + // for easier and quicker access. state->cached_running_loop = loop; // borrowed, kept alive by ts_dict state->cached_running_loop_tsid = PyThreadState_GetID(tstate); - PyMutex_Unlock(&state->mutex); - return 0; } @@ -1672,12 +1682,11 @@ FutureIter_dealloc(futureiterobject *it) state = get_asyncio_state(module); } + // TODO GH-121621: This should be moved to thread state as well. if (state && state->fi_freelist_len < FI_FREELIST_MAXLEN) { - PyMutex_Lock(&state->mutex); state->fi_freelist_len++; it->future = (FutureObj*) state->fi_freelist; state->fi_freelist = it; - PyMutex_Unlock(&state->mutex); } else { PyObject_GC_Del(it); @@ -1884,11 +1893,9 @@ future_new_iter(PyObject *fut) ENSURE_FUTURE_ALIVE(state, fut) if (state->fi_freelist_len) { - PyMutex_Lock(&state->mutex); state->fi_freelist_len--; it = state->fi_freelist; state->fi_freelist = (futureiterobject*) it->future; - PyMutex_Unlock(&state->mutex); it->future = NULL; _Py_NewReference((PyObject*) it); } @@ -2027,6 +2034,7 @@ static PyMethodDef TaskWakeupDef = { static void register_task(asyncio_state *state, TaskObj *task) { + ASYNCIO_STATE_LOCK(state); assert(Task_Check(state, task)); assert(task != &state->asyncio_tasks.tail); if (task->next != NULL) { @@ -2037,10 +2045,9 @@ register_task(asyncio_state *state, TaskObj *task) assert(state->asyncio_tasks.head != NULL); task->next = state->asyncio_tasks.head; - PyMutex_Lock(&state->mutex); state->asyncio_tasks.head->prev = task; state->asyncio_tasks.head = task; - PyMutex_Unlock(&state->mutex); + ASYNCIO_STATE_UNLOCK(state); } static int @@ -2060,15 +2067,15 @@ unregister_task(asyncio_state *state, TaskObj *task) assert(state->asyncio_tasks.head != task); return; } + ASYNCIO_STATE_LOCK(state); task->next->prev = task->prev; if (task->prev == NULL) { assert(state->asyncio_tasks.head == task); - PyMutex_Lock(&state->mutex); state->asyncio_tasks.head = task->next; - PyMutex_Unlock(&state->mutex); } else { task->prev->next = task->next; } + ASYNCIO_STATE_UNLOCK(state); task->next = NULL; task->prev = NULL; assert(state->asyncio_tasks.head != task); @@ -2226,9 +2233,8 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop, // optimization: defer task name formatting // store the task counter as PyLong in the name // for deferred formatting in get_name - PyMutex_Lock(&state->mutex); - name = PyLong_FromUnsignedLongLong(++state->task_name_counter); - PyMutex_Unlock(&state->mutex); + FT_ATOMIC_ADD_UINT64(state->task_name_counter, 1); + name = PyLong_FromUnsignedLongLong(state->task_name_counter); } else if (!PyUnicode_CheckExact(name)) { name = PyObject_Str(name); } else { @@ -3765,7 +3771,6 @@ module_free_freelists(asyncio_state *state) PyObject *current; next = (PyObject*) state->fi_freelist; - PyMutex_Lock(&state->mutex); while (next != NULL) { assert(state->fi_freelist_len > 0); state->fi_freelist_len--; @@ -3776,7 +3781,6 @@ module_free_freelists(asyncio_state *state) } assert(state->fi_freelist_len == 0); state->fi_freelist = NULL; - PyMutex_Unlock(&state->mutex); } static int @@ -3861,7 +3865,6 @@ module_init(asyncio_state *state) { PyObject *module = NULL; - PyMutex_Lock(&state->mutex); state->asyncio_mod = PyImport_ImportModule("asyncio"); if (state->asyncio_mod == NULL) { goto fail; @@ -3931,13 +3934,10 @@ module_init(asyncio_state *state) goto fail; } - PyMutex_Unlock(&state->mutex); - Py_DECREF(module); return 0; fail: - PyMutex_Unlock(&state->mutex); Py_CLEAR(module); return -1; @@ -3969,11 +3969,9 @@ module_exec(PyObject *mod) { asyncio_state *state = get_asyncio_state(mod); - PyMutex_Lock(&state->mutex); Py_SET_TYPE(&state->asyncio_tasks.tail, state->TaskType); _Py_SetImmortalUntracked((PyObject *)&state->asyncio_tasks.tail); state->asyncio_tasks.head = &state->asyncio_tasks.tail; - PyMutex_Unlock(&state->mutex); #define CREATE_TYPE(m, tp, spec, base) \ do { \ From 580304cf2db3b0066d62123901c759f85764b787 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Fri, 12 Jul 2024 22:58:03 +0800 Subject: [PATCH 3/9] fix default build --- Modules/_asynciomodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 6cf36597c89dc5..53ae02094c00de 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -81,8 +81,8 @@ typedef struct { # define ASYNCIO_STATE_LOCK(state) PyMutex_Lock(&state->mutex) # define ASYNCIO_STATE_UNLOCK(state) PyMutex_Unlock(&state->mutex) #else -# define ASYNCIO_STATE_LOCK(state) (void(state)) -# define ASYNCIO_STATE_UNLOCK(state) (void(state)) +# define ASYNCIO_STATE_LOCK(state) ((void)state)) +# define ASYNCIO_STATE_UNLOCK(state) ((void)state) #endif typedef struct futureiterobject futureiterobject; From 1faed1225ee0ef74f025d5d4150fc7cab2baf3ab Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Fri, 12 Jul 2024 23:14:52 +0800 Subject: [PATCH 4/9] Fix typo --- Modules/_asynciomodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 53ae02094c00de..6a1a3b50cd255a 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -81,7 +81,7 @@ typedef struct { # define ASYNCIO_STATE_LOCK(state) PyMutex_Lock(&state->mutex) # define ASYNCIO_STATE_UNLOCK(state) PyMutex_Unlock(&state->mutex) #else -# define ASYNCIO_STATE_LOCK(state) ((void)state)) +# define ASYNCIO_STATE_LOCK(state) ((void)state) # define ASYNCIO_STATE_UNLOCK(state) ((void)state) #endif From ba3d77174807733e3d6dd0e5f703db161e88bd0c Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sat, 13 Jul 2024 01:47:17 +0800 Subject: [PATCH 5/9] Address review --- .../internal/pycore_pyatomic_ft_wrappers.h | 2 -- Modules/_asynciomodule.c | 24 ++++++++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Include/internal/pycore_pyatomic_ft_wrappers.h b/Include/internal/pycore_pyatomic_ft_wrappers.h index d0426ec700fa1e..a1bb383bcd22e9 100644 --- a/Include/internal/pycore_pyatomic_ft_wrappers.h +++ b/Include/internal/pycore_pyatomic_ft_wrappers.h @@ -20,7 +20,6 @@ extern "C" { #endif #ifdef Py_GIL_DISABLED -#define FT_ATOMIC_ADD_UINT64(value, new_value) _Py_atomic_add_uint64(&value, new_value) #define FT_ATOMIC_LOAD_PTR(value) _Py_atomic_load_ptr(&value) #define FT_ATOMIC_STORE_PTR(value, new_value) _Py_atomic_store_ptr(&value, new_value) #define FT_ATOMIC_LOAD_SSIZE(value) _Py_atomic_load_ssize(&value) @@ -64,7 +63,6 @@ extern "C" { _Py_atomic_store_uint32_relaxed(&value, new_value) #else -#define FT_ATOMIC_ADD_UINT64(value, new_value) value += new_value #define FT_ATOMIC_LOAD_PTR(value) value #define FT_ATOMIC_STORE_PTR(value, new_value) value = new_value #define FT_ATOMIC_LOAD_SSIZE(value) value diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 6a1a3b50cd255a..4caf59e158c33c 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -2039,6 +2039,7 @@ register_task(asyncio_state *state, TaskObj *task) assert(task != &state->asyncio_tasks.tail); if (task->next != NULL) { // already registered + ASYNCIO_STATE_UNLOCK(state); return; } assert(task->prev == NULL); @@ -2057,7 +2058,7 @@ register_eager_task(asyncio_state *state, PyObject *task) } static void -unregister_task(asyncio_state *state, TaskObj *task) +unregister_task_no_lock(asyncio_state *state, TaskObj *task) { assert(Task_Check(state, task)); assert(task != &state->asyncio_tasks.tail); @@ -2067,7 +2068,7 @@ unregister_task(asyncio_state *state, TaskObj *task) assert(state->asyncio_tasks.head != task); return; } - ASYNCIO_STATE_LOCK(state); + task->next->prev = task->prev; if (task->prev == NULL) { assert(state->asyncio_tasks.head == task); @@ -2075,12 +2076,20 @@ unregister_task(asyncio_state *state, TaskObj *task) } else { task->prev->next = task->next; } - ASYNCIO_STATE_UNLOCK(state); + task->next = NULL; task->prev = NULL; assert(state->asyncio_tasks.head != task); } +static void +unregister_task(asyncio_state *state, TaskObj *task) +{ + ASYNCIO_STATE_LOCK(state); + unregister_task_no_lock(state, task); + ASYNCIO_STATE_UNLOCK(state); +} + static int unregister_eager_task(asyncio_state *state, PyObject *task) { @@ -2233,8 +2242,12 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop, // optimization: defer task name formatting // store the task counter as PyLong in the name // for deferred formatting in get_name - FT_ATOMIC_ADD_UINT64(state->task_name_counter, 1); - name = PyLong_FromUnsignedLongLong(state->task_name_counter); +#ifdef Py_GIL_DISABLED + unsigned long long counter = _Py_atomic_add_uint64(&state->task_name_counter, 1) + 1; +#else + unsigned long long counter = ++state->task_name_counter; +#endif + name = PyLong_FromUnsignedLongLong(counter); } else if (!PyUnicode_CheckExact(name)) { name = PyObject_Str(name); } else { @@ -3968,7 +3981,6 @@ static int module_exec(PyObject *mod) { asyncio_state *state = get_asyncio_state(mod); - Py_SET_TYPE(&state->asyncio_tasks.tail, state->TaskType); _Py_SetImmortalUntracked((PyObject *)&state->asyncio_tasks.tail); state->asyncio_tasks.head = &state->asyncio_tasks.tail; From ec2c175706f681cabf81562fe4fcc928289039ed Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sat, 13 Jul 2024 01:48:40 +0800 Subject: [PATCH 6/9] fixup whitespace --- Modules/_asynciomodule.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 4caf59e158c33c..4214e6b1a1df14 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -402,6 +402,7 @@ set_running_loop(asyncio_state *state, PyObject *loop) // for easier and quicker access. state->cached_running_loop = loop; // borrowed, kept alive by ts_dict state->cached_running_loop_tsid = PyThreadState_GetID(tstate); + return 0; } @@ -2068,7 +2069,6 @@ unregister_task_no_lock(asyncio_state *state, TaskObj *task) assert(state->asyncio_tasks.head != task); return; } - task->next->prev = task->prev; if (task->prev == NULL) { assert(state->asyncio_tasks.head == task); @@ -2076,7 +2076,6 @@ unregister_task_no_lock(asyncio_state *state, TaskObj *task) } else { task->prev->next = task->next; } - task->next = NULL; task->prev = NULL; assert(state->asyncio_tasks.head != task); From e1b730a0a38e7bbfe691a7c5ae335fdefeb5186b Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sat, 13 Jul 2024 02:11:15 +0800 Subject: [PATCH 7/9] minor nit --- Modules/_asynciomodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 4214e6b1a1df14..0782b0e4e529f8 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -2059,7 +2059,7 @@ register_eager_task(asyncio_state *state, PyObject *task) } static void -unregister_task_no_lock(asyncio_state *state, TaskObj *task) +unregister_task_lock_held(asyncio_state *state, TaskObj *task) { assert(Task_Check(state, task)); assert(task != &state->asyncio_tasks.tail); @@ -2085,7 +2085,7 @@ static void unregister_task(asyncio_state *state, TaskObj *task) { ASYNCIO_STATE_LOCK(state); - unregister_task_no_lock(state, task); + unregister_task_lock_held(state, task); ASYNCIO_STATE_UNLOCK(state); } From 8d00ede4449800ba880cb8fa0c998e484337afc7 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sun, 14 Jul 2024 19:26:05 +0800 Subject: [PATCH 8/9] Inline state lock into unregister_task --- Modules/_asynciomodule.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 0782b0e4e529f8..b142f9a446dd2f 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -2059,14 +2059,16 @@ register_eager_task(asyncio_state *state, PyObject *task) } static void -unregister_task_lock_held(asyncio_state *state, TaskObj *task) +unregister_task(asyncio_state *state, TaskObj *task) { + ASYNCIO_STATE_LOCK(state); assert(Task_Check(state, task)); assert(task != &state->asyncio_tasks.tail); if (task->next == NULL) { // not registered assert(task->prev == NULL); assert(state->asyncio_tasks.head != task); + ASYNCIO_STATE_UNLOCK(state); return; } task->next->prev = task->prev; @@ -2079,13 +2081,6 @@ unregister_task_lock_held(asyncio_state *state, TaskObj *task) task->next = NULL; task->prev = NULL; assert(state->asyncio_tasks.head != task); -} - -static void -unregister_task(asyncio_state *state, TaskObj *task) -{ - ASYNCIO_STATE_LOCK(state); - unregister_task_lock_held(state, task); ASYNCIO_STATE_UNLOCK(state); } From c03112243f446ab99192395ac11bbaa58eaf07e8 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sun, 14 Jul 2024 17:28:41 +0530 Subject: [PATCH 9/9] Apply suggestions from code review --- Modules/_asynciomodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index b142f9a446dd2f..105dd8f961146e 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -352,7 +352,7 @@ get_running_loop(asyncio_state *state, PyObject **loop) } } - // TODO GH-121621: The should be moved to PyThreadState + // TODO GH-121621: This should be moved to PyThreadState // for easier and quicker access. state->cached_running_loop = rl; state->cached_running_loop_tsid = ts_id; @@ -398,7 +398,7 @@ set_running_loop(asyncio_state *state, PyObject *loop) } - // TODO GH-121621: The should be moved to PyThreadState + // TODO GH-121621: This should be moved to PyThreadState // for easier and quicker access. state->cached_running_loop = loop; // borrowed, kept alive by ts_dict state->cached_running_loop_tsid = PyThreadState_GetID(tstate);