This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 07a470f6966 sched: Improve nxsched stack overflow checking
implementation
07a470f6966 is described below
commit 07a470f6966622b4a4f3b59fb86c292139329062
Author: wangchengdong <[email protected]>
AuthorDate: Wed Oct 1 21:46:38 2025 +0800
sched: Improve nxsched stack overflow checking implementation
1. Remove STACKCHECK_SOFTWARE config,
2. Do sp value checking when STACKCHECK_MARGIN == 0,
3. Do margin-based stack check when STACKCHECK_MARGIN > 0,
4. Disable stack check when STACKCHECK_MARGIN == -1
Signed-off-by: Chengdong Wang <[email protected]>
---
Documentation/debugging/stackcheck.rst | 3 +-
Kconfig | 16 +-----
sched/irq/irq_dispatch.c | 2 +-
sched/sched/CMakeLists.txt | 6 ++
sched/sched/Make.defs | 6 ++
sched/sched/nxsched_checkstackoverflow.c | 94 ++++++++++++++++++++++++++++++++
sched/sched/sched.h | 7 +++
sched/sched/sched_switchcontext.c | 15 +----
8 files changed, 119 insertions(+), 30 deletions(-)
diff --git a/Documentation/debugging/stackcheck.rst
b/Documentation/debugging/stackcheck.rst
index 39e848782a7..064d85cf587 100644
--- a/Documentation/debugging/stackcheck.rst
+++ b/Documentation/debugging/stackcheck.rst
@@ -56,8 +56,7 @@ Stack Overflow Software Check During Context Switching
2. Check if the sp register is out of bounds.
Usage:
- Enable CONFIG_STACKCHECK_SOFTWARE
- You can set the detection length by STACKCHECK_MARGIN
+ Set the detection length by STACKCHECK_MARGIN
Stack Overflow Hardware Check
-----------------------------
diff --git a/Kconfig b/Kconfig
index a6cb1a255ec..9249de831e1 100644
--- a/Kconfig
+++ b/Kconfig
@@ -2455,23 +2455,13 @@ config STACK_COLORATION
Only supported by a few architectures.
-config STACKCHECK_SOFTWARE
- bool "Software detection of stack overflow"
- depends on STACK_COLORATION && DEBUG_ASSERTIONS
- ---help---
- When switching contexts, it will detect whether a stack
overflow occurs.
- Two methods are used here.
- The first is to check the legitimacy of the value of the sp
register;
- the second is to check the specified number of bytes at the
bottom of the stack.
- If either of these two methods fails, an ASSERT will be
triggered.
-
config STACKCHECK_MARGIN
int "Stack overflow check size (bytes)"
- depends on STACKCHECK_SOFTWARE
- default 16
+ depends on DEBUG_ASSERTIONS
+ default -1
---help---
Specifies the number of bytes at the end of the stack to check
for overflow.
- A value of 0 disables additional checking. Increase this value
for stricter
+ A value of -1 disables additional checking. Increase this value
for stricter
overflow detection, at the cost of additional overhead.
config STACK_CANARIES
diff --git a/sched/irq/irq_dispatch.c b/sched/irq/irq_dispatch.c
index 561eae68787..33f7d7a035a 100644
--- a/sched/irq/irq_dispatch.c
+++ b/sched/irq/irq_dispatch.c
@@ -158,7 +158,7 @@ void irq_dispatch(int irq, FAR void *context)
}
#endif
-#if defined(CONFIG_STACKCHECK_SOFTWARE) && CONFIG_STACKCHECK_MARGIN > 0
+#if defined(CONFIG_STACKCHECK_MARGIN) && (CONFIG_STACKCHECK_MARGIN > 0)
DEBUGASSERT(up_check_intstack(this_cpu(),
CONFIG_STACKCHECK_MARGIN) == 0);
#endif
diff --git a/sched/sched/CMakeLists.txt b/sched/sched/CMakeLists.txt
index 83df2678436..1edfe87fc61 100644
--- a/sched/sched/CMakeLists.txt
+++ b/sched/sched/CMakeLists.txt
@@ -49,6 +49,12 @@ set(SRCS
sched_get_stateinfo.c
sched_switchcontext.c)
+if(DEFINED CONFIG_STACKCHECK_MARGIN)
+ if(NOT CONFIG_STACKCHECK_MARGIN EQUAL -1)
+ list(APPEND SRCS nxsched_checkstackoverflow.c)
+ endif()
+endif()
+
if(CONFIG_PRIORITY_INHERITANCE)
list(APPEND SRCS sched_reprioritize.c)
endif()
diff --git a/sched/sched/Make.defs b/sched/sched/Make.defs
index be076eca23d..7cc19db557b 100644
--- a/sched/sched/Make.defs
+++ b/sched/sched/Make.defs
@@ -32,6 +32,12 @@ CSRCS += sched_idletask.c sched_self.c sched_get_stackinfo.c
sched_get_tls.c
CSRCS += sched_sysinfo.c sched_get_stateinfo.c sched_getcpu.c
CSRCS += sched_switchcontext.c
+ifneq ($(CONFIG_STACKCHECK_MARGIN),)
+ ifneq ($(CONFIG_STACKCHECK_MARGIN),-1)
+ CSRCS += nxsched_checkstackoverflow.c
+ endif
+endif
+
ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
CSRCS += sched_reprioritize.c
endif
diff --git a/sched/sched/nxsched_checkstackoverflow.c
b/sched/sched/nxsched_checkstackoverflow.c
new file mode 100644
index 00000000000..163623781d5
--- /dev/null
+++ b/sched/sched/nxsched_checkstackoverflow.c
@@ -0,0 +1,94 @@
+/****************************************************************************
+ * sched/sched/nxsched_checkstackoverflow.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <time.h>
+#include <assert.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/sched.h>
+#include <nuttx/sched_note.h>
+
+#include "sched/sched.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nxsched_checkstackoverflow
+ *
+ * Description:
+ * Verify that the specified thread has not overflowed its stack.
+ *
+ * Behavior depends on CONFIG_STACKCHECK_MARGIN:
+ *
+ * - CONFIG_STACKCHECK_MARGIN == 0:
+ * Perform a strict boundary check. The current stack pointer must
+ * remain within the allocated stack region [base, top].
+ *
+ * - CONFIG_STACKCHECK_MARGIN > 0:
+ * Perform an architecture-specific check with a safety margin.
+ * The stack must not extend beyond the reserved margin area.
+ *
+ * - CONFIG_STACKCHECK_MARGIN < 0:
+ * Stack checking is disabled at build time. In this case, calls to
+ * nxsched_checkstackoverflow() are replaced with a no-op macro.
+ *
+ * Input Parameters:
+ * tcb - Pointer to the TCB of the thread to be checked.
+ *
+ * Returned Value:
+ * None. The function will trigger a DEBUGASSERT if a stack overflow
+ * condition is detected.
+ *
+ ****************************************************************************/
+
+void nxsched_checkstackoverflow(FAR struct tcb_s *tcb)
+{
+#if (CONFIG_STACKCHECK_MARGIN == 0)
+ /* Strict stack pointer check:
+ * SP must remain within the allocated stack boundaries.
+ */
+
+ if (tcb->xcp.regs != NULL)
+ {
+ uintptr_t sp = up_getusrsp(tcb->xcp.regs);
+ uintptr_t top = (uintptr_t)tcb->stack_base_ptr + tcb->adj_stack_size;
+ uintptr_t bot = (uintptr_t)tcb->stack_base_ptr;
+
+ DEBUGASSERT(sp > bot && sp <= top);
+ }
+
+#elif defined(CONFIG_STACK_COLORATION) && (CONFIG_STACKCHECK_MARGIN > 0)
+ /* Margin-based stack check:
+ * Allow some reserved margin area before reporting overflow.
+ */
+
+ DEBUGASSERT(up_check_tcbstack(tcb, CONFIG_STACKCHECK_MARGIN) == 0);
+#endif
+}
diff --git a/sched/sched/sched.h b/sched/sched/sched.h
index 2ce145d1db7..9e0432b90f1 100644
--- a/sched/sched/sched.h
+++ b/sched/sched/sched.h
@@ -393,6 +393,13 @@ static inline_function FAR struct tcb_s *this_task(void)
}
#endif
+#if defined(CONFIG_STACKCHECK_MARGIN) && \
+ (CONFIG_STACKCHECK_MARGIN != -1)
+void nxsched_checkstackoverflow(FAR struct tcb_s *tcb);
+#else
+# define nxsched_checkstackoverflow(tcb)
+#endif
+
#ifdef CONFIG_SMP
bool nxsched_switch_running(int cpu, bool switch_equal);
void nxsched_process_delivered(int cpu);
diff --git a/sched/sched/sched_switchcontext.c
b/sched/sched/sched_switchcontext.c
index 0db4e01b984..aa4c5e7e564 100644
--- a/sched/sched/sched_switchcontext.c
+++ b/sched/sched/sched_switchcontext.c
@@ -49,20 +49,7 @@
void nxsched_switch_context(FAR struct tcb_s *from, FAR struct tcb_s *to)
{
-#ifdef CONFIG_STACKCHECK_SOFTWARE
- if (from->xcp.regs)
- {
- uintptr_t sp = up_getusrsp(from->xcp.regs);
- uintptr_t top = (uintptr_t)from->stack_base_ptr + from->adj_stack_size;
- uintptr_t bottom = (uintptr_t)from->stack_base_ptr;
- DEBUGASSERT(sp > bottom && sp <= top);
- }
-
-#if CONFIG_STACKCHECK_MARGIN > 0
- DEBUGASSERT(up_check_tcbstack(from, CONFIG_STACKCHECK_MARGIN) == 0);
-#endif
-
-#endif
+ nxsched_checkstackoverflow(from);
#ifdef CONFIG_SCHED_SPORADIC
/* Perform sporadic schedule operations */