summaryrefslogtreecommitdiff
path: root/Python/pystate.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/pystate.c')
-rw-r--r--Python/pystate.c40
1 files changed, 24 insertions, 16 deletions
diff --git a/Python/pystate.c b/Python/pystate.c
index f1eb6d97fa..d5d98b0c6d 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -47,7 +47,9 @@ static int autoTLSkey = 0;
static PyInterpreterState *interp_head = NULL;
-PyThreadState *_PyThreadState_Current = NULL;
+/* Assuming the current thread holds the GIL, this is the
+ PyThreadState for the current thread. */
+_Py_atomic_address _PyThreadState_Current = {NULL};
PyThreadFrameGetter _PyThreadState_GetFrame = NULL;
#ifdef WITH_THREAD
@@ -334,7 +336,7 @@ tstate_delete_common(PyThreadState *tstate)
void
PyThreadState_Delete(PyThreadState *tstate)
{
- if (tstate == _PyThreadState_Current)
+ if (tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current))
Py_FatalError("PyThreadState_Delete: tstate is still current");
tstate_delete_common(tstate);
#ifdef WITH_THREAD
@@ -348,11 +350,12 @@ PyThreadState_Delete(PyThreadState *tstate)
void
PyThreadState_DeleteCurrent()
{
- PyThreadState *tstate = _PyThreadState_Current;
+ PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
+ &_PyThreadState_Current);
if (tstate == NULL)
Py_FatalError(
"PyThreadState_DeleteCurrent: no current tstate");
- _PyThreadState_Current = NULL;
+ _Py_atomic_store_relaxed(&_PyThreadState_Current, NULL);
tstate_delete_common(tstate);
if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
PyThread_delete_key_value(autoTLSkey);
@@ -364,19 +367,22 @@ PyThreadState_DeleteCurrent()
PyThreadState *
PyThreadState_Get(void)
{
- if (_PyThreadState_Current == NULL)
+ PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
+ &_PyThreadState_Current);
+ if (tstate == NULL)
Py_FatalError("PyThreadState_Get: no current thread");
- return _PyThreadState_Current;
+ return tstate;
}
PyThreadState *
PyThreadState_Swap(PyThreadState *newts)
{
- PyThreadState *oldts = _PyThreadState_Current;
+ PyThreadState *oldts = (PyThreadState*)_Py_atomic_load_relaxed(
+ &_PyThreadState_Current);
- _PyThreadState_Current = newts;
+ _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.
@@ -405,16 +411,18 @@ PyThreadState_Swap(PyThreadState *newts)
PyObject *
PyThreadState_GetDict(void)
{
- if (_PyThreadState_Current == NULL)
+ PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
+ &_PyThreadState_Current);
+ if (tstate == NULL)
return NULL;
- if (_PyThreadState_Current->dict == NULL) {
+ if (tstate->dict == NULL) {
PyObject *d;
- _PyThreadState_Current->dict = d = PyDict_New();
+ tstate->dict = d = PyDict_New();
if (d == NULL)
PyErr_Clear();
}
- return _PyThreadState_Current->dict;
+ return tstate->dict;
}
@@ -453,6 +461,7 @@ PyThreadState_SetAsyncExc(long id, PyObject *exc) {
p->async_exc = exc;
HEAD_UNLOCK();
Py_XDECREF(old_exc);
+ _PyEval_SignalAsyncExc();
return 1;
}
}
@@ -549,10 +558,7 @@ PyThreadState_IsCurrent(PyThreadState *tstate)
{
/* Must be the tstate for this thread */
assert(PyGILState_GetThisThreadState()==tstate);
- /* On Windows at least, simple reads and writes to 32 bit values
- are atomic.
- */
- return tstate == _PyThreadState_Current;
+ return tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current);
}
/* Internal initialization/finalization functions called by
@@ -563,6 +569,8 @@ _PyGILState_Init(PyInterpreterState *i, PyThreadState *t)
{
assert(i && t); /* must init with valid states */
autoTLSkey = PyThread_create_key();
+ if (autoTLSkey == -1)
+ Py_FatalError("Could not allocate TLS entry");
autoInterpreterState = i;
assert(PyThread_get_key_value(autoTLSkey) == NULL);
assert(t->gilstate_counter == 0);