[Python-checkins] bpo-46008: Move thread-related interpreter state into a sub-struct. (gh-29971)

ericsnowcurrently webhook-mailer at python.org
Tue Dec 7 16:03:59 EST 2021


https://github.com/python/cpython/commit/313f92a57bc3887026ec16adb536bb2b7580ce47
commit: 313f92a57bc3887026ec16adb536bb2b7580ce47
branch: main
author: Eric Snow <ericsnowcurrently at gmail.com>
committer: ericsnowcurrently <ericsnowcurrently at gmail.com>
date: 2021-12-07T14:03:47-07:00
summary:

bpo-46008: Move thread-related interpreter state into a sub-struct. (gh-29971)

This parallels _PyRuntimeState.interpreters.  Doing this helps make it more clear what part of PyInterpreterState relates to its threads.

https://bugs.python.org/issue46008

files:
M Include/internal/pycore_interp.h
M Modules/_threadmodule.c
M Python/ceval.c
M Python/pylifecycle.c
M Python/pystate.c
M Python/thread.c
M Python/thread_nt.h
M Python/thread_pthread.h

diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h
index f52ee594106f9..53938e3d7bc09 100644
--- a/Include/internal/pycore_interp.h
+++ b/Include/internal/pycore_interp.h
@@ -238,7 +238,19 @@ struct type_cache {
 struct _is {
 
     struct _is *next;
-    struct _ts *tstate_head;
+
+    struct pythreads {
+        int _preallocated_used;
+        uint64_t next_unique_id;
+        struct _ts *head;
+        /* Used in Modules/_threadmodule.c. */
+        long count;
+        /* Support for runtime thread stack size tuning.
+           A value of 0 means using the platform's default stack size
+           or the size specified by the THREAD_STACK_SIZE macro. */
+        /* Used in Python/thread.c. */
+        size_t stacksize;
+    } threads;
 
     /* Reference to the _PyRuntime global variable. This field exists
        to not have to pass runtime in addition to tstate to a function.
@@ -268,14 +280,6 @@ struct _is {
     // (-1: "off", 1: "on", 0: no override)
     int override_frozen_modules;
 
-    /* Used in Modules/_threadmodule.c. */
-    long num_threads;
-    /* Support for runtime thread stack size tuning.
-       A value of 0 means using the platform's default stack size
-       or the size specified by the THREAD_STACK_SIZE macro. */
-    /* Used in Python/thread.c. */
-    size_t pythread_stacksize;
-
     PyObject *codec_search_path;
     PyObject *codec_search_cache;
     PyObject *codec_error_registry;
@@ -302,8 +306,6 @@ struct _is {
     PyObject *after_forkers_child;
 #endif
 
-    uint64_t tstate_next_unique_id;
-
     struct _warnings_runtime_state warnings;
     struct atexit_state atexit;
 
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index 39b116afcaa3e..2ba081d92b9af 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -3,7 +3,7 @@
 /* Interface to Sjoerd's portable C thread library */
 
 #include "Python.h"
-#include "pycore_interp.h"        // _PyInterpreterState.num_threads
+#include "pycore_interp.h"        // _PyInterpreterState.threads.count
 #include "pycore_moduleobject.h"  // _PyModule_GetState()
 #include "pycore_pylifecycle.h"
 #include "pycore_pystate.h"       // _PyThreadState_Init()
@@ -1089,7 +1089,7 @@ thread_run(void *boot_raw)
 #endif
     _PyThreadState_Init(tstate);
     PyEval_AcquireThread(tstate);
-    tstate->interp->num_threads++;
+    tstate->interp->threads.count++;
 
     PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs);
     if (res == NULL) {
@@ -1105,7 +1105,7 @@ thread_run(void *boot_raw)
     }
 
     thread_bootstate_free(boot);
-    tstate->interp->num_threads--;
+    tstate->interp->threads.count--;
     PyThreadState_Clear(tstate);
     _PyThreadState_DeleteCurrent(tstate);
 
@@ -1279,7 +1279,7 @@ static PyObject *
 thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
 {
     PyInterpreterState *interp = _PyInterpreterState_GET();
-    return PyLong_FromLong(interp->num_threads);
+    return PyLong_FromLong(interp->threads.count);
 }
 
 PyDoc_STRVAR(_count_doc,
diff --git a/Python/ceval.c b/Python/ceval.c
index 36d1360015ceb..2e40c0f5b391a 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -784,7 +784,7 @@ Py_SetRecursionLimit(int new_limit)
 {
     PyInterpreterState *interp = _PyInterpreterState_GET();
     interp->ceval.recursion_limit = new_limit;
-    for (PyThreadState *p = interp->tstate_head; p != NULL; p = p->next) {
+    for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) {
         int depth = p->recursion_limit - p->recursion_remaining;
         p->recursion_limit = new_limit;
         p->recursion_remaining = new_limit - depth;
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 84b76ea3275a7..f648ddab0388f 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -2043,7 +2043,7 @@ Py_EndInterpreter(PyThreadState *tstate)
 
     _PyAtExit_Call(tstate->interp);
 
-    if (tstate != interp->tstate_head || tstate->next != NULL) {
+    if (tstate != interp->threads.head || tstate->next != NULL) {
         Py_FatalError("not the last thread");
     }
 
diff --git a/Python/pystate.c b/Python/pystate.c
index a0bd05077ee15..4dd4cab249725 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -271,7 +271,7 @@ PyInterpreterState_New(void)
         return NULL;
     }
 
-    interp->tstate_next_unique_id = 0;
+    interp->threads.next_unique_id = 0;
 
     interp->audit_hooks = NULL;
 
@@ -297,7 +297,7 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
     }
 
     HEAD_LOCK(runtime);
-    for (PyThreadState *p = interp->tstate_head; p != NULL; p = p->next) {
+    for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) {
         PyThreadState_Clear(p);
     }
     HEAD_UNLOCK(runtime);
@@ -371,7 +371,7 @@ zapthreads(PyInterpreterState *interp, int check_current)
     PyThreadState *tstate;
     /* No need to lock the mutex here because this should only happen
        when the threads are all really dead (XXX famous last words). */
-    while ((tstate = interp->tstate_head) != NULL) {
+    while ((tstate = interp->threads.head) != NULL) {
         _PyThreadState_Delete(tstate, check_current);
     }
 }
@@ -399,7 +399,7 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
             break;
         }
     }
-    if (interp->tstate_head != NULL) {
+    if (interp->threads.head != NULL) {
         Py_FatalError("remaining threads");
     }
     *p = interp->next;
@@ -702,12 +702,12 @@ new_threadstate(PyInterpreterState *interp, int init)
     }
 
     HEAD_LOCK(runtime);
-    tstate->id = ++interp->tstate_next_unique_id;
+    tstate->id = ++interp->threads.next_unique_id;
     tstate->prev = NULL;
-    tstate->next = interp->tstate_head;
+    tstate->next = interp->threads.head;
     if (tstate->next)
         tstate->next->prev = tstate;
-    interp->tstate_head = tstate;
+    interp->threads.head = tstate;
     HEAD_UNLOCK(runtime);
 
     return tstate;
@@ -930,7 +930,7 @@ tstate_delete_common(PyThreadState *tstate,
         tstate->prev->next = tstate->next;
     }
     else {
-        interp->tstate_head = tstate->next;
+        interp->threads.head = tstate->next;
     }
     if (tstate->next) {
         tstate->next->prev = tstate->prev;
@@ -1008,7 +1008,7 @@ _PyThreadState_DeleteExcept(_PyRuntimeState *runtime, PyThreadState *tstate)
     /* Remove all thread states, except tstate, from the linked list of
        thread states.  This will allow calling PyThreadState_Clear()
        without holding the lock. */
-    PyThreadState *list = interp->tstate_head;
+    PyThreadState *list = interp->threads.head;
     if (list == tstate) {
         list = tstate->next;
     }
@@ -1019,7 +1019,7 @@ _PyThreadState_DeleteExcept(_PyRuntimeState *runtime, PyThreadState *tstate)
         tstate->next->prev = tstate->prev;
     }
     tstate->prev = tstate->next = NULL;
-    interp->tstate_head = tstate;
+    interp->threads.head = tstate;
     HEAD_UNLOCK(runtime);
 
     /* Clear and deallocate all stale thread states.  Even if this
@@ -1180,7 +1180,7 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
      * head_mutex for the duration.
      */
     HEAD_LOCK(runtime);
-    for (PyThreadState *tstate = interp->tstate_head; tstate != NULL; tstate = tstate->next) {
+    for (PyThreadState *tstate = interp->threads.head; tstate != NULL; tstate = tstate->next) {
         if (tstate->thread_id != id) {
             continue;
         }
@@ -1244,7 +1244,7 @@ PyInterpreterState_Next(PyInterpreterState *interp) {
 
 PyThreadState *
 PyInterpreterState_ThreadHead(PyInterpreterState *interp) {
-    return interp->tstate_head;
+    return interp->threads.head;
 }
 
 PyThreadState *
@@ -1281,7 +1281,7 @@ _PyThread_CurrentFrames(void)
     PyInterpreterState *i;
     for (i = runtime->interpreters.head; i != NULL; i = i->next) {
         PyThreadState *t;
-        for (t = i->tstate_head; t != NULL; t = t->next) {
+        for (t = i->threads.head; t != NULL; t = t->next) {
             InterpreterFrame *frame = t->cframe->current_frame;
             if (frame == NULL) {
                 continue;
@@ -1334,7 +1334,7 @@ _PyThread_CurrentExceptions(void)
     PyInterpreterState *i;
     for (i = runtime->interpreters.head; i != NULL; i = i->next) {
         PyThreadState *t;
-        for (t = i->tstate_head; t != NULL; t = t->next) {
+        for (t = i->threads.head; t != NULL; t = t->next) {
             _PyErr_StackItem *err_info = _PyErr_GetTopmostException(t);
             if (err_info == NULL) {
                 continue;
diff --git a/Python/thread.c b/Python/thread.c
index dfe28b6bdb680..b1c0cfe84f28d 100644
--- a/Python/thread.c
+++ b/Python/thread.c
@@ -109,7 +109,7 @@ _PyThread_debug_deprecation(void)
 size_t
 PyThread_get_stacksize(void)
 {
-    return _PyInterpreterState_GET()->pythread_stacksize;
+    return _PyInterpreterState_GET()->threads.stacksize;
 }
 
 /* Only platforms defining a THREAD_SET_STACKSIZE() macro
diff --git a/Python/thread_nt.h b/Python/thread_nt.h
index 0dde1a0409738..084bd58731487 100644
--- a/Python/thread_nt.h
+++ b/Python/thread_nt.h
@@ -1,4 +1,4 @@
-#include "pycore_interp.h"    // _PyInterpreterState.pythread_stacksize
+#include "pycore_interp.h"    // _PyInterpreterState.threads.stacksize
 
 /* This code implemented by Dag.Gruneau at elsa.preseco.comm.se */
 /* Fast NonRecursiveMutex support by Yakov Markovitch, markovitch at iso.ru */
@@ -199,7 +199,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
     obj->func = func;
     obj->arg = arg;
     PyThreadState *tstate = _PyThreadState_GET();
-    size_t stacksize = tstate ? tstate->interp->pythread_stacksize : 0;
+    size_t stacksize = tstate ? tstate->interp->threads.stacksize : 0;
     hThread = (HANDLE)_beginthreadex(0,
                       Py_SAFE_DOWNCAST(stacksize, Py_ssize_t, unsigned int),
                       bootstrap, obj,
@@ -376,13 +376,13 @@ _pythread_nt_set_stacksize(size_t size)
 {
     /* set to default */
     if (size == 0) {
-        _PyInterpreterState_GET()->pythread_stacksize = 0;
+        _PyInterpreterState_GET()->threads.stacksize = 0;
         return 0;
     }
 
     /* valid range? */
     if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
-        _PyInterpreterState_GET()->pythread_stacksize = size;
+        _PyInterpreterState_GET()->threads.stacksize = size;
         return 0;
     }
 
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
index 12dad7e9e4427..c90ab25d4841d 100644
--- a/Python/thread_pthread.h
+++ b/Python/thread_pthread.h
@@ -1,4 +1,4 @@
-#include "pycore_interp.h"    // _PyInterpreterState.pythread_stacksize
+#include "pycore_interp.h"    // _PyInterpreterState.threads.stacksize
 
 /* Posix threads interface */
 
@@ -262,7 +262,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
 #endif
 #if defined(THREAD_STACK_SIZE)
     PyThreadState *tstate = _PyThreadState_GET();
-    size_t stacksize = tstate ? tstate->interp->pythread_stacksize : 0;
+    size_t stacksize = tstate ? tstate->interp->threads.stacksize : 0;
     tss = (stacksize != 0) ? stacksize : THREAD_STACK_SIZE;
     if (tss != 0) {
         if (pthread_attr_setstacksize(&attrs, tss) != 0) {
@@ -764,7 +764,7 @@ _pythread_pthread_set_stacksize(size_t size)
 
     /* set to default */
     if (size == 0) {
-        _PyInterpreterState_GET()->pythread_stacksize = 0;
+        _PyInterpreterState_GET()->threads.stacksize = 0;
         return 0;
     }
 
@@ -781,7 +781,7 @@ _pythread_pthread_set_stacksize(size_t size)
             rc = pthread_attr_setstacksize(&attrs, size);
             pthread_attr_destroy(&attrs);
             if (rc == 0) {
-                _PyInterpreterState_GET()->pythread_stacksize = size;
+                _PyInterpreterState_GET()->threads.stacksize = size;
                 return 0;
             }
         }



More information about the Python-checkins mailing list