feat(kernel): Check interrupt-disabled context in RT_DEBUG_SCHEDULER_…#11315
feat(kernel): Check interrupt-disabled context in RT_DEBUG_SCHEDULER_…#11315wdfk-prog wants to merge 1 commit intoRT-Thread:masterfrom
Conversation
|
👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread! 为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。 🛠 操作步骤 | Steps
完成后,提交将自动更新至 如有问题欢迎联系我们,再次感谢您的贡献!💐 |
|
这个 pr 要测试下,能否给个简单的测试用例,我压测一下 |
|
@BernardXiong 熊大也看看,不知道 smart 那边是否会有关闭中断后还允许调度的行为 |
rt_base_t irq_flag;
irq_flag = rt_hw_interrupt_disable();
//执行文件系统操作
rt_mutex_take
rt_mutex_release
rt_hw_interrupt_enable(irq_flag);
//会触发断言
if (mutex->owner == thread)
{
/**
* get mutex successfully
* Note: assert to avoid an unexpected resume
*/
RT_ASSERT(thread->error == RT_EOK);
} |
There was a problem hiding this comment.
Pull request overview
This PR strengthens RT-Thread kernel debug context checking by treating “thread context but globally interrupts disabled” as an invalid context for potentially blocking/scheduling code paths, via an added rt_hw_interrupt_is_disabled() check in RT_DEBUG_SCHEDULER_AVAILABLE().
Changes:
- Extend
RT_DEBUG_SCHEDULER_AVAILABLE()to also fail when global IRQs are disabled. - Tighten precondition checking for IPC/synchronization primitives that rely on
RT_DEBUG_SCHEDULER_AVAILABLE(...)to prevent entering suspend/schedule/timeout paths in an IRQ-disabled region.
Comments suppressed due to low confidence (2)
include/rtthread.h:880
- [bug/错误]: Semantics are now split between
RT_DEBUG_SCHEDULER_AVAILABLE()andrt_scheduler_is_available().
English: This macro now treats “IRQ globally disabled” as “scheduler not available”, but the inline helper rt_scheduler_is_available() in the same header still returns true when in thread context with interrupts disabled. Callers that rely on rt_scheduler_is_available() to decide whether it is safe to take mutexes or delay (e.g. SPI/ULog code paths) can still enter blocking APIs while IRQs are disabled. Consider aligning rt_scheduler_is_available() with the new definition (and updating the nearby comment to include the IRQ-enabled requirement) to keep a single, consistent notion of “scheduler available”.
中文:目前“调度器可用”的语义被拆成了两套:该调试宏新增了“全局关中断”判定,但同文件的 rt_scheduler_is_available() 仍可能在“线程上下文但已关中断”时返回真。依赖 rt_scheduler_is_available() 来决定是否可以 rt_mutex_take()/rt_thread_delay() 的代码路径(如 SPI/ULog)仍可能在关中断场景进入阻塞接口。建议同步更新 rt_scheduler_is_available()(并把上方注释也补充“需开中断”的条件),避免语义不一致。
if ((rt_critical_level() != 0) || rt_hw_interrupt_is_disabled()) \
{ \
rt_kprintf("Function[%s]: scheduler is not available\n", \
__FUNCTION__); \
RT_ASSERT(0) \
} \
RT_DEBUG_IN_THREAD_CONTEXT; \
} \
include/rtthread.h:880
- [maintainability/可维护性]: Check order may reduce diagnostic precision when scheduler hasn’t started or when in ISR.
English: RT_DEBUG_SCHEDULER_AVAILABLE() currently checks rt_critical_level()/rt_hw_interrupt_is_disabled() before RT_DEBUG_IN_THREAD_CONTEXT. If this macro is (mis)used before scheduler start or in interrupt context, it may now assert with “scheduler is not available” instead of the more specific messages from RT_DEBUG_IN_THREAD_CONTEXT (e.g., “shall not be used before scheduler start” / “shall not be used in ISR”). Consider calling RT_DEBUG_IN_THREAD_CONTEXT first, then checking critical/IRQ-disabled state, to keep the most actionable assertion message.
中文:该宏目前先检查 rt_critical_level()/rt_hw_interrupt_is_disabled(),再做 RT_DEBUG_IN_THREAD_CONTEXT。如果在调度器未启动或 ISR 中误用,可能会先触发“scheduler is not available”而不是更具体的报错信息。建议先执行 RT_DEBUG_IN_THREAD_CONTEXT,再检查 critical/关中断状态,以提升断言信息的可定位性。
if ((rt_critical_level() != 0) || rt_hw_interrupt_is_disabled()) \
{ \
rt_kprintf("Function[%s]: scheduler is not available\n", \
__FUNCTION__); \
RT_ASSERT(0) \
} \
RT_DEBUG_IN_THREAD_CONTEXT; \
} \
嗯,如果是这样的行为确实会有问题,关闭中断后尝试的 ipc 行为会导致无法进行上下文调度,这种行为也应该是在应用层要避免的😂 |
为什么提交这份PR (why to submit this PR)
修复
RT_DEBUG_SCHEDULER_AVAILABLE()对“调度器可用上下文”的判断不完整问题。当前实现仅检查:
rt_critical_level() == 0,即 scheduler lock 已释放;但它没有覆盖这样一种场景:
rt_hw_interrupt_disable()关闭。在这种情况下,代码路径表面上满足“线程上下文 + 非 scheduler lock”条件,但实际上已经不适合进入可能触发挂起、超时等待或调度切换的逻辑。对于
rt_mutex_take()、rt_sem_take()等阻塞型接口,这会放过一类非法调用场景,可能进一步导致状态不一致、异常断言或系统卡死。因此提交本 PR,在
RT_DEBUG_SCHEDULER_AVAILABLE()中补充rt_hw_interrupt_is_disabled()检查,使“scheduler available”的判定与实际运行约束保持一致。你的解决方案是什么 (what is your solution)
本 PR 仅做一处内核检查增强:
补充中断关闭状态检查
include/rtthread.h的RT_DEBUG_SCHEDULER_AVAILABLE()宏中,增加rt_hw_interrupt_is_disabled()判断;scheduler is not available。收紧阻塞型接口的上下文约束
RT_DEBUG_SCHEDULER_AVAILABLE(RT_TRUE)的 IPC / 同步原语接口,在“线程上下文但中断已关闭”的场景下尽早断言;提升问题定位效率
thread->error异常、owner 状态不一致或断言失败更容易定位。修改内容 (patch summary)
请提供验证的bsp和config (provide the config and bsp)
BSP:
bsp/stm32/...(请填写实际验证的 BSP 路径).config:
RT_USING_MUTEXRT_USING_SEMAPHORERT_DEBUGING_ASSERT建议验证场景:
rt_mutex_take(..., timeout),行为保持不变;rt_hw_interrupt_disable()保护区内调用可能阻塞的 IPC 接口,能够被前置断言及时捕获;timeout == 0的 try-take / 非阻塞路径是否符合预期;action:
当前拉取/合并请求的状态 Intent for your PR
必须选择一项 Choose one (Mandatory):
代码质量 Code Quality:
我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:
#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up.github/ALL_BSP_COMPILE.json