summaryrefslogtreecommitdiff
path: root/Python/pystate.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/pystate.c')
-rw-r--r--Python/pystate.c786
1 files changed, 393 insertions, 393 deletions
diff --git a/Python/pystate.c b/Python/pystate.c
index 7154aeac24..f113839ef0 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -60,95 +60,95 @@ static void _PyGILState_NoteThreadState(PyThreadState* tstate);
PyInterpreterState *
PyInterpreterState_New(void)
{
- PyInterpreterState *interp = (PyInterpreterState *)
- malloc(sizeof(PyInterpreterState));
+ PyInterpreterState *interp = (PyInterpreterState *)
+ malloc(sizeof(PyInterpreterState));
- if (interp != NULL) {
- HEAD_INIT();
+ if (interp != NULL) {
+ HEAD_INIT();
#ifdef WITH_THREAD
- if (head_mutex == NULL)
- Py_FatalError("Can't initialize threads for interpreter");
+ if (head_mutex == NULL)
+ Py_FatalError("Can't initialize threads for interpreter");
#endif
- interp->modules = NULL;
- interp->modules_reloading = NULL;
- interp->modules_by_index = NULL;
- interp->sysdict = NULL;
- interp->builtins = NULL;
- interp->tstate_head = NULL;
- interp->codec_search_path = NULL;
- interp->codec_search_cache = NULL;
- interp->codec_error_registry = NULL;
- interp->codecs_initialized = 0;
+ interp->modules = NULL;
+ interp->modules_reloading = NULL;
+ interp->modules_by_index = NULL;
+ interp->sysdict = NULL;
+ interp->builtins = NULL;
+ interp->tstate_head = NULL;
+ interp->codec_search_path = NULL;
+ interp->codec_search_cache = NULL;
+ interp->codec_error_registry = NULL;
+ interp->codecs_initialized = 0;
#ifdef HAVE_DLOPEN
#ifdef RTLD_NOW
- interp->dlopenflags = RTLD_NOW;
+ interp->dlopenflags = RTLD_NOW;
#else
- interp->dlopenflags = RTLD_LAZY;
+ interp->dlopenflags = RTLD_LAZY;
#endif
#endif
#ifdef WITH_TSC
- interp->tscdump = 0;
+ interp->tscdump = 0;
#endif
- HEAD_LOCK();
- interp->next = interp_head;
- interp_head = interp;
- HEAD_UNLOCK();
- }
+ HEAD_LOCK();
+ interp->next = interp_head;
+ interp_head = interp;
+ HEAD_UNLOCK();
+ }
- return interp;
+ return interp;
}
void
PyInterpreterState_Clear(PyInterpreterState *interp)
{
- PyThreadState *p;
- HEAD_LOCK();
- for (p = interp->tstate_head; p != NULL; p = p->next)
- PyThreadState_Clear(p);
- HEAD_UNLOCK();
- Py_CLEAR(interp->codec_search_path);
- Py_CLEAR(interp->codec_search_cache);
- Py_CLEAR(interp->codec_error_registry);
- Py_CLEAR(interp->modules);
- Py_CLEAR(interp->modules_by_index);
- Py_CLEAR(interp->modules_reloading);
- Py_CLEAR(interp->sysdict);
- Py_CLEAR(interp->builtins);
+ PyThreadState *p;
+ HEAD_LOCK();
+ for (p = interp->tstate_head; p != NULL; p = p->next)
+ PyThreadState_Clear(p);
+ HEAD_UNLOCK();
+ Py_CLEAR(interp->codec_search_path);
+ Py_CLEAR(interp->codec_search_cache);
+ Py_CLEAR(interp->codec_error_registry);
+ Py_CLEAR(interp->modules);
+ Py_CLEAR(interp->modules_by_index);
+ Py_CLEAR(interp->modules_reloading);
+ Py_CLEAR(interp->sysdict);
+ Py_CLEAR(interp->builtins);
}
static void
zapthreads(PyInterpreterState *interp)
{
- PyThreadState *p;
- /* No need to lock the mutex here because this should only happen
- when the threads are all really dead (XXX famous last words). */
- while ((p = interp->tstate_head) != NULL) {
- PyThreadState_Delete(p);
- }
+ PyThreadState *p;
+ /* No need to lock the mutex here because this should only happen
+ when the threads are all really dead (XXX famous last words). */
+ while ((p = interp->tstate_head) != NULL) {
+ PyThreadState_Delete(p);
+ }
}
void
PyInterpreterState_Delete(PyInterpreterState *interp)
{
- PyInterpreterState **p;
- zapthreads(interp);
- HEAD_LOCK();
- for (p = &interp_head; ; p = &(*p)->next) {
- if (*p == NULL)
- Py_FatalError(
- "PyInterpreterState_Delete: invalid interp");
- if (*p == interp)
- break;
- }
- if (interp->tstate_head != NULL)
- Py_FatalError("PyInterpreterState_Delete: remaining threads");
- *p = interp->next;
- HEAD_UNLOCK();
- free(interp);
+ PyInterpreterState **p;
+ zapthreads(interp);
+ HEAD_LOCK();
+ for (p = &interp_head; ; p = &(*p)->next) {
+ if (*p == NULL)
+ Py_FatalError(
+ "PyInterpreterState_Delete: invalid interp");
+ if (*p == interp)
+ break;
+ }
+ if (interp->tstate_head != NULL)
+ Py_FatalError("PyInterpreterState_Delete: remaining threads");
+ *p = interp->next;
+ HEAD_UNLOCK();
+ free(interp);
}
@@ -156,141 +156,141 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
static struct _frame *
threadstate_getframe(PyThreadState *self)
{
- return self->frame;
+ return self->frame;
}
static PyThreadState *
new_threadstate(PyInterpreterState *interp, int init)
{
- PyThreadState *tstate = (PyThreadState *)malloc(sizeof(PyThreadState));
-
- if (_PyThreadState_GetFrame == 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->tracing = 0;
- tstate->use_tracing = 0;
- tstate->tick_counter = 0;
- tstate->gilstate_counter = 0;
- tstate->async_exc = NULL;
+ PyThreadState *tstate = (PyThreadState *)malloc(sizeof(PyThreadState));
+
+ if (_PyThreadState_GetFrame == 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->tracing = 0;
+ tstate->use_tracing = 0;
+ tstate->tick_counter = 0;
+ tstate->gilstate_counter = 0;
+ tstate->async_exc = NULL;
#ifdef WITH_THREAD
- tstate->thread_id = PyThread_get_thread_ident();
+ tstate->thread_id = PyThread_get_thread_ident();
#else
- tstate->thread_id = 0;
+ tstate->thread_id = 0;
#endif
- tstate->dict = NULL;
+ tstate->dict = NULL;
- tstate->curexc_type = NULL;
- tstate->curexc_value = NULL;
- tstate->curexc_traceback = NULL;
+ tstate->curexc_type = NULL;
+ tstate->curexc_value = NULL;
+ tstate->curexc_traceback = NULL;
- tstate->exc_type = NULL;
- tstate->exc_value = NULL;
- tstate->exc_traceback = NULL;
+ tstate->exc_type = NULL;
+ tstate->exc_value = NULL;
+ tstate->exc_traceback = NULL;
- tstate->c_profilefunc = NULL;
- tstate->c_tracefunc = NULL;
- tstate->c_profileobj = NULL;
- tstate->c_traceobj = NULL;
+ tstate->c_profilefunc = NULL;
+ tstate->c_tracefunc = NULL;
+ tstate->c_profileobj = NULL;
+ tstate->c_traceobj = NULL;
- if (init)
- _PyThreadState_Init(tstate);
+ if (init)
+ _PyThreadState_Init(tstate);
- HEAD_LOCK();
- tstate->next = interp->tstate_head;
- interp->tstate_head = tstate;
- HEAD_UNLOCK();
- }
+ HEAD_LOCK();
+ tstate->next = interp->tstate_head;
+ interp->tstate_head = tstate;
+ HEAD_UNLOCK();
+ }
- return tstate;
+ return tstate;
}
PyThreadState *
PyThreadState_New(PyInterpreterState *interp)
{
- return new_threadstate(interp, 1);
+ return new_threadstate(interp, 1);
}
PyThreadState *
_PyThreadState_Prealloc(PyInterpreterState *interp)
{
- return new_threadstate(interp, 0);
+ return new_threadstate(interp, 0);
}
void
_PyThreadState_Init(PyThreadState *tstate)
{
#ifdef WITH_THREAD
- _PyGILState_NoteThreadState(tstate);
+ _PyGILState_NoteThreadState(tstate);
#endif
}
PyObject*
PyState_FindModule(struct PyModuleDef* m)
{
- Py_ssize_t index = m->m_base.m_index;
- PyInterpreterState *state = PyThreadState_GET()->interp;
- PyObject *res;
- if (index == 0)
- return NULL;
- if (state->modules_by_index == NULL)
- return NULL;
- if (index > PyList_GET_SIZE(state->modules_by_index))
- return NULL;
- res = PyList_GET_ITEM(state->modules_by_index, index);
- return res==Py_None ? NULL : res;
+ Py_ssize_t index = m->m_base.m_index;
+ PyInterpreterState *state = PyThreadState_GET()->interp;
+ PyObject *res;
+ if (index == 0)
+ return NULL;
+ if (state->modules_by_index == NULL)
+ return NULL;
+ if (index > PyList_GET_SIZE(state->modules_by_index))
+ return NULL;
+ res = PyList_GET_ITEM(state->modules_by_index, index);
+ return res==Py_None ? NULL : res;
}
int
_PyState_AddModule(PyObject* module, struct PyModuleDef* def)
{
- PyInterpreterState *state = PyThreadState_GET()->interp;
- if (!def)
- return -1;
- if (!state->modules_by_index) {
- state->modules_by_index = PyList_New(0);
- if (!state->modules_by_index)
- return -1;
- }
- while(PyList_GET_SIZE(state->modules_by_index) <= def->m_base.m_index)
- if (PyList_Append(state->modules_by_index, Py_None) < 0)
- return -1;
- Py_INCREF(module);
- return PyList_SetItem(state->modules_by_index,
- def->m_base.m_index, module);
+ PyInterpreterState *state = PyThreadState_GET()->interp;
+ if (!def)
+ return -1;
+ if (!state->modules_by_index) {
+ state->modules_by_index = PyList_New(0);
+ if (!state->modules_by_index)
+ return -1;
+ }
+ while(PyList_GET_SIZE(state->modules_by_index) <= def->m_base.m_index)
+ if (PyList_Append(state->modules_by_index, Py_None) < 0)
+ return -1;
+ Py_INCREF(module);
+ return PyList_SetItem(state->modules_by_index,
+ def->m_base.m_index, module);
}
void
PyThreadState_Clear(PyThreadState *tstate)
{
- if (Py_VerboseFlag && tstate->frame != NULL)
- fprintf(stderr,
- "PyThreadState_Clear: warning: thread still has a frame\n");
+ if (Py_VerboseFlag && tstate->frame != NULL)
+ fprintf(stderr,
+ "PyThreadState_Clear: warning: thread still has a frame\n");
- Py_CLEAR(tstate->frame);
+ Py_CLEAR(tstate->frame);
- Py_CLEAR(tstate->dict);
- Py_CLEAR(tstate->async_exc);
+ Py_CLEAR(tstate->dict);
+ Py_CLEAR(tstate->async_exc);
- Py_CLEAR(tstate->curexc_type);
- Py_CLEAR(tstate->curexc_value);
- Py_CLEAR(tstate->curexc_traceback);
+ Py_CLEAR(tstate->curexc_type);
+ Py_CLEAR(tstate->curexc_value);
+ Py_CLEAR(tstate->curexc_traceback);
- Py_CLEAR(tstate->exc_type);
- Py_CLEAR(tstate->exc_value);
- Py_CLEAR(tstate->exc_traceback);
+ Py_CLEAR(tstate->exc_type);
+ Py_CLEAR(tstate->exc_value);
+ Py_CLEAR(tstate->exc_traceback);
- tstate->c_profilefunc = NULL;
- tstate->c_tracefunc = NULL;
- Py_CLEAR(tstate->c_profileobj);
- Py_CLEAR(tstate->c_traceobj);
+ tstate->c_profilefunc = NULL;
+ tstate->c_tracefunc = NULL;
+ Py_CLEAR(tstate->c_profileobj);
+ Py_CLEAR(tstate->c_traceobj);
}
@@ -298,50 +298,50 @@ PyThreadState_Clear(PyThreadState *tstate)
static void
tstate_delete_common(PyThreadState *tstate)
{
- PyInterpreterState *interp;
- PyThreadState **p;
- PyThreadState *prev_p = NULL;
- if (tstate == NULL)
- Py_FatalError("PyThreadState_Delete: NULL tstate");
- interp = tstate->interp;
- if (interp == NULL)
- Py_FatalError("PyThreadState_Delete: NULL interp");
- HEAD_LOCK();
- for (p = &interp->tstate_head; ; p = &(*p)->next) {
- if (*p == NULL)
- Py_FatalError(
- "PyThreadState_Delete: invalid tstate");
- if (*p == tstate)
- break;
- /* Sanity check. These states should never happen but if
- * they do we must abort. Otherwise we'll end up spinning in
- * in a tight loop with the lock held. A similar check is done
- * in thread.c find_key(). */
- if (*p == prev_p)
- Py_FatalError(
- "PyThreadState_Delete: small circular list(!)"
- " and tstate not found.");
- prev_p = *p;
- if ((*p)->next == interp->tstate_head)
- Py_FatalError(
- "PyThreadState_Delete: circular list(!) and"
- " tstate not found.");
- }
- *p = tstate->next;
- HEAD_UNLOCK();
- free(tstate);
+ PyInterpreterState *interp;
+ PyThreadState **p;
+ PyThreadState *prev_p = NULL;
+ if (tstate == NULL)
+ Py_FatalError("PyThreadState_Delete: NULL tstate");
+ interp = tstate->interp;
+ if (interp == NULL)
+ Py_FatalError("PyThreadState_Delete: NULL interp");
+ HEAD_LOCK();
+ for (p = &interp->tstate_head; ; p = &(*p)->next) {
+ if (*p == NULL)
+ Py_FatalError(
+ "PyThreadState_Delete: invalid tstate");
+ if (*p == tstate)
+ break;
+ /* Sanity check. These states should never happen but if
+ * they do we must abort. Otherwise we'll end up spinning in
+ * in a tight loop with the lock held. A similar check is done
+ * in thread.c find_key(). */
+ if (*p == prev_p)
+ Py_FatalError(
+ "PyThreadState_Delete: small circular list(!)"
+ " and tstate not found.");
+ prev_p = *p;
+ if ((*p)->next == interp->tstate_head)
+ Py_FatalError(
+ "PyThreadState_Delete: circular list(!) and"
+ " tstate not found.");
+ }
+ *p = tstate->next;
+ HEAD_UNLOCK();
+ free(tstate);
}
void
PyThreadState_Delete(PyThreadState *tstate)
{
- if (tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current))
- Py_FatalError("PyThreadState_Delete: tstate is still current");
- tstate_delete_common(tstate);
+ if (tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current))
+ Py_FatalError("PyThreadState_Delete: tstate is still current");
+ tstate_delete_common(tstate);
#ifdef WITH_THREAD
- if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
- PyThread_delete_key_value(autoTLSkey);
+ if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
+ PyThread_delete_key_value(autoTLSkey);
#endif /* WITH_THREAD */
}
@@ -350,16 +350,16 @@ PyThreadState_Delete(PyThreadState *tstate)
void
PyThreadState_DeleteCurrent()
{
- PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
- &_PyThreadState_Current);
- if (tstate == NULL)
- Py_FatalError(
- "PyThreadState_DeleteCurrent: no current tstate");
- _Py_atomic_store_relaxed(&_PyThreadState_Current, NULL);
- tstate_delete_common(tstate);
- if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
- PyThread_delete_key_value(autoTLSkey);
- PyEval_ReleaseLock();
+ PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
+ &_PyThreadState_Current);
+ if (tstate == NULL)
+ Py_FatalError(
+ "PyThreadState_DeleteCurrent: no current tstate");
+ _Py_atomic_store_relaxed(&_PyThreadState_Current, NULL);
+ tstate_delete_common(tstate);
+ if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
+ PyThread_delete_key_value(autoTLSkey);
+ PyEval_ReleaseLock();
}
#endif /* WITH_THREAD */
@@ -367,39 +367,39 @@ PyThreadState_DeleteCurrent()
PyThreadState *
PyThreadState_Get(void)
{
- PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
- &_PyThreadState_Current);
- if (tstate == NULL)
- Py_FatalError("PyThreadState_Get: no current thread");
+ PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
+ &_PyThreadState_Current);
+ if (tstate == NULL)
+ Py_FatalError("PyThreadState_Get: no current thread");
- return tstate;
+ return tstate;
}
PyThreadState *
PyThreadState_Swap(PyThreadState *newts)
{
- PyThreadState *oldts = (PyThreadState*)_Py_atomic_load_relaxed(
- &_PyThreadState_Current);
-
- _Py_atomic_store_relaxed(&_PyThreadState_Current, newts);
- /* It should not be possible for more than one thread state
- to be used for a thread. Check this the best we can in debug
- builds.
- */
+ PyThreadState *oldts = (PyThreadState*)_Py_atomic_load_relaxed(
+ &_PyThreadState_Current);
+
+ _Py_atomic_store_relaxed(&_PyThreadState_Current, newts);
+ /* It should not be possible for more than one thread state
+ to be used for a thread. Check this the best we can in debug
+ builds.
+ */
#if defined(Py_DEBUG) && defined(WITH_THREAD)
- if (newts) {
- /* This can be called from PyEval_RestoreThread(). Similar
- to it, we need to ensure errno doesn't change.
- */
- int err = errno;
- PyThreadState *check = PyGILState_GetThisThreadState();
- if (check && check->interp == newts->interp && check != newts)
- Py_FatalError("Invalid thread state for this thread");
- errno = err;
- }
+ if (newts) {
+ /* This can be called from PyEval_RestoreThread(). Similar
+ to it, we need to ensure errno doesn't change.
+ */
+ int err = errno;
+ PyThreadState *check = PyGILState_GetThisThreadState();
+ if (check && check->interp == newts->interp && check != newts)
+ Py_FatalError("Invalid thread state for this thread");
+ errno = err;
+ }
#endif
- return oldts;
+ return oldts;
}
/* An extension mechanism to store arbitrary additional per-thread state.
@@ -411,18 +411,18 @@ PyThreadState_Swap(PyThreadState *newts)
PyObject *
PyThreadState_GetDict(void)
{
- PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
- &_PyThreadState_Current);
- if (tstate == NULL)
- return NULL;
+ PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
+ &_PyThreadState_Current);
+ if (tstate == NULL)
+ return NULL;
- if (tstate->dict == NULL) {
- PyObject *d;
- tstate->dict = d = PyDict_New();
- if (d == NULL)
- PyErr_Clear();
- }
- return tstate->dict;
+ if (tstate->dict == NULL) {
+ PyObject *d;
+ tstate->dict = d = PyDict_New();
+ if (d == NULL)
+ PyErr_Clear();
+ }
+ return tstate->dict;
}
@@ -436,37 +436,37 @@ PyThreadState_GetDict(void)
int
PyThreadState_SetAsyncExc(long id, PyObject *exc) {
- PyThreadState *tstate = PyThreadState_GET();
- PyInterpreterState *interp = tstate->interp;
- PyThreadState *p;
-
- /* Although the GIL is held, a few C API functions can be called
- * without the GIL held, and in particular some that create and
- * destroy thread and interpreter states. Those can mutate the
- * list of thread states we're traversing, so to prevent that we lock
- * head_mutex for the duration.
- */
- HEAD_LOCK();
- for (p = interp->tstate_head; p != NULL; p = p->next) {
- if (p->thread_id == id) {
- /* Tricky: we need to decref the current value
- * (if any) in p->async_exc, but that can in turn
- * allow arbitrary Python code to run, including
- * perhaps calls to this function. To prevent
- * deadlock, we need to release head_mutex before
- * the decref.
- */
- PyObject *old_exc = p->async_exc;
- Py_XINCREF(exc);
- p->async_exc = exc;
- HEAD_UNLOCK();
- Py_XDECREF(old_exc);
- _PyEval_SignalAsyncExc();
- return 1;
- }
- }
- HEAD_UNLOCK();
- return 0;
+ PyThreadState *tstate = PyThreadState_GET();
+ PyInterpreterState *interp = tstate->interp;
+ PyThreadState *p;
+
+ /* Although the GIL is held, a few C API functions can be called
+ * without the GIL held, and in particular some that create and
+ * destroy thread and interpreter states. Those can mutate the
+ * list of thread states we're traversing, so to prevent that we lock
+ * head_mutex for the duration.
+ */
+ HEAD_LOCK();
+ for (p = interp->tstate_head; p != NULL; p = p->next) {
+ if (p->thread_id == id) {
+ /* Tricky: we need to decref the current value
+ * (if any) in p->async_exc, but that can in turn
+ * allow arbitrary Python code to run, including
+ * perhaps calls to this function. To prevent
+ * deadlock, we need to release head_mutex before
+ * the decref.
+ */
+ PyObject *old_exc = p->async_exc;
+ Py_XINCREF(exc);
+ p->async_exc = exc;
+ HEAD_UNLOCK();
+ Py_XDECREF(old_exc);
+ _PyEval_SignalAsyncExc();
+ return 1;
+ }
+ }
+ HEAD_UNLOCK();
+ return 0;
}
@@ -476,22 +476,22 @@ PyThreadState_SetAsyncExc(long id, PyObject *exc) {
PyInterpreterState *
PyInterpreterState_Head(void)
{
- return interp_head;
+ return interp_head;
}
PyInterpreterState *
PyInterpreterState_Next(PyInterpreterState *interp) {
- return interp->next;
+ return interp->next;
}
PyThreadState *
PyInterpreterState_ThreadHead(PyInterpreterState *interp) {
- return interp->tstate_head;
+ return interp->tstate_head;
}
PyThreadState *
PyThreadState_Next(PyThreadState *tstate) {
- return tstate->next;
+ return tstate->next;
}
/* The implementation of sys._current_frames(). This is intended to be
@@ -502,44 +502,44 @@ PyThreadState_Next(PyThreadState *tstate) {
PyObject *
_PyThread_CurrentFrames(void)
{
- PyObject *result;
- PyInterpreterState *i;
-
- result = PyDict_New();
- if (result == NULL)
- return NULL;
-
- /* for i in all interpreters:
- * for t in all of i's thread states:
- * if t's frame isn't NULL, map t's id to its frame
- * Because these lists can mutute even when the GIL is held, we
- * need to grab head_mutex for the duration.
- */
- HEAD_LOCK();
- for (i = interp_head; i != NULL; i = i->next) {
- PyThreadState *t;
- for (t = i->tstate_head; t != NULL; t = t->next) {
- PyObject *id;
- int stat;
- struct _frame *frame = t->frame;
- if (frame == NULL)
- continue;
- id = PyLong_FromLong(t->thread_id);
- if (id == NULL)
- goto Fail;
- stat = PyDict_SetItem(result, id, (PyObject *)frame);
- Py_DECREF(id);
- if (stat < 0)
- goto Fail;
- }
- }
- HEAD_UNLOCK();
- return result;
+ PyObject *result;
+ PyInterpreterState *i;
+
+ result = PyDict_New();
+ if (result == NULL)
+ return NULL;
+
+ /* for i in all interpreters:
+ * for t in all of i's thread states:
+ * if t's frame isn't NULL, map t's id to its frame
+ * Because these lists can mutute even when the GIL is held, we
+ * need to grab head_mutex for the duration.
+ */
+ HEAD_LOCK();
+ for (i = interp_head; i != NULL; i = i->next) {
+ PyThreadState *t;
+ for (t = i->tstate_head; t != NULL; t = t->next) {
+ PyObject *id;
+ int stat;
+ struct _frame *frame = t->frame;
+ if (frame == NULL)
+ continue;
+ id = PyLong_FromLong(t->thread_id);
+ if (id == NULL)
+ goto Fail;
+ stat = PyDict_SetItem(result, id, (PyObject *)frame);
+ Py_DECREF(id);
+ if (stat < 0)
+ goto Fail;
+ }
+ }
+ HEAD_UNLOCK();
+ return result;
Fail:
- HEAD_UNLOCK();
- Py_DECREF(result);
- return NULL;
+ HEAD_UNLOCK();
+ Py_DECREF(result);
+ return NULL;
}
/* Python "auto thread state" API. */
@@ -556,9 +556,9 @@ _PyThread_CurrentFrames(void)
static int
PyThreadState_IsCurrent(PyThreadState *tstate)
{
- /* Must be the tstate for this thread */
- assert(PyGILState_GetThisThreadState()==tstate);
- return tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current);
+ /* Must be the tstate for this thread */
+ assert(PyGILState_GetThisThreadState()==tstate);
+ return tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current);
}
/* Internal initialization/finalization functions called by
@@ -567,21 +567,21 @@ PyThreadState_IsCurrent(PyThreadState *tstate)
void
_PyGILState_Init(PyInterpreterState *i, PyThreadState *t)
{
- assert(i && t); /* must init with valid states */
- autoTLSkey = PyThread_create_key();
- autoInterpreterState = i;
- assert(PyThread_get_key_value(autoTLSkey) == NULL);
- assert(t->gilstate_counter == 0);
+ assert(i && t); /* must init with valid states */
+ autoTLSkey = PyThread_create_key();
+ autoInterpreterState = i;
+ assert(PyThread_get_key_value(autoTLSkey) == NULL);
+ assert(t->gilstate_counter == 0);
- _PyGILState_NoteThreadState(t);
+ _PyGILState_NoteThreadState(t);
}
void
_PyGILState_Fini(void)
{
- PyThread_delete_key(autoTLSkey);
- autoTLSkey = 0;
- autoInterpreterState = NULL;
+ PyThread_delete_key(autoTLSkey);
+ autoTLSkey = 0;
+ autoInterpreterState = NULL;
}
/* When a thread state is created for a thread by some mechanism other than
@@ -592,113 +592,113 @@ _PyGILState_Fini(void)
static void
_PyGILState_NoteThreadState(PyThreadState* tstate)
{
- /* If autoTLSkey is 0, this must be the very first threadstate created
- in Py_Initialize(). Don't do anything for now (we'll be back here
- when _PyGILState_Init is called). */
- if (!autoTLSkey)
- return;
+ /* If autoTLSkey is 0, this must be the very first threadstate created
+ in Py_Initialize(). Don't do anything for now (we'll be back here
+ when _PyGILState_Init is called). */
+ if (!autoTLSkey)
+ return;
- /* Stick the thread state for this thread in thread local storage.
+ /* Stick the thread state for this thread in thread local storage.
- The only situation where you can legitimately have more than one
- thread state for an OS level thread is when there are multiple
- interpreters, when:
+ The only situation where you can legitimately have more than one
+ thread state for an OS level thread is when there are multiple
+ interpreters, when:
- a) You shouldn't really be using the PyGILState_ APIs anyway,
- and:
+ a) You shouldn't really be using the PyGILState_ APIs anyway,
+ and:
- b) The slightly odd way PyThread_set_key_value works (see
- comments by its implementation) means that the first thread
- state created for that given OS level thread will "win",
- which seems reasonable behaviour.
- */
- if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0)
- Py_FatalError("Couldn't create autoTLSkey mapping");
+ b) The slightly odd way PyThread_set_key_value works (see
+ comments by its implementation) means that the first thread
+ state created for that given OS level thread will "win",
+ which seems reasonable behaviour.
+ */
+ if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0)
+ Py_FatalError("Couldn't create autoTLSkey mapping");
- /* PyGILState_Release must not try to delete this thread state. */
- tstate->gilstate_counter = 1;
+ /* PyGILState_Release must not try to delete this thread state. */
+ tstate->gilstate_counter = 1;
}
/* The public functions */
PyThreadState *
PyGILState_GetThisThreadState(void)
{
- if (autoInterpreterState == NULL || autoTLSkey == 0)
- return NULL;
- return (PyThreadState *)PyThread_get_key_value(autoTLSkey);
+ if (autoInterpreterState == NULL || autoTLSkey == 0)
+ return NULL;
+ return (PyThreadState *)PyThread_get_key_value(autoTLSkey);
}
PyGILState_STATE
PyGILState_Ensure(void)
{
- int current;
- PyThreadState *tcur;
- /* Note that we do not auto-init Python here - apart from
- potential races with 2 threads auto-initializing, pep-311
- spells out other issues. Embedders are expected to have
- called Py_Initialize() and usually PyEval_InitThreads().
- */
- assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */
- tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey);
- if (tcur == NULL) {
- /* Create a new thread state for this thread */
- tcur = PyThreadState_New(autoInterpreterState);
- if (tcur == NULL)
- Py_FatalError("Couldn't create thread-state for new thread");
- /* This is our thread state! We'll need to delete it in the
- matching call to PyGILState_Release(). */
- tcur->gilstate_counter = 0;
- current = 0; /* new thread state is never current */
- }
- else
- current = PyThreadState_IsCurrent(tcur);
- if (current == 0)
- PyEval_RestoreThread(tcur);
- /* Update our counter in the thread-state - no need for locks:
- - tcur will remain valid as we hold the GIL.
- - the counter is safe as we are the only thread "allowed"
- to modify this value
- */
- ++tcur->gilstate_counter;
- return current ? PyGILState_LOCKED : PyGILState_UNLOCKED;
+ int current;
+ PyThreadState *tcur;
+ /* Note that we do not auto-init Python here - apart from
+ potential races with 2 threads auto-initializing, pep-311
+ spells out other issues. Embedders are expected to have
+ called Py_Initialize() and usually PyEval_InitThreads().
+ */
+ assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */
+ tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey);
+ if (tcur == NULL) {
+ /* Create a new thread state for this thread */
+ tcur = PyThreadState_New(autoInterpreterState);
+ if (tcur == NULL)
+ Py_FatalError("Couldn't create thread-state for new thread");
+ /* This is our thread state! We'll need to delete it in the
+ matching call to PyGILState_Release(). */
+ tcur->gilstate_counter = 0;
+ current = 0; /* new thread state is never current */
+ }
+ else
+ current = PyThreadState_IsCurrent(tcur);
+ if (current == 0)
+ PyEval_RestoreThread(tcur);
+ /* Update our counter in the thread-state - no need for locks:
+ - tcur will remain valid as we hold the GIL.
+ - the counter is safe as we are the only thread "allowed"
+ to modify this value
+ */
+ ++tcur->gilstate_counter;
+ return current ? PyGILState_LOCKED : PyGILState_UNLOCKED;
}
void
PyGILState_Release(PyGILState_STATE oldstate)
{
- PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value(
- autoTLSkey);
- if (tcur == NULL)
- Py_FatalError("auto-releasing thread-state, "
- "but no thread-state for this thread");
- /* We must hold the GIL and have our thread state current */
- /* XXX - remove the check - the assert should be fine,
- but while this is very new (April 2003), the extra check
- by release-only users can't hurt.
- */
- if (! PyThreadState_IsCurrent(tcur))
- Py_FatalError("This thread state must be current when releasing");
- assert(PyThreadState_IsCurrent(tcur));
- --tcur->gilstate_counter;
- assert(tcur->gilstate_counter >= 0); /* illegal counter value */
-
- /* If we're going to destroy this thread-state, we must
- * clear it while the GIL is held, as destructors may run.
- */
- if (tcur->gilstate_counter == 0) {
- /* can't have been locked when we created it */
- assert(oldstate == PyGILState_UNLOCKED);
- PyThreadState_Clear(tcur);
- /* Delete the thread-state. Note this releases the GIL too!
- * It's vital that the GIL be held here, to avoid shutdown
- * races; see bugs 225673 and 1061968 (that nasty bug has a
- * habit of coming back).
- */
- PyThreadState_DeleteCurrent();
- }
- /* Release the lock if necessary */
- else if (oldstate == PyGILState_UNLOCKED)
- PyEval_SaveThread();
+ PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value(
+ autoTLSkey);
+ if (tcur == NULL)
+ Py_FatalError("auto-releasing thread-state, "
+ "but no thread-state for this thread");
+ /* We must hold the GIL and have our thread state current */
+ /* XXX - remove the check - the assert should be fine,
+ but while this is very new (April 2003), the extra check
+ by release-only users can't hurt.
+ */
+ if (! PyThreadState_IsCurrent(tcur))
+ Py_FatalError("This thread state must be current when releasing");
+ assert(PyThreadState_IsCurrent(tcur));
+ --tcur->gilstate_counter;
+ assert(tcur->gilstate_counter >= 0); /* illegal counter value */
+
+ /* If we're going to destroy this thread-state, we must
+ * clear it while the GIL is held, as destructors may run.
+ */
+ if (tcur->gilstate_counter == 0) {
+ /* can't have been locked when we created it */
+ assert(oldstate == PyGILState_UNLOCKED);
+ PyThreadState_Clear(tcur);
+ /* Delete the thread-state. Note this releases the GIL too!
+ * It's vital that the GIL be held here, to avoid shutdown
+ * races; see bugs 225673 and 1061968 (that nasty bug has a
+ * habit of coming back).
+ */
+ PyThreadState_DeleteCurrent();
+ }
+ /* Release the lock if necessary */
+ else if (oldstate == PyGILState_UNLOCKED)
+ PyEval_SaveThread();
}
#ifdef __cplusplus