summaryrefslogtreecommitdiff
path: root/Python/pystate.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/pystate.c')
-rw-r--r--Python/pystate.c69
1 files changed, 42 insertions, 27 deletions
diff --git a/Python/pystate.c b/Python/pystate.c
index 83f15fd671..e8026c52f0 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -3,11 +3,13 @@
#include "Python.h"
-#ifndef Py_BUILD_CORE
-/* ensure that PyThreadState_GET() is a macro, not an alias to
- * PyThreadState_Get() */
-# error "pystate.c must be compiled with Py_BUILD_CORE defined"
-#endif
+#define GET_TSTATE() \
+ ((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current))
+#define SET_TSTATE(value) \
+ _Py_atomic_store_relaxed(&_PyThreadState_Current, (Py_uintptr_t)(value))
+#define GET_INTERP_STATE() \
+ (GET_TSTATE()->interp)
+
/* --------------------------------------------------------------------------
CAUTION
@@ -32,6 +34,8 @@ to avoid the expense of doing their own locking).
extern "C" {
#endif
+int _PyGILState_check_enabled = 1;
+
#ifdef WITH_THREAD
#include "pythread.h"
static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
@@ -43,7 +47,7 @@ static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
GILState implementation
*/
static PyInterpreterState *autoInterpreterState = NULL;
-static int autoTLSkey = 0;
+static int autoTLSkey = -1;
#else
#define HEAD_INIT() /* Nothing */
#define HEAD_LOCK() /* Nothing */
@@ -54,7 +58,7 @@ static PyInterpreterState *interp_head = NULL;
/* Assuming the current thread holds the GIL, this is the
PyThreadState for the current thread. */
-_Py_atomic_address _PyThreadState_Current = {NULL};
+_Py_atomic_address _PyThreadState_Current = {0};
PyThreadFrameGetter _PyThreadState_GetFrame = NULL;
#ifdef WITH_THREAD
@@ -260,7 +264,7 @@ PyObject*
PyState_FindModule(struct PyModuleDef* module)
{
Py_ssize_t index = module->m_base.m_index;
- PyInterpreterState *state = PyThreadState_GET()->interp;
+ PyInterpreterState *state = GET_INTERP_STATE();
PyObject *res;
if (module->m_slots) {
return NULL;
@@ -284,7 +288,7 @@ _PyState_AddModule(PyObject* module, struct PyModuleDef* def)
"PyState_AddModule called on module with slots");
return -1;
}
- state = PyThreadState_GET()->interp;
+ state = GET_INTERP_STATE();
if (!def)
return -1;
if (!state->modules_by_index) {
@@ -304,7 +308,7 @@ int
PyState_AddModule(PyObject* module, struct PyModuleDef* def)
{
Py_ssize_t index;
- PyInterpreterState *state = PyThreadState_GET()->interp;
+ PyInterpreterState *state = GET_INTERP_STATE();
if (!def) {
Py_FatalError("PyState_AddModule: Module Definition is NULL");
return -1;
@@ -331,7 +335,7 @@ PyState_RemoveModule(struct PyModuleDef* def)
"PyState_RemoveModule called on module with slots");
return -1;
}
- state = PyThreadState_GET()->interp;
+ state = GET_INTERP_STATE();
if (index == 0) {
Py_FatalError("PyState_RemoveModule: Module index invalid.");
return -1;
@@ -351,7 +355,7 @@ PyState_RemoveModule(struct PyModuleDef* def)
void
_PyState_ClearModules(void)
{
- PyInterpreterState *state = PyThreadState_GET()->interp;
+ PyInterpreterState *state = GET_INTERP_STATE();
if (state->modules_by_index) {
Py_ssize_t i;
for (i = 0; i < PyList_GET_SIZE(state->modules_by_index); i++) {
@@ -429,7 +433,7 @@ tstate_delete_common(PyThreadState *tstate)
void
PyThreadState_Delete(PyThreadState *tstate)
{
- if (tstate == PyThreadState_GET())
+ if (tstate == GET_TSTATE())
Py_FatalError("PyThreadState_Delete: tstate is still current");
#ifdef WITH_THREAD
if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
@@ -443,14 +447,14 @@ PyThreadState_Delete(PyThreadState *tstate)
void
PyThreadState_DeleteCurrent()
{
- PyThreadState *tstate = PyThreadState_GET();
+ PyThreadState *tstate = GET_TSTATE();
if (tstate == NULL)
Py_FatalError(
"PyThreadState_DeleteCurrent: no current tstate");
- _Py_atomic_store_relaxed(&_PyThreadState_Current, NULL);
+ tstate_delete_common(tstate);
if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
PyThread_delete_key_value(autoTLSkey);
- tstate_delete_common(tstate);
+ SET_TSTATE(NULL);
PyEval_ReleaseLock();
}
#endif /* WITH_THREAD */
@@ -496,14 +500,14 @@ _PyThreadState_DeleteExcept(PyThreadState *tstate)
PyThreadState *
_PyThreadState_UncheckedGet(void)
{
- return PyThreadState_GET();
+ return GET_TSTATE();
}
PyThreadState *
PyThreadState_Get(void)
{
- PyThreadState *tstate = PyThreadState_GET();
+ PyThreadState *tstate = GET_TSTATE();
if (tstate == NULL)
Py_FatalError("PyThreadState_Get: no current thread");
@@ -514,9 +518,9 @@ PyThreadState_Get(void)
PyThreadState *
PyThreadState_Swap(PyThreadState *newts)
{
- PyThreadState *oldts = PyThreadState_GET();
+ PyThreadState *oldts = GET_TSTATE();
- _Py_atomic_store_relaxed(&_PyThreadState_Current, newts);
+ SET_TSTATE(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.
@@ -545,7 +549,7 @@ PyThreadState_Swap(PyThreadState *newts)
PyObject *
PyThreadState_GetDict(void)
{
- PyThreadState *tstate = PyThreadState_GET();
+ PyThreadState *tstate = GET_TSTATE();
if (tstate == NULL)
return NULL;
@@ -569,8 +573,7 @@ PyThreadState_GetDict(void)
int
PyThreadState_SetAsyncExc(long id, PyObject *exc) {
- PyThreadState *tstate = PyThreadState_GET();
- PyInterpreterState *interp = tstate->interp;
+ PyInterpreterState *interp = GET_INTERP_STATE();
PyThreadState *p;
/* Although the GIL is held, a few C API functions can be called
@@ -691,11 +694,11 @@ PyThreadState_IsCurrent(PyThreadState *tstate)
{
/* Must be the tstate for this thread */
assert(PyGILState_GetThisThreadState()==tstate);
- return tstate == PyThreadState_GET();
+ return tstate == GET_TSTATE();
}
/* Internal initialization/finalization functions called by
- Py_Initialize/Py_Finalize
+ Py_Initialize/Py_FinalizeEx
*/
void
_PyGILState_Init(PyInterpreterState *i, PyThreadState *t)
@@ -715,6 +718,7 @@ void
_PyGILState_Fini(void)
{
PyThread_delete_key(autoTLSkey);
+ autoTLSkey = -1;
autoInterpreterState = NULL;
}
@@ -783,8 +787,19 @@ PyGILState_GetThisThreadState(void)
int
PyGILState_Check(void)
{
- PyThreadState *tstate = PyThreadState_GET();
- return tstate && (tstate == PyGILState_GetThisThreadState());
+ PyThreadState *tstate;
+
+ if (!_PyGILState_check_enabled)
+ return 1;
+
+ if (autoTLSkey == -1)
+ return 1;
+
+ tstate = GET_TSTATE();
+ if (tstate == NULL)
+ return 0;
+
+ return (tstate == PyGILState_GetThisThreadState());
}
PyGILState_STATE