diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 95ff4ee285d..377724c623e 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -654,6 +654,18 @@ with sub-interpreters: made on the main thread. This is mainly a helper/diagnostic function. +.. c:function:: int PyGILState_Check() + + Return 1 if the current thread is holding the GIL and 0 otherwise. + This function can be called from any thread at any time. + Only if it has had its Python thread state initialized and currently is + holding the GIL will it return 1. + This is mainly a helper/diagnostic function. It can be useful + for example in callback contexts or memory allocation functions when + knowing that the GIL is locked can allow the caller to perform sensitive + actions or otherwise behave differently. + + The following macros are normally used without a trailing semicolon; look for example usage in the Python source distribution. diff --git a/Include/pystate.h b/Include/pystate.h index 2017b0276ff..b29ce2a482f 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -212,6 +212,11 @@ PyAPI_FUNC(void) PyGILState_Release(PyGILState_STATE); */ PyAPI_FUNC(PyThreadState *) PyGILState_GetThisThreadState(void); +/* Helper/diagnostic function - return 1 if the current thread + * currently holds the GIL, 0 otherwise + */ +PyAPI_FUNC(int) PyGILState_Check(void); + #endif /* #ifdef WITH_THREAD */ /* The implementation of sys._current_frames() Returns a dict mapping diff --git a/Misc/NEWS b/Misc/NEWS index c7833829b44..ffa48ba4017 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ What's New in Python 3.4.0 Alpha 1? Core and Builtins ----------------- +- Issue #17522: Add the PyGILState_Check() API. + - Issue #16475: Support object instancing, recursion and interned strings in marshal diff --git a/Python/pystate.c b/Python/pystate.c index cfd61d00986..70038936d67 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -697,6 +697,15 @@ PyGILState_GetThisThreadState(void) return (PyThreadState *)PyThread_get_key_value(autoTLSkey); } +int +PyGILState_Check(void) +{ + /* can't use PyThreadState_Get() since it will assert that it has the GIL */ + PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current); + return tstate && (tstate == PyGILState_GetThisThreadState()); +} + PyGILState_STATE PyGILState_Ensure(void) {