Skip to content

feat(kernel): Check interrupt-disabled context in RT_DEBUG_SCHEDULER_…#11315

Open
wdfk-prog wants to merge 1 commit intoRT-Thread:masterfrom
wdfk-prog:RT_DEBUG_SCHEDULER_AVAILABLE
Open

feat(kernel): Check interrupt-disabled context in RT_DEBUG_SCHEDULER_…#11315
wdfk-prog wants to merge 1 commit intoRT-Thread:masterfrom
wdfk-prog:RT_DEBUG_SCHEDULER_AVAILABLE

Conversation

@wdfk-prog
Copy link
Copy Markdown
Contributor

@wdfk-prog wdfk-prog commented Apr 5, 2026

为什么提交这份PR (why to submit this PR)

修复 RT_DEBUG_SCHEDULER_AVAILABLE() 对“调度器可用上下文”的判断不完整问题。

当前实现仅检查:

  • rt_critical_level() == 0,即 scheduler lock 已释放;
  • 当前处于线程上下文,而非中断上下文。

但它没有覆盖这样一种场景:

  • 当前仍在线程上下文;
  • 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 仅做一处内核检查增强:

  1. 补充中断关闭状态检查

    • include/rtthread.hRT_DEBUG_SCHEDULER_AVAILABLE() 宏中,增加 rt_hw_interrupt_is_disabled() 判断;
    • 当 scheduler lock 未释放,或当前处于全局关中断状态时,统一判定为 scheduler is not available
  2. 收紧阻塞型接口的上下文约束

    • 让依赖 RT_DEBUG_SCHEDULER_AVAILABLE(RT_TRUE) 的 IPC / 同步原语接口,在“线程上下文但中断已关闭”的场景下尽早断言;
    • 避免继续进入 suspend / schedule / timeout 相关路径后才暴露问题。
  3. 提升问题定位效率

    • 对调用者来说,错误会在前置条件检查阶段直接暴露;
    • 比进入深层等待逻辑后出现 thread->error 异常、owner 状态不一致或断言失败更容易定位。

修改内容 (patch summary)

-        if (rt_critical_level() != 0)
+        if ((rt_critical_level() != 0) || rt_hw_interrupt_is_disabled())

请提供验证的bsp和config (provide the config and bsp)

  • BSP:

    • bsp/stm32/...(请填写实际验证的 BSP 路径)
  • .config:

    • RT_USING_MUTEX
    • RT_USING_SEMAPHORE
    • RT_DEBUGING_ASSERT
    • 以及实际复现问题所需的 BSP / 驱动配置
  • 建议验证场景:

    1. 在线程上下文、开中断状态下调用 rt_mutex_take(..., timeout),行为保持不变;
    2. rt_hw_interrupt_disable() 保护区内调用可能阻塞的 IPC 接口,能够被前置断言及时捕获;
    3. 验证 timeout == 0 的 try-take / 非阻塞路径是否符合预期;
    4. 回归检查常见 BSP 启动与 IPC 基本用例,确认未引入误报。
  • action:

    • 请填写你自己仓库 PR branch 对应的 CI / Action 链接

当前拉取/合并请求的状态 Intent for your PR

必须选择一项 Choose one (Mandatory):

  • 本拉取/合并请求是一个草稿版本 This PR is for a code-review and is intended to get feedback
  • 本拉取/合并请求是一个成熟版本 This PR is mature, and ready to be integrated into the repo

代码质量 Code Quality:

我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:

  • 已经仔细查看过代码改动的对比 Already check the difference between PR and old code
  • 代码风格正确,包括缩进空格,命名及其他风格 Style guide is adhered to, including spacing, naming and other styles
  • 没有垃圾代码,代码尽量精简,不包含#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up
  • 所有变更均有原因及合理的,并且不会影响到其他软件组件代码或BSP All modifications are justified and not affect other components or BSP
  • 对难懂代码均提供对应的注释 I've commented appropriately where code is tricky
  • 代码是高质量的 Code in this PR is of high quality
  • 已经使用格式化工具确保格式符合 RT-Thread 代码规范 This PR complies with RT-Thread code specification
  • 如果是新增bsp, 已经添加ci检查到 .github/ALL_BSP_COMPILE.json

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 5, 2026

👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread!

为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。
To ensure your code complies with RT-Thread's coding style, please run the code formatting workflow by following the steps below (If the formatting of CI fails to run).


🛠 操作步骤 | Steps

  1. 前往 Actions 页面 | Go to the Actions page
    点击进入工作流 → | Click to open workflow →

  2. 点击 Run workflow | Click Run workflow

  • 设置需排除的文件/目录(目录请以"/"结尾)
    Set files/directories to exclude (directories should end with "/")
  • 将目标分支设置为 \ Set the target branch to:RT_DEBUG_SCHEDULER_AVAILABLE
  • 设置PR number为 \ Set the PR number to:11315
  1. 等待工作流完成 | Wait for the workflow to complete
    格式化后的代码将自动推送至你的分支。
    The formatted code will be automatically pushed to your branch.

完成后,提交将自动更新至 RT_DEBUG_SCHEDULER_AVAILABLE 分支,关联的 Pull Request 也会同步更新。
Once completed, commits will be pushed to the RT_DEBUG_SCHEDULER_AVAILABLE branch automatically, and the related Pull Request will be updated.

如有问题欢迎联系我们,再次感谢您的贡献!💐
If you have any questions, feel free to reach out. Thanks again for your contribution!

@Rbb666 Rbb666 self-requested a review April 13, 2026 02:52
@Rbb666
Copy link
Copy Markdown
Member

Rbb666 commented Apr 14, 2026

这个 pr 要测试下,能否给个简单的测试用例,我压测一下

@Rbb666 Rbb666 requested review from BernardXiong and Copilot April 14, 2026 01:28
@Rbb666
Copy link
Copy Markdown
Member

Rbb666 commented Apr 14, 2026

@BernardXiong 熊大也看看,不知道 smart 那边是否会有关闭中断后还允许调度的行为

@wdfk-prog
Copy link
Copy Markdown
Contributor Author

wdfk-prog commented Apr 14, 2026

这个 pr 要测试下,能否给个简单的测试用例,我压测一下

  • 这个只能提供一种场景吧;用户异常操作在中断屏蔽里面执行了互斥锁获取
  • 没有仔细看过,互斥锁是否有另一个地方已经加锁了
    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);
    }

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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() and rt_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;                                           \
    }                                                                         \

@Rbb666
Copy link
Copy Markdown
Member

Rbb666 commented Apr 14, 2026

这个 pr 要测试下,能否给个简单的测试用例,我压测一下

  • 这个只能提供一种场景吧;用户异常操作在中断屏蔽里面执行了互斥锁获取

  • 没有仔细看过,互斥锁是否有另一个地方已经加锁了

    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);

    }

嗯,如果是这样的行为确实会有问题,关闭中断后尝试的 ipc 行为会导致无法进行上下文调度,这种行为也应该是在应用层要避免的😂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants