summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngus Gratton <angus@redyak.com.au>2025-08-06 10:20:57 +1000
committerAngus Gratton <angus@redyak.com.au>2025-08-19 10:33:40 +1000
commitd8672f4cde83c0a5632f9e6ac5a55eb68fed64f9 (patch)
treebede31b12b8c34a6dd841227bf2cf664c117cf5a
parent3faf2298537ee34648d27a662529ff2aa73cec1c (diff)
unix: Increase stack sizes if running with sanitizers.
The specific problem seems to be that the runtime "Python stack frame" function call is several times more expensive in stack usage when running with UBSan on older GCC (observed on gcc 11.4 as used in CI, would get 'RuntimeError: maximum recursion depth exceeded' when running some tests with UBSan enabled.) Other stack usage (i.e. from pushing things on the stack in Python) stays the same. Whatever causes the usage seems to be mostly gone in later GCC versions. Includes a refactor to apply the same stack size multipliers for the default thread stack size same as the main stack size. This goes in a new port-specific header as it depends on macros in misc.h, so can't be in mpconfigport.h. A side effect of this is that the default thread stack size is now doubled on ARM, same as the main stack size. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
-rw-r--r--ports/unix/main.c7
-rw-r--r--ports/unix/mpthreadport.c5
-rw-r--r--ports/unix/stack_size.h54
3 files changed, 59 insertions, 7 deletions
diff --git a/ports/unix/main.c b/ports/unix/main.c
index 5f6b99f98..dd0788aaa 100644
--- a/ports/unix/main.c
+++ b/ports/unix/main.c
@@ -54,6 +54,7 @@
#include "extmod/vfs_posix.h"
#include "genhdr/mpversion.h"
#include "input.h"
+#include "stack_size.h"
// Command line options, with their defaults
static bool compile_only = false;
@@ -479,11 +480,7 @@ int main(int argc, char **argv) {
#endif
// Define a reasonable stack limit to detect stack overflow.
- mp_uint_t stack_size = 40000 * (sizeof(void *) / 4);
- #if defined(__arm__) && !defined(__thumb2__)
- // ARM (non-Thumb) architectures require more stack.
- stack_size *= 2;
- #endif
+ mp_uint_t stack_size = 40000 * UNIX_STACK_MULTIPLIER;
// We should capture stack top ASAP after start, and it should be
// captured guaranteedly before any other stack variables are allocated.
diff --git a/ports/unix/mpthreadport.c b/ports/unix/mpthreadport.c
index 141cd0218..a41b3ec9f 100644
--- a/ports/unix/mpthreadport.c
+++ b/ports/unix/mpthreadport.c
@@ -31,6 +31,7 @@
#include "py/runtime.h"
#include "py/mpthread.h"
#include "py/gc.h"
+#include "stack_size.h"
#if MICROPY_PY_THREAD
@@ -244,9 +245,9 @@ void mp_thread_start(void) {
}
mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
- // default stack size is 8k machine-words
+ // default stack size
if (*stack_size == 0) {
- *stack_size = 8192 * sizeof(void *);
+ *stack_size = 32768 * UNIX_STACK_MULTIPLIER;
}
// minimum stack size is set by pthreads
diff --git a/ports/unix/stack_size.h b/ports/unix/stack_size.h
new file mode 100644
index 000000000..f6159bb69
--- /dev/null
+++ b/ports/unix/stack_size.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2025 Angus Gratton
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef MICROPY_INCLUDED_UNIX_STACK_SIZE_H
+#define MICROPY_INCLUDED_UNIX_STACK_SIZE_H
+
+#include "py/misc.h"
+
+// Define scaling factors for the stack size (also applies to main thread)
+#ifndef UNIX_STACK_MULTIPLIER
+
+#if defined(__arm__) && !defined(__thumb2__)
+// ARM (non-Thumb) architectures require more stack.
+#define UNIX_STACK_MUL_ARM 2
+#else
+#define UNIX_STACK_MUL_ARM 1
+#endif
+
+#if MP_SANITIZER_BUILD
+// Sanitizer features consume significant stack in some cases
+// This multiplier can probably be removed when using GCC 12 or newer.
+#define UNIX_STACK_MUL_SANITIZERS 4
+#else
+#define UNIX_STACK_MUL_SANITIZERS 1
+#endif
+
+// Double the stack size for 64-bit builds, plus additional scaling
+#define UNIX_STACK_MULTIPLIER ((sizeof(void *) / 4) * UNIX_STACK_MUL_ARM * UNIX_STACK_MUL_SANITIZERS)
+
+#endif // UNIX_STACK_MULTIPLIER
+
+#endif // MICROPY_INCLUDED_UNIX_STACK_SIZE_H