Last active
November 17, 2022 00:30
-
-
Save ericsnowcurrently/99e2c79281a02a407ddf1dd49bf2d321 to your computer and use it in GitHub Desktop.
analysis of gilstate operations
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
_PyRuntimeState_GetThreadState() | |
_PyRuntime.gilstate.tstate_current <---- | |
_PyRuntimeGILState_GetThreadState() | |
_PyRuntime.gilstate.tstate_current <---- | |
_PyRuntimeGILState_SetThreadState(tstate) | |
_PyRuntime.gilstate.tstate_current = tstate <---- | |
_PyThreadState_GET() | |
_PyRuntimeState_GetThreadState() | |
... | |
_PyInterpreterState_GET() | |
tstate = _PyThreadState_GET() | |
... | |
_Py_EnsureTstateNotNULL() | |
return tstate->interp | |
_PyGILState_GetInterpreterStateUnsafe() | |
_PyRuntime.gilstate.autoInterpreterState <---- | |
_PyGILState_GetThisThreadState() | |
if _PyRuntime.gilstate.autoInterpreterState: <---- | |
expected = PyThread_tss_get(_PyRuntime.gilstate.autoTSSkey) <---- | |
else | |
expected = NULL | |
_PyGILState_NoteThreadState() | |
if _PyRuntime.gilstate.autoInterpreterState: <---- | |
if PyThread_tss_get(_PyRuntime.gilstate.autoTSSkey) == NULL: <---- | |
PyThread_tss_set(_PyRuntime.gilstate.autoTSSkey, newts) <---- | |
_PyGILState_SetTstate() | |
if _Py_IsMainInterpreter(tstate.interp): | |
_PyRuntime.gilstate.autoInterpreterState = tstate.interp <---- | |
_PyGILState_NoteThreadState(tstate) | |
... | |
PyThreadState_IsCurrent(tcur) | |
assert(_PyGILState_GetThisThreadState() == tcur) | |
... | |
current = (tcur == _PyRuntimeGILState_GetThreadState()) | |
... | |
_PyThreadState_SetCurrent() | |
_PyGILState_NoteThreadState() | |
... | |
_PyThreadState_DeleteCurrent() | |
tstate_delete_common() | |
if _PyRuntime.gilstate.autoInterpreterState and <---- | |
PyThread_tss_get(_PyRuntime.gilstate.autoTSSkey) == tstate: <---- | |
PyThread_tss_set(_PyRuntime.gilstate.autoTSSkey, NULL) <---- | |
_PyThreadState_Swap() | |
_PyRuntimeGILState_GetThreadState() | |
... | |
_PyRuntimeGILState_SetThreadState() | |
... | |
PyEval_SaveThread() | |
oldts = _PyThreadState_Swap(NULL) | |
... | |
_Py_EnsureTstateNotNULL(oldts) | |
assert(gil_created()) | |
... | |
drop_gil() | |
if _PyRuntime.ceval.gil.locked: | |
_PyRuntime.ceval.gil.last_holder = tstate | |
_PyRuntime.ceval.gil.locked = 1 | |
PyEval_RestoreThread() | |
_Py_EnsureTstateNotNULL() | |
take_gil() | |
... | |
_PyThreadState_Swap() | |
... | |
Py_BEGIN_ALLOW_THREADS | |
PyEval_SaveThread() | |
... | |
Py_END_ALLOW_THREADS | |
PyEval_RestoreThread() | |
... | |
PyThreadState_New(interp = _PyRuntime.gilstate.autoInterpreterState) <---- | |
new_threadstate() | |
acquire-head-lock | |
| interp.threads.next_unique_id++ | |
| newts = alloc_threadstate() | |
| interp.threads.head = tcur | |
| init_threadstate() | |
| tcur.interp = interp | |
- release-head-lock | |
_PyThreadState_SetCurrent() | |
... | |
PyGILState_Ensure() | |
assert(_PyEval_ThreadsInitialized()) | |
gil_created() | |
actual = (_PyRuntime.ceval.gil.locked >= 0) | |
assert(_PyRuntime.gilstate.autoInterpreterState) <---- | |
tcur = PyThread_tss_get(_PyRuntime.gilstate.autoTSSkey) <---- | |
if tcur == NULL: | |
tcur = PyThreadState_New(interp = _PyRuntime.gilstate.autoInterpreterState) <---- | |
... | |
current = False | |
else: | |
current = PyThreadState_IsCurrent(tcur) | |
... | |
return PyGILState_LOCKED if current else PyGILState_UNLOCKED | |
PyGILState_Release() | |
tstate = PyThread_tss_get(_PyRuntime.gilstate.autoTSSkey) <---- | |
if PyThreadState_IsCurrent(tstate): | |
... | |
--tstate.gilstate_counter | |
if tstate.gilstate_counter == 0: | |
PyThreadState_Clear(tstate) | |
assert(_PyRuntimeGILState_GetThreadState() == tstate) | |
... | |
_PyThreadState_DeleteCurrent() | |
... | |
elif oldstate == PyGILState_UNLOCKED: | |
PyEval_SaveThread() | |
... | |
############################################################################### | |
# failing on some buildbots due to https://github.com/python/cpython/pull/99378 | |
test.test_threading.ThreadTests.test_frame_tstate_tracing() | |
_testcapi.call_in_temporary_c_thread() | |
acquire-start-lock | |
acquire-exit-lock | |
PyThread_start_new_thread() -> temporary_c_thread() | |
_PyThreadState_GET() | |
... | |
pthread_create() -> pythread_wrapper() -> temporary_c_thread() | |
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | |
release-start-lock | |
PyGILState_Ensure() | |
... | |
PyObject_CallNoArgs() | |
Py_CLEAR() | |
PyGILState_Release() | |
... | |
release-exit-lock | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
block-on-start-lock | |
Py_BEGIN_ALLOW_THREADS | |
... | |
block-on-exit-lock | |
Py_END_ALLOW_THREADS | |
... | |
******************************************************************************* | |
main | |
lock "start" | |
lock "stop" | |
get _PyRuntime.gilstate.tstate_current (discarded) | |
block on "start" | |
new thread | |
release "start" | |
race | |
main | |
get _PyRuntime.gilstate.tstate_current -> oldts | |
set _PyRuntime.gilstate.tstate_current <- NULL | |
new thread | |
get _PyRuntime.gilstate.autoInterpreterState (discarded) | |
tss-get _PyRuntime.gilstate.autoTSSkey -> tcur | |
if tcur == NULL: | |
get _PyRuntime.gilstate.autoInterpreterState -> interp | |
get _PyRuntime.gilstate.autoInterpreterState (discarded) | |
tss-get _PyRuntime.gilstate.autoTSSkey (discarded) | |
tss-set _PyRuntime.gilstate.autoTSSkey <- tcur | |
else: | |
get _PyRuntime.gilstate.autoInterpreterState (discarded) | |
tss-get _PyRuntime.gilstate.autoTSSkey (discarded) | |
get _PyRuntime.gilstate.tstate_current (discarded) | |
<various uses via PyObject_CallNoArgs()> | |
tss-get _PyRuntime.gilstate.autoTSSkey -> tstate | |
get _PyRuntime.gilstate.tstate_current (discarded) | |
get _PyRuntime.gilstate.autoInterpreterState (discarded) | |
tss-get _PyRuntime.gilstate.autoTSSkey -> current | |
if current == tstate: | |
tss-set _PyRuntime.gilstate.autoTSSkey <- NULL | |
get _PyRuntime.gilstate.tstate_current -> ,,, | |
set _PyRuntime.gilstate.tstate_current <- NULL | |
main | |
block on "stop" | |
get _PyRuntime.gilstate.tstate_current (discarded) | |
set _PyRuntime.gilstate.tstate_current <- oldts | |
new thread | |
release "stop" | |
############################################################################### | |
# failing on some buildbots due to https://github.com/python/cpython/pull/99378 | |
test.test_capi.test_misc.TestThreadState.test_gilstate_ensure_no_deadlock() | |
_testcapi._test_thread_state() | |
acquire-done-lock | |
PyThread_start_new_thread() -> pythread_wrapper() -> _make_call_from_thread() | |
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | |
_make_call() | |
PyGILState_Ensure() | |
... | |
PyObject_CallNoArgs() | |
PyGILState_Release() | |
... | |
release-done-lock | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
_make_call() | |
... | |
Py_BEGIN_ALLOW_THREADS | |
... | |
_make_call() | |
... | |
block-on-done-lock | |
Py_END_ALLOW_THREADS | |
... | |
Py_BEGIN_ALLOW_THREADS | |
... | |
PyThread_start_new_thread() | |
_make_call() | |
... | |
block-on-done-lock | |
Py_END_ALLOW_THREADS | |
... | |
******************************************************************************* | |
... | |
############################################################################### |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment