From 088c8a15411bba6453ee838b522b3bfa4ef3cd72 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Fri, 10 Nov 2023 16:28:26 -0500 Subject: [PATCH 1/3] Add "how to" for the critical_section Argument Clinic directive. See also https://github.com/python/cpython/issues/111903. --- development-tools/clinic.rst | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/development-tools/clinic.rst b/development-tools/clinic.rst index 08ba17cbff..615bb0c543 100644 --- a/development-tools/clinic.rst +++ b/development-tools/clinic.rst @@ -1955,6 +1955,47 @@ The generated docstring ends up looking like this: Return a copy of the code object with new values for the specified fields. +.. _clinic-howto-critical-sections: + +How to use critical sections with Argument Clinic +------------------------------------------------- + +You can use the ``@critical_section`` directive to instruct Argument Clinic to +wrap the call to the "impl" function in a Python critical section. In +``--disable-gil`` builds of CPython, the critical section will acquire the +per-object lock of the first argument. Python critical sections are no-ops in +builds of CPython with the GIL. + +See :cpy-file:`Include/internal/pycore_critical_section.h` and :pep:`703` for +more details about critical sections. + +Example from :cpy-file:`Modules/_io/bufferedio.c`:: + + /*[clinic input] + @critical_section + _io._Buffered.close + [clinic start generated code]*/ + +The generated glue code looks like this: + +.. code-block:: c + + static PyObject * + _io__Buffered_close(buffered *self, PyObject *Py_UNUSED(ignored)) + { + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = _io__Buffered_close_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; + } + + +.. versionadded:: 3.13 + + .. _clinic-howto-deprecate-positional: .. _clinic-howto-deprecate-keyword: From 6a80036fcf2162011574493fc409a3ad635ace04 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Tue, 14 Nov 2023 10:51:08 +0000 Subject: [PATCH 2/3] SemBr Co-authored-by: Erlend E. Aasland --- development-tools/clinic.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/development-tools/clinic.rst b/development-tools/clinic.rst index 615bb0c543..c98ffb81f6 100644 --- a/development-tools/clinic.rst +++ b/development-tools/clinic.rst @@ -1961,10 +1961,10 @@ How to use critical sections with Argument Clinic ------------------------------------------------- You can use the ``@critical_section`` directive to instruct Argument Clinic to -wrap the call to the "impl" function in a Python critical section. In -``--disable-gil`` builds of CPython, the critical section will acquire the -per-object lock of the first argument. Python critical sections are no-ops in -builds of CPython with the GIL. +wrap the call to the "impl" function in a Python critical section. +In ``--disable-gil`` builds of CPython, +the critical section will acquire the per-object lock of the first argument. +Python critical sections are no-ops in builds of CPython with the GIL. See :cpy-file:`Include/internal/pycore_critical_section.h` and :pep:`703` for more details about critical sections. From 6df4ecdb6bed6d8f96fb22e8dd476e35f9683ee9 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Tue, 14 Nov 2023 11:07:52 -0500 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Alex Waygood --- development-tools/clinic.rst | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/development-tools/clinic.rst b/development-tools/clinic.rst index c98ffb81f6..aa0efddd6b 100644 --- a/development-tools/clinic.rst +++ b/development-tools/clinic.rst @@ -1961,13 +1961,18 @@ How to use critical sections with Argument Clinic ------------------------------------------------- You can use the ``@critical_section`` directive to instruct Argument Clinic to -wrap the call to the "impl" function in a Python critical section. -In ``--disable-gil`` builds of CPython, -the critical section will acquire the per-object lock of the first argument. -Python critical sections are no-ops in builds of CPython with the GIL. +wrap the call to the "impl" function in a "Python critical section". +In builds of CPython without the Global Interpreter Lock ("GIL"), +critical sections are required in order to achieve +thread safety without causing deadlocks between threads. +When a critical section is entered into, a per-object lock associated +with the first argument of the decorated function is acquired. +The lock is released on exiting the critical section. -See :cpy-file:`Include/internal/pycore_critical_section.h` and :pep:`703` for -more details about critical sections. +Python critical sections are no-ops in builds of CPython with the GIL. +See :cpy-file:`Include/internal/pycore_critical_section.h` +and :pep:`PEP 703 <703#python-critical-sections>` +for more details about critical sections. Example from :cpy-file:`Modules/_io/bufferedio.c`::