From 2dae505e87e3815f087d4b07a71bb2c5cce22304 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Fri, 3 May 2024 11:09:57 -0400 Subject: gh-117514: Add `sys._is_gil_enabled()` function (#118514) The function returns `True` or `False` depending on whether the GIL is currently enabled. In the default build, it always returns `True` because the GIL is always enabled. --- Doc/library/sys.rst | 8 ++++++ Lib/test/test_sys.py | 6 +++++ .../2024-05-02-16-04-51.gh-issue-117514.CJiuC0.rst | 4 +++ Python/clinic/sysmodule.c.h | 30 +++++++++++++++++++++- Python/sysmodule.c | 20 +++++++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-05-02-16-04-51.gh-issue-117514.CJiuC0.rst diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 19d6856..91afa9d 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1199,6 +1199,14 @@ always available. return value of :func:`intern` around to benefit from it. +.. function:: _is_gil_enabled() + + Return :const:`True` if the :term:`GIL` is enabled and :const:`False` if + it is disabled. + + .. versionadded:: 3.13 + + .. function:: is_finalizing() Return :const:`True` if the main Python interpreter is diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 14ec51e..df0a6f0 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1053,6 +1053,12 @@ class SysModuleTest(unittest.TestCase): c = sys.getallocatedblocks() self.assertIn(c, range(b - 50, b + 50)) + def test_is_gil_enabled(self): + if support.Py_GIL_DISABLED: + self.assertIs(type(sys._is_gil_enabled()), bool) + else: + self.assertTrue(sys._is_gil_enabled()) + def test_is_finalizing(self): self.assertIs(sys.is_finalizing(), False) # Don't use the atexit module because _Py_Finalizing is only set diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-05-02-16-04-51.gh-issue-117514.CJiuC0.rst b/Misc/NEWS.d/next/Core and Builtins/2024-05-02-16-04-51.gh-issue-117514.CJiuC0.rst new file mode 100644 index 0000000..fc162af --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-05-02-16-04-51.gh-issue-117514.CJiuC0.rst @@ -0,0 +1,4 @@ +Add ``sys._is_gil_enabled()`` function that returns whether the GIL is +currently enabled. In the default build it always returns ``True`` because +the GIL is always enabled. In the free-threaded build, it may return +``True`` or ``False``. diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index 31f66e8..0a8704c 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -1485,6 +1485,34 @@ exit: return return_value; } +PyDoc_STRVAR(sys__is_gil_enabled__doc__, +"_is_gil_enabled($module, /)\n" +"--\n" +"\n" +"Return True if the GIL is currently enabled and False otherwise."); + +#define SYS__IS_GIL_ENABLED_METHODDEF \ + {"_is_gil_enabled", (PyCFunction)sys__is_gil_enabled, METH_NOARGS, sys__is_gil_enabled__doc__}, + +static int +sys__is_gil_enabled_impl(PyObject *module); + +static PyObject * +sys__is_gil_enabled(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + int _return_value; + + _return_value = sys__is_gil_enabled_impl(module); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyBool_FromLong((long)_return_value); + +exit: + return return_value; +} + #ifndef SYS_GETWINDOWSVERSION_METHODDEF #define SYS_GETWINDOWSVERSION_METHODDEF #endif /* !defined(SYS_GETWINDOWSVERSION_METHODDEF) */ @@ -1528,4 +1556,4 @@ exit: #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=518424ee03e353b0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=352ac7a0085e8a1f input=a9049054013a1b77]*/ diff --git a/Python/sysmodule.c b/Python/sysmodule.c index d3fbfcd..f469f16 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2393,6 +2393,25 @@ sys__get_cpu_count_config_impl(PyObject *module) return config->cpu_count; } +/*[clinic input] +sys._is_gil_enabled -> bool + +Return True if the GIL is currently enabled and False otherwise. +[clinic start generated code]*/ + +static int +sys__is_gil_enabled_impl(PyObject *module) +/*[clinic end generated code: output=57732cf53f5b9120 input=7e9c47f15a00e809]*/ +{ +#ifdef Py_GIL_DISABLED + PyInterpreterState *interp = _PyInterpreterState_GET(); + return interp->ceval.gil->enabled; +#else + return 1; +#endif +} + + static PerfMapState perf_map_state; PyAPI_FUNC(int) PyUnstable_PerfMapState_Init(void) { @@ -2565,6 +2584,7 @@ static PyMethodDef sys_methods[] = { SYS__STATS_DUMP_METHODDEF #endif SYS__GET_CPU_COUNT_CONFIG_METHODDEF + SYS__IS_GIL_ENABLED_METHODDEF {NULL, NULL} // sentinel }; -- cgit v0.12