summaryrefslogtreecommitdiffstats
path: root/Include/cpython
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2019-11-04 18:48:34 (GMT)
committerGitHub <noreply@github.com>2019-11-04 18:48:34 (GMT)
commitf4b1e3d7c64985f5d5b00f6cc9a1c146bbbfd613 (patch)
treeb42e4aaf30370f71b5622f8a41976ac71706d8e8 /Include/cpython
parent6552563b3d5061816720a5a6c7d4ffd6ba35b98b (diff)
downloadcpython-f4b1e3d7c64985f5d5b00f6cc9a1c146bbbfd613.zip
cpython-f4b1e3d7c64985f5d5b00f6cc9a1c146bbbfd613.tar.gz
cpython-f4b1e3d7c64985f5d5b00f6cc9a1c146bbbfd613.tar.bz2
bpo-38644: Add Py_EnterRecursiveCall() to the limited API (GH-17046)
Provide Py_EnterRecursiveCall() and Py_LeaveRecursiveCall() as regular functions for the limited API. Previously, there were defined as macros, but these macros didn't work with the limited API which cannot access PyThreadState.recursion_depth field. Remove _Py_CheckRecursionLimit from the stable ABI. Add Include/cpython/ceval.h header file.
Diffstat (limited to 'Include/cpython')
-rw-r--r--Include/cpython/ceval.h50
1 files changed, 50 insertions, 0 deletions
diff --git a/Include/cpython/ceval.h b/Include/cpython/ceval.h
new file mode 100644
index 0000000..61bbc4f
--- /dev/null
+++ b/Include/cpython/ceval.h
@@ -0,0 +1,50 @@
+#ifndef Py_CPYTHON_CEVAL_H
+# error "this header file must not be included directly"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PyAPI_DATA(int) _Py_CheckRecursionLimit;
+
+#ifdef USE_STACKCHECK
+/* With USE_STACKCHECK macro defined, trigger stack checks in
+ _Py_CheckRecursiveCall() on every 64th call to Py_EnterRecursiveCall. */
+# define _Py_MakeRecCheck(x) \
+ (++(x) > _Py_CheckRecursionLimit || \
+ ++(PyThreadState_GET()->stackcheck_counter) > 64)
+#else
+# define _Py_MakeRecCheck(x) (++(x) > _Py_CheckRecursionLimit)
+#endif
+
+PyAPI_FUNC(int) _Py_CheckRecursiveCall(const char *where);
+
+#define _Py_EnterRecursiveCall_macro(where) \
+ (_Py_MakeRecCheck(PyThreadState_GET()->recursion_depth) && \
+ _Py_CheckRecursiveCall(where))
+
+#define Py_EnterRecursiveCall(where) _Py_EnterRecursiveCall_macro(where)
+
+
+/* Compute the "lower-water mark" for a recursion limit. When
+ * Py_LeaveRecursiveCall() is called with a recursion depth below this mark,
+ * the overflowed flag is reset to 0. */
+#define _Py_RecursionLimitLowerWaterMark(limit) \
+ (((limit) > 200) \
+ ? ((limit) - 50) \
+ : (3 * ((limit) >> 2)))
+
+#define _Py_MakeEndRecCheck(x) \
+ (--(x) < _Py_RecursionLimitLowerWaterMark(_Py_CheckRecursionLimit))
+
+#define _Py_LeaveRecursiveCall_macro() \
+ do{ if(_Py_MakeEndRecCheck(PyThreadState_GET()->recursion_depth)) \
+ PyThreadState_GET()->overflowed = 0; \
+ } while(0)
+
+#define Py_LeaveRecursiveCall() _Py_LeaveRecursiveCall_macro()
+
+#ifdef __cplusplus
+}
+#endif