mirror of
https://github.com/apache/nuttx.git
synced 2026-05-22 13:52:22 +08:00
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 <wangchengdong@lixiang.com>
This commit is contained in:
committed by
Xiang Xiao
parent
1210dc4919
commit
07a470f696
@@ -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
|
||||
-----------------------------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user