[pypy-commit] pypy cpyext-gil-ensure: Write the plan
arigo
pypy.commits at gmail.com
Tue Mar 22 06:44:15 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: cpyext-gil-ensure
Changeset: r83244:4198667ea611
Date: 2016-03-22 11:43 +0100
http://bitbucket.org/pypy/pypy/changeset/4198667ea611/
Log: Write the plan
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -192,6 +192,58 @@
# exceptions generate a OperationError(w_SystemError); and the funtion returns
# the error value specifed in the API.
#
+# Handling of the GIL
+# -------------------
+#
+# We add a global variable that contains a thread id. Invariant: this
+# variable always contain 0 when the PyPy GIL is released. It should
+# also contain 0 when regular RPython code executes. In
+# non-cpyext-related code, it will thus always be 0.
+#
+# **make_generic_cpy_call():** RPython to C, with the GIL held. Before
+# the call, must assert that the global variable is 0 and set the
+# current thread identifier into the global variable. After the call,
+# assert that the global variable still contains the current thread id,
+# and reset it to 0.
+#
+# **make_wrapper():** C to RPython; by default assume that the GIL is
+# held, but accepts gil="acquire", "release", "around",
+# "pygilstate_ensure", "pygilstate_release".
+#
+# When a wrapper() is called:
+#
+# * "acquire": assert that the GIL is not currently held, i.e. the
+# global variable does not contain the current thread id (otherwise,
+# deadlock!). Acquire the PyPy GIL. After we acquired it, assert
+# that the global variable is 0 (it must be 0 according to the
+# invariant that it was 0 immediately before we acquired the GIL,
+# because the GIL was released at that point).
+#
+# * gil=None: we hold the GIL already. Assert that the current thread
+# identifier is in the global variable, and replace it with 0.
+#
+# * "pygilstate_ensure": if the global variable contains the current
+# thread id, replace it with 0 and set the extra arg to 0. Otherwise,
+# do the "acquire" and set the extra arg to 1. Then we'll call
+# pystate.py:PyGILState_Ensure() with this extra arg, which will do
+# the rest of the logic.
+#
+# When a wrapper() returns, first assert that the global variable is
+# still 0, and then:
+#
+# * "release": release the PyPy GIL. The global variable was 0 up to
+# and including at the point where we released the GIL, but afterwards
+# it is possible that the GIL is acquired by a different thread very
+# quickly.
+#
+# * gil=None: we keep holding the GIL. Set the current thread
+# identifier into the global variable.
+#
+# * "pygilstate_release": if the argument is PyGILState_UNLOCKED,
+# release the PyPy GIL; otherwise, set the current thread identifier
+# into the global variable. The rest of the logic of
+# PyGILState_Release() should be done before, in pystate.py.
+
cpyext_namespace = NameManager('cpyext_')
More information about the pypy-commit
mailing list