summaryrefslogtreecommitdiffstats
path: root/Include/internal
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-03-13 09:19:38 (GMT)
committerGitHub <noreply@github.com>2020-03-13 09:19:38 (GMT)
commit224481a8c988fca12f488544edd2f01c0af2a91d (patch)
tree88e6b0085773ec3591216f0f41e8ae4dcb06a5b9 /Include/internal
parent0b72b23fb0c130279f65f3bcd23521acf4a98c88 (diff)
downloadcpython-224481a8c988fca12f488544edd2f01c0af2a91d.zip
cpython-224481a8c988fca12f488544edd2f01c0af2a91d.tar.gz
cpython-224481a8c988fca12f488544edd2f01c0af2a91d.tar.bz2
bpo-39947: Move Py_EnterRecursiveCall() to internal C API (GH-18972)
Move the static inline function flavor of Py_EnterRecursiveCall() and Py_LeaveRecursiveCall() to the internal C API: they access PyThreadState attributes. The limited C API provides regular functions which hide implementation details.
Diffstat (limited to 'Include/internal')
-rw-r--r--Include/internal/pycore_ceval.h60
1 files changed, 60 insertions, 0 deletions
diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h
index 23d8091..ae6ef9a 100644
--- a/Include/internal/pycore_ceval.h
+++ b/Include/internal/pycore_ceval.h
@@ -56,6 +56,66 @@ extern PyObject *_PyEval_EvalCode(
extern int _PyEval_ThreadsInitialized(_PyRuntimeState *runtime);
extern PyStatus _PyEval_InitThreads(PyThreadState *tstate);
+
+/* --- _Py_EnterRecursiveCall() ----------------------------------------- */
+
+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. */
+static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
+ return (++tstate->recursion_depth > _Py_CheckRecursionLimit
+ || ++tstate->stackcheck_counter > 64);
+}
+#else
+static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
+ return (++tstate->recursion_depth > _Py_CheckRecursionLimit);
+}
+#endif
+
+PyAPI_FUNC(int) _Py_CheckRecursiveCall(
+ PyThreadState *tstate,
+ const char *where);
+
+static inline int _Py_EnterRecursiveCall(PyThreadState *tstate,
+ const char *where) {
+ return (_Py_MakeRecCheck(tstate) && _Py_CheckRecursiveCall(tstate, where));
+}
+
+static inline int _Py_EnterRecursiveCall_inline(const char *where) {
+ PyThreadState *tstate = PyThreadState_GET();
+ return _Py_EnterRecursiveCall(tstate, where);
+}
+
+#define Py_EnterRecursiveCall(where) _Py_EnterRecursiveCall_inline(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))
+
+static inline void _Py_LeaveRecursiveCall(PyThreadState *tstate) {
+ if (_Py_MakeEndRecCheck(tstate->recursion_depth)) {
+ tstate->overflowed = 0;
+ }
+}
+
+static inline void _Py_LeaveRecursiveCall_inline(void) {
+ PyThreadState *tstate = PyThreadState_GET();
+ _Py_LeaveRecursiveCall(tstate);
+}
+
+#define Py_LeaveRecursiveCall() _Py_LeaveRecursiveCall_inline()
+
+
#ifdef __cplusplus
}
#endif