Browse Source

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.
pull/12936/head
Victor Stinner 7 years ago
committed by GitHub
parent
commit
8bb3230149
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      Include/cpython/pystate.h
  2. 5
      Include/internal/pycore_pystate.h
  3. 2
      Modules/_threadmodule.c
  4. 138
      Python/pystate.c

2
Include/cpython/pystate.h

@ -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

5
Include/internal/pycore_pystate.h

@ -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);

2
Modules/_threadmodule.c

@ -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);

138
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) {
return NULL;
}
if (_PyThreadState_GetFrame == NULL)
if (_PyThreadState_GetFrame == NULL) {
_PyThreadState_GetFrame = threadstate_getframe; _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->interp = interp;
tstate->dict = NULL;
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->curexc_type = NULL;
tstate->curexc_value = NULL;
tstate->curexc_traceback = NULL;
tstate->dict = 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->curexc_type = NULL;
tstate->curexc_value = NULL;
tstate->curexc_traceback = NULL;
tstate->c_profilefunc = NULL;
tstate->c_tracefunc = NULL;
tstate->c_profileobj = NULL;
tstate->c_traceobj = 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->trash_delete_nesting = 0;
tstate->trash_delete_later = NULL;
tstate->on_delete = NULL;
tstate->on_delete_data = NULL;
tstate->c_profilefunc = NULL;
tstate->c_tracefunc = NULL;
tstate->c_profileobj = NULL;
tstate->c_traceobj = NULL;
tstate->coroutine_origin_tracking_depth = 0;
tstate->trash_delete_nesting = 0;
tstate->trash_delete_later = NULL;
tstate->on_delete = NULL;
tstate->on_delete_data = NULL;
tstate->coroutine_wrapper = NULL;
tstate->in_coroutine_wrapper = 0;
tstate->coroutine_origin_tracking_depth = 0;
tstate->async_gen_firstiter = NULL;
tstate->async_gen_finalizer = NULL;
tstate->coroutine_wrapper = NULL;
tstate->in_coroutine_wrapper = 0;
tstate->context = NULL;
tstate->context_ver = 1;
tstate->async_gen_firstiter = NULL;
tstate->async_gen_finalizer = NULL;
tstate->id = ++interp->tstate_next_unique_id;
tstate->context = NULL;
tstate->context_ver = 1;
if (init)
_PyThreadState_Init(tstate);
tstate->id = ++interp->tstate_next_unique_id;
HEAD_LOCK();
tstate->prev = NULL;
tstate->next = interp->tstate_head;
if (tstate->next)
tstate->next->prev = tstate;
interp->tstate_head = tstate;
HEAD_UNLOCK();
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 */
if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) {
/* must init with valid states */
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;
assert(PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == NULL);
assert(t->gilstate_counter == 0);
gilstate->autoInterpreterState = interp;
assert(PyThread_tss_get(&gilstate->autoTSSkey) == NULL);
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_set(&_PyRuntime.gilstate.autoTSSkey, (void *)tstate)
) != 0)
{
if (PyThread_tss_get(&gilstate->autoTSSkey) == NULL) {
if ((PyThread_tss_set(&gilstate->autoTSSkey, (void *)tstate)) != 0) {
Py_FatalError("Couldn't create autoTSSkey mapping"); Py_FatalError("Couldn't create autoTSSkey mapping");
} }
} }

Loading…
Cancel
Save