bpo-36710: Add runtime parameter to _PyThreadState_Init() (GH-12935)

* Add 'runtime' parameter to _PyThreadState_Init()
* Add 'gilstate' parameter to _PyGILState_NoteThreadState()
* Move _PyThreadState_Init() and _PyThreadState_DeleteExcept()
   to the internal C API.
This commit is contained in:
Victor Stinner 2019-04-24 16:47:40 +02:00 committed by GitHub
parent 6c44fde3e0
commit 8bb3230149
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 95 additions and 82 deletions

View File

@ -155,8 +155,6 @@ PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void);
PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*); PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*);
PyAPI_FUNC(void) _PyState_ClearModules(void); PyAPI_FUNC(void) _PyState_ClearModules(void);
PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *); PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *);
PyAPI_FUNC(void) _PyThreadState_Init(PyThreadState *);
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate);
PyAPI_FUNC(void) _PyGILState_Reinit(void); PyAPI_FUNC(void) _PyGILState_Reinit(void);
/* Similar to PyThreadState_Get(), but don't issue a fatal error /* Similar to PyThreadState_Get(), but don't issue a fatal error

View File

@ -231,6 +231,11 @@ PyAPI_FUNC(void) _PyRuntime_Finalize(void);
/* Other */ /* Other */
PyAPI_FUNC(void) _PyThreadState_Init(
_PyRuntimeState *runtime,
PyThreadState *tstate);
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate);
PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *); PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *);
PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(void); PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(void);

View File

@ -994,7 +994,7 @@ t_bootstrap(void *boot_raw)
tstate = boot->tstate; tstate = boot->tstate;
tstate->thread_id = PyThread_get_thread_ident(); tstate->thread_id = PyThread_get_thread_ident();
_PyThreadState_Init(tstate); _PyThreadState_Init(&_PyRuntime, tstate);
PyEval_AcquireThread(tstate); PyEval_AcquireThread(tstate);
tstate->interp->num_threads++; tstate->interp->num_threads++;
res = PyObject_Call(boot->func, boot->args, boot->keyw); res = PyObject_Call(boot->func, boot->args, boot->keyw);

View File

@ -133,7 +133,9 @@ _PyRuntimeState_ReInitThreads(void)
WAIT_LOCK) WAIT_LOCK)
#define HEAD_UNLOCK() PyThread_release_lock(_PyRuntime.interpreters.mutex) #define HEAD_UNLOCK() PyThread_release_lock(_PyRuntime.interpreters.mutex)
static void _PyGILState_NoteThreadState(PyThreadState* tstate); /* Forward declaration */
static void _PyGILState_NoteThreadState(
struct _gilstate_runtime_state *gilstate, PyThreadState* tstate);
_PyInitError _PyInitError
_PyInterpreterState_Enable(_PyRuntimeState *runtime) _PyInterpreterState_Enable(_PyRuntimeState *runtime)
@ -487,71 +489,74 @@ static PyThreadState *
new_threadstate(PyInterpreterState *interp, int init) new_threadstate(PyInterpreterState *interp, int init)
{ {
PyThreadState *tstate = (PyThreadState *)PyMem_RawMalloc(sizeof(PyThreadState)); PyThreadState *tstate = (PyThreadState *)PyMem_RawMalloc(sizeof(PyThreadState));
if (tstate == NULL) {
if (_PyThreadState_GetFrame == NULL) return NULL;
_PyThreadState_GetFrame = threadstate_getframe;
if (tstate != NULL) {
tstate->interp = interp;
tstate->frame = NULL;
tstate->recursion_depth = 0;
tstate->overflowed = 0;
tstate->recursion_critical = 0;
tstate->stackcheck_counter = 0;
tstate->tracing = 0;
tstate->use_tracing = 0;
tstate->gilstate_counter = 0;
tstate->async_exc = NULL;
tstate->thread_id = PyThread_get_thread_ident();
tstate->dict = NULL;
tstate->curexc_type = NULL;
tstate->curexc_value = NULL;
tstate->curexc_traceback = NULL;
tstate->exc_state.exc_type = NULL;
tstate->exc_state.exc_value = NULL;
tstate->exc_state.exc_traceback = NULL;
tstate->exc_state.previous_item = NULL;
tstate->exc_info = &tstate->exc_state;
tstate->c_profilefunc = NULL;
tstate->c_tracefunc = NULL;
tstate->c_profileobj = NULL;
tstate->c_traceobj = NULL;
tstate->trash_delete_nesting = 0;
tstate->trash_delete_later = NULL;
tstate->on_delete = NULL;
tstate->on_delete_data = NULL;
tstate->coroutine_origin_tracking_depth = 0;
tstate->coroutine_wrapper = NULL;
tstate->in_coroutine_wrapper = 0;
tstate->async_gen_firstiter = NULL;
tstate->async_gen_finalizer = NULL;
tstate->context = NULL;
tstate->context_ver = 1;
tstate->id = ++interp->tstate_next_unique_id;
if (init)
_PyThreadState_Init(tstate);
HEAD_LOCK();
tstate->prev = NULL;
tstate->next = interp->tstate_head;
if (tstate->next)
tstate->next->prev = tstate;
interp->tstate_head = tstate;
HEAD_UNLOCK();
} }
if (_PyThreadState_GetFrame == NULL) {
_PyThreadState_GetFrame = threadstate_getframe;
}
tstate->interp = interp;
tstate->frame = NULL;
tstate->recursion_depth = 0;
tstate->overflowed = 0;
tstate->recursion_critical = 0;
tstate->stackcheck_counter = 0;
tstate->tracing = 0;
tstate->use_tracing = 0;
tstate->gilstate_counter = 0;
tstate->async_exc = NULL;
tstate->thread_id = PyThread_get_thread_ident();
tstate->dict = NULL;
tstate->curexc_type = NULL;
tstate->curexc_value = NULL;
tstate->curexc_traceback = NULL;
tstate->exc_state.exc_type = NULL;
tstate->exc_state.exc_value = NULL;
tstate->exc_state.exc_traceback = NULL;
tstate->exc_state.previous_item = NULL;
tstate->exc_info = &tstate->exc_state;
tstate->c_profilefunc = NULL;
tstate->c_tracefunc = NULL;
tstate->c_profileobj = NULL;
tstate->c_traceobj = NULL;
tstate->trash_delete_nesting = 0;
tstate->trash_delete_later = NULL;
tstate->on_delete = NULL;
tstate->on_delete_data = NULL;
tstate->coroutine_origin_tracking_depth = 0;
tstate->coroutine_wrapper = NULL;
tstate->in_coroutine_wrapper = 0;
tstate->async_gen_firstiter = NULL;
tstate->async_gen_finalizer = NULL;
tstate->context = NULL;
tstate->context_ver = 1;
tstate->id = ++interp->tstate_next_unique_id;
if (init) {
_PyThreadState_Init(&_PyRuntime, tstate);
}
HEAD_LOCK();
tstate->prev = NULL;
tstate->next = interp->tstate_head;
if (tstate->next)
tstate->next->prev = tstate;
interp->tstate_head = tstate;
HEAD_UNLOCK();
return tstate; return tstate;
} }
@ -568,9 +573,9 @@ _PyThreadState_Prealloc(PyInterpreterState *interp)
} }
void void
_PyThreadState_Init(PyThreadState *tstate) _PyThreadState_Init(_PyRuntimeState *runtime, PyThreadState *tstate)
{ {
_PyGILState_NoteThreadState(tstate); _PyGILState_NoteThreadState(&runtime->gilstate, tstate);
} }
PyObject* PyObject*
@ -1037,17 +1042,23 @@ PyThreadState_IsCurrent(PyThreadState *tstate)
Py_Initialize/Py_FinalizeEx Py_Initialize/Py_FinalizeEx
*/ */
void void
_PyGILState_Init(PyInterpreterState *i, PyThreadState *t) _PyGILState_Init(PyInterpreterState *interp, PyThreadState *tstate)
{ {
assert(i && t); /* must init with valid states */ /* must init with valid states */
if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) { assert(interp != NULL);
assert(tstate != NULL);
_PyRuntimeState *runtime = &_PyRuntime;
struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) {
Py_FatalError("Could not allocate TSS entry"); Py_FatalError("Could not allocate TSS entry");
} }
_PyRuntime.gilstate.autoInterpreterState = i; gilstate->autoInterpreterState = interp;
assert(PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == NULL); assert(PyThread_tss_get(&gilstate->autoTSSkey) == NULL);
assert(t->gilstate_counter == 0); assert(tstate->gilstate_counter == 0);
_PyGILState_NoteThreadState(t); _PyGILState_NoteThreadState(gilstate, tstate);
} }
PyInterpreterState * PyInterpreterState *
@ -1104,13 +1115,14 @@ _PyGILState_Reinit(void)
a better fix for SF bug #1010677 than the first one attempted). a better fix for SF bug #1010677 than the first one attempted).
*/ */
static void static void
_PyGILState_NoteThreadState(PyThreadState* tstate) _PyGILState_NoteThreadState(struct _gilstate_runtime_state *gilstate, PyThreadState* tstate)
{ {
/* If autoTSSkey isn't initialized, this must be the very first /* If autoTSSkey isn't initialized, this must be the very first
threadstate created in Py_Initialize(). Don't do anything for now threadstate created in Py_Initialize(). Don't do anything for now
(we'll be back here when _PyGILState_Init is called). */ (we'll be back here when _PyGILState_Init is called). */
if (!_PyRuntime.gilstate.autoInterpreterState) if (!gilstate->autoInterpreterState) {
return; return;
}
/* Stick the thread state for this thread in thread specific storage. /* Stick the thread state for this thread in thread specific storage.
@ -1124,10 +1136,8 @@ _PyGILState_NoteThreadState(PyThreadState* tstate)
The first thread state created for that given OS level thread will The first thread state created for that given OS level thread will
"win", which seems reasonable behaviour. "win", which seems reasonable behaviour.
*/ */
if (PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == NULL) { if (PyThread_tss_get(&gilstate->autoTSSkey) == NULL) {
if ((PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, (void *)tstate) if ((PyThread_tss_set(&gilstate->autoTSSkey, (void *)tstate)) != 0) {
) != 0)
{
Py_FatalError("Couldn't create autoTSSkey mapping"); Py_FatalError("Couldn't create autoTSSkey mapping");
} }
} }