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:
parent
6c44fde3e0
commit
8bb3230149
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
168
Python/pystate.c
168
Python/pystate.c
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue