static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
uintptr_t here_addr = _Py_get_machine_stack_pointer();
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
+#if _Py_STACK_GROWS_DOWN
return here_addr < _tstate->c_stack_soft_limit;
+#else
+ return here_addr > _tstate->c_stack_soft_limit;
+#endif
}
// Export for '_json' shared extension, used via _Py_EnterRecursiveCall()
uintptr_t here_addr = _Py_get_machine_stack_pointer();
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
assert(_tstate->c_stack_hard_limit != 0);
+#if _Py_STACK_GROWS_DOWN
return here_addr <= _tstate->c_stack_soft_limit;
+#else
+ return here_addr >= _tstate->c_stack_soft_limit;
+#endif
}
static inline void _Py_LeaveRecursiveCall(void) {
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
assert(_tstate->c_stack_hard_limit != 0);
intptr_t here_addr = _Py_get_machine_stack_pointer();
+#if _Py_STACK_GROWS_DOWN
return Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, here_addr - (intptr_t)_tstate->c_stack_soft_limit, _PyOS_STACK_MARGIN_SHIFT);
+#else
+ return Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, (intptr_t)_tstate->c_stack_soft_limit - here_addr, _PyOS_STACK_MARGIN_SHIFT);
+#endif
}
#ifdef __cplusplus
#endif
+// Assume the stack grows down unless specified otherwise
+#ifndef _Py_STACK_GROWS_DOWN
+# define _Py_STACK_GROWS_DOWN 1
+#endif
+
+
#endif /* Py_PYPORT_H */
this_sp = _testinternalcapi.get_stack_pointer()
lower_sp = _testcapi.pyobject_vectorcall(get_sp, (), ())
- self.assertLess(lower_sp, this_sp)
+ if _testcapi._Py_STACK_GROWS_DOWN:
+ self.assertLess(lower_sp, this_sp)
+ safe_margin = this_sp - lower_sp
+ else:
+ self.assertLess(this_sp, lower_sp)
+ safe_margin = lower_sp - this_sp
# Add an (arbitrary) extra 20% for safety
- safe_margin = (this_sp - lower_sp) * 6 / 5
+ safe_margin *= 6 / 5
self.assertLess(safe_margin, _testinternalcapi.get_stack_margin())
@skip_on_s390x
--- /dev/null
+Restore support for HP PA-RISC, which has an upwards-growing stack.
PyModule_AddObject(m, "INT64_MAX", PyLong_FromInt64(INT64_MAX));
PyModule_AddObject(m, "UINT64_MAX", PyLong_FromUInt64(UINT64_MAX));
+ if (PyModule_AddIntMacro(m, _Py_STACK_GROWS_DOWN)) {
+ return NULL;
+ }
+
if (PyModule_AddIntMacro(m, Py_single_input)) {
return NULL;
}
{
uintptr_t here_addr = _Py_get_machine_stack_pointer();
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
+#if _Py_STACK_GROWS_DOWN
if (here_addr > _tstate->c_stack_soft_limit + margin_count * _PyOS_STACK_MARGIN_BYTES) {
+#else
+ if (here_addr <= _tstate->c_stack_soft_limit - margin_count * _PyOS_STACK_MARGIN_BYTES) {
+#endif
return 0;
}
if (_tstate->c_stack_hard_limit == 0) {
_Py_InitializeRecursionLimits(tstate);
}
+#if _Py_STACK_GROWS_DOWN
return here_addr <= _tstate->c_stack_soft_limit + margin_count * _PyOS_STACK_MARGIN_BYTES;
+#else
+ return here_addr > _tstate->c_stack_soft_limit - margin_count * _PyOS_STACK_MARGIN_BYTES;
+#endif
}
void
{
uintptr_t here_addr = _Py_get_machine_stack_pointer();
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
+#if _Py_STACK_GROWS_DOWN
if (here_addr < _tstate->c_stack_hard_limit) {
+#else
+ if (here_addr > _tstate->c_stack_hard_limit) {
+#endif
Py_FatalError("Unchecked stack overflow.");
}
}
}
if (err == 0) {
uintptr_t base = ((uintptr_t)stack_addr) + guard_size;
- _tstate->c_stack_top = base + stack_size;
-#ifdef _Py_THREAD_SANITIZER
+ uintptr_t top = base + stack_size;
+# ifdef _Py_THREAD_SANITIZER
// Thread sanitizer crashes if we use a bit more than half the stack.
- _tstate->c_stack_soft_limit = base + (stack_size / 2);
-#else
- _tstate->c_stack_soft_limit = base + _PyOS_STACK_MARGIN_BYTES * 2;
-#endif
+# if _Py_STACK_GROWS_DOWN
+ base += stack_size / 2;
+# else
+ top -= stack_size / 2;
+# endif
+# endif
+# if _Py_STACK_GROWS_DOWN
+ _tstate->c_stack_top = top;
_tstate->c_stack_hard_limit = base + _PyOS_STACK_MARGIN_BYTES;
+ _tstate->c_stack_soft_limit = base + _PyOS_STACK_MARGIN_BYTES * 2;
assert(_tstate->c_stack_soft_limit < here_addr);
assert(here_addr < _tstate->c_stack_top);
+# else
+ _tstate->c_stack_top = base;
+ _tstate->c_stack_hard_limit = top - _PyOS_STACK_MARGIN_BYTES;
+ _tstate->c_stack_soft_limit = top - _PyOS_STACK_MARGIN_BYTES * 2;
+ assert(here_addr > base);
+ assert(here_addr < _tstate->c_stack_soft_limit);
+# endif
return;
}
# endif
uintptr_t here_addr = _Py_get_machine_stack_pointer();
assert(_tstate->c_stack_soft_limit != 0);
assert(_tstate->c_stack_hard_limit != 0);
+#if _Py_STACK_GROWS_DOWN
if (here_addr < _tstate->c_stack_hard_limit) {
/* Overflowing while handling an overflow. Give up. */
int kbytes_used = (int)(_tstate->c_stack_top - here_addr)/1024;
+#else
+ if (here_addr > _tstate->c_stack_hard_limit) {
+ /* Overflowing while handling an overflow. Give up. */
+ int kbytes_used = (int)(here_addr - _tstate->c_stack_top)/1024;
+#endif
char buffer[80];
snprintf(buffer, 80, "Unrecoverable stack overflow (used %d kB)%s", kbytes_used, where);
Py_FatalError(buffer);
return 0;
}
else {
+#if _Py_STACK_GROWS_DOWN
int kbytes_used = (int)(_tstate->c_stack_top - here_addr)/1024;
+#else
+ int kbytes_used = (int)(here_addr - _tstate->c_stack_top)/1024;
+#endif
tstate->recursion_headroom++;
_PyErr_Format(tstate, PyExc_RecursionError,
"Stack overflow (used %d kB)%s",
LIBRARY
BUILDEXEEXT
NO_AS_NEEDED
+_Py_STACK_GROWS_DOWN
MULTIARCH_CPPFLAGS
PLATFORM_TRIPLET
MULTIARCH
fi
+# Guess C stack direction
+case $host in #(
+ hppa*) :
+ _Py_STACK_GROWS_DOWN=0 ;; #(
+ *) :
+ _Py_STACK_GROWS_DOWN=1 ;;
+esac
+
+printf "%s\n" "#define _Py_STACK_GROWS_DOWN $_Py_STACK_GROWS_DOWN" >>confdefs.h
+
+
+
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PEP 11 support tier" >&5
printf %s "checking for PEP 11 support tier... " >&6; }
case $host/$ac_cv_cc_name in #(
fi
AC_SUBST([MULTIARCH_CPPFLAGS])
+# Guess C stack direction
+AS_CASE([$host],
+ [hppa*], [_Py_STACK_GROWS_DOWN=0],
+ [_Py_STACK_GROWS_DOWN=1])
+AC_DEFINE_UNQUOTED([_Py_STACK_GROWS_DOWN], [$_Py_STACK_GROWS_DOWN],
+ [Define to 1 if the machine stack grows down (default); 0 if it grows up.])
+AC_SUBST([_Py_STACK_GROWS_DOWN])
+
dnl Support tiers according to https://peps.python.org/pep-0011/
dnl
dnl NOTE: Windows support tiers are defined in PC/pyconfig.h.
/* HACL* library can compile SIMD256 implementations */
#undef _Py_HACL_CAN_COMPILE_VEC256
+/* Define to 1 if the machine stack grows down (default); 0 if it grows up. */
+#undef _Py_STACK_GROWS_DOWN
+
/* Define to force use of thread-safe errno, h_errno, and other functions */
#undef _REENTRANT