Skip to content

Instantly share code, notes, and snippets.

@reed-lau
Last active March 24, 2020 04:43
Show Gist options
  • Save reed-lau/a78657a8c9da6efcbc6d7cbc98ec1fa1 to your computer and use it in GitHub Desktop.
Save reed-lau/a78657a8c9da6efcbc6d7cbc98ec1fa1 to your computer and use it in GitHub Desktop.
#define GET_TSTATE() \
((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current))
#define SET_TSTATE(value) \
_Py_atomic_store_relaxed(&_PyThreadState_Current, (Py_uintptr_t)(value))
PyThreadState *
PyThreadState_Swap(PyThreadState *newts)
{
PyThreadState *oldts = GET_TSTATE();
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.
*/
#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;
}
#endif
return oldts;
}
PyThreadState *
PyEval_SaveThread(void)
{
PyThreadState *tstate = PyThreadState_Swap(NULL);
if (tstate == NULL)
Py_FatalError("PyEval_SaveThread: NULL tstate");
if (gil_created())
drop_gil(tstate);
return tstate;
}
void
PyEval_RestoreThread(PyThreadState *tstate)
{
if (tstate == NULL)
Py_FatalError("PyEval_RestoreThread: NULL tstate");
if (gil_created()) {
int err = errno;
take_gil(tstate);
/* _Py_Finalizing is protected by the GIL */
if (_Py_Finalizing && tstate != _Py_Finalizing) {
drop_gil(tstate);
PyThread_exit_thread();
assert(0); /* unreachable */
}
errno = err;
}
PyThreadState_Swap(tstate);
}
void
PyThread_exit_thread(void)
{
dprintf(("PyThread_exit_thread called\n"));
if (!initialized)
exit(0);
pthread_exit(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment