Skip to content

Conversation

@Kurngsy
Copy link
Contributor

@Kurngsy Kurngsy commented Nov 21, 2025

Pull Request 提交信息

为什么提交这份 PR (Why to Submit This PR)

修复 rt_thread_suspend_to_list() 函数对已处于延时挂起状态线程的处理缺陷,补全重复挂起场景下的定时器管理逻辑,确保线程挂起语义的一致性。

线程因 rt_thread_mdelay() 进入延时挂起(依赖定时器唤醒)后,调用 rt_thread_suspend_to_list() 对其重复挂起时,原代码仅返回成功但未停止定时器,导致定时器超时后线程被错误唤醒,违背挂起操作的设计初衷。

你的解决方案是什么 (What is Your Solution)

  1. 扩展挂起状态校验范围:从单一 RT_THREAD_SUSPEND 状态校验,改为 RT_THREAD_SUSPEND_MASK 掩码校验,支持识别延时挂起等子类挂起状态。
  2. 完善定时器管理逻辑:检测到线程已挂起且定时器处于开启状态时,主动调用 rt_sched_thread_timer_stop() 停止定时器,避免线程被错误唤醒。
  3. 新增挂起状态升级逻辑:支持更严格的挂起类型覆盖宽松类型,细化线程挂起状态的精细化管理。
  4. 优化日志输出:升级异常状态日志级别,并在定时器被中止时输出日志报告,便于问题定位。

验证的 BSP 和 Config (Provide the Config and BSP)

  • BSP 路径rt-thread-master\bsp\nxp\imx\imxrt\imxrt1064-nxp-evk
  • 验证方式:基于上述 BSP 编译运行测试用例,验证重复挂起场景下定时器停止逻辑及线程状态一致性。

当前拉取/合并请求的状态 (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

Refactor thread suspension logic to improve clarity and correctness.
@github-actions
Copy link

👋 感谢您对 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:master
  • 设置PR number为 \ Set the PR number to:10970
  1. 等待工作流完成 | Wait for the workflow to complete
    格式化后的代码将自动推送至你的分支。
    The formatted code will be automatically pushed to your branch.

完成后,提交将自动更新至 master 分支,关联的 Pull Request 也会同步更新。
Once completed, commits will be pushed to the master 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!

@github-actions github-actions bot added the Kernel PR has src relate code label Nov 21, 2025
@github-actions
Copy link

github-actions bot commented Nov 21, 2025

📌 Code Review Assignment

🏷️ Tag: kernel

Reviewers: GorrayLi ReviewSun hamburger-os lianux-mm wdfk-prog xu18838022837

Changed Files (Click to expand)
  • src/thread.c

📊 Current Review Status (Last Updated: 2025-12-10 21:39 CST)

  • GorrayLi Pending Review
  • ReviewSun Pending Review
  • hamburger-os Pending Review
  • lianux-mm Pending Review
  • wdfk-prog Pending Review
  • xu18838022837 Pending Review

📝 Review Instructions

  1. 维护者可以通过单击此处来刷新审查状态: 🔄 刷新状态
    Maintainers can refresh the review status by clicking here: 🔄 Refresh Status

  2. 确认审核通过后评论 LGTM/lgtm
    Comment LGTM/lgtm after confirming approval

  3. PR合并前需至少一位维护者确认
    PR must be confirmed by at least one maintainer before merging

ℹ️ 刷新CI状态操作需要具备仓库写入权限。
ℹ️ Refresh CI status operation requires repository Write permission.

@Kurngsy
Copy link
Contributor Author

Kurngsy commented Nov 26, 2025

@Rbb666 麻烦review一下呢🌹

Removed unnecessary blank line in thread.c.
@Kurngsy Kurngsy requested a review from Rbb666 November 30, 2025 12:03
@Rbb666
Copy link
Member

Rbb666 commented Nov 30, 2025

@Rbb666 麻烦review一下呢🌹

我要明天测试下哈,最近有点忙

@Kurngsy
Copy link
Contributor Author

Kurngsy commented Dec 8, 2025

@Rbb666 麻烦review一下呢🌹

我要明天测试下哈,最近有点忙

👀还在吗

@Rbb666
Copy link
Member

Rbb666 commented Dec 9, 2025

@Kurngsy 我测试了下,没什么太大问题 ,然后我发现有部分代码有高度重合部分,所以微调了下,请作者看下谢谢

thread_suspend.patch

diff --git a/src/thread.c b/src/thread.c
index 481dfebeef..1a9b8f4027 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -885,26 +885,27 @@ RTM_EXPORT(rt_thread_control);
 #include <lwp_signal.h>
 #endif
 
-static void _thread_set_suspend_state(struct rt_thread *thread, int suspend_flag)
+/* Convert suspend_flag to corresponding thread suspend state value */
+static rt_uint8_t _thread_get_suspend_state(int suspend_flag)
 {
-    rt_uint8_t stat = RT_THREAD_SUSPEND_UNINTERRUPTIBLE;
-
-    RT_ASSERT(thread != RT_NULL);
     switch (suspend_flag)
     {
     case RT_INTERRUPTIBLE:
-        stat = RT_THREAD_SUSPEND_INTERRUPTIBLE;
-        break;
+        return RT_THREAD_SUSPEND_INTERRUPTIBLE;
     case RT_KILLABLE:
-        stat = RT_THREAD_SUSPEND_KILLABLE;
-        break;
+        return RT_THREAD_SUSPEND_KILLABLE;
     case RT_UNINTERRUPTIBLE:
-        stat = RT_THREAD_SUSPEND_UNINTERRUPTIBLE;
-        break;
     default:
-        RT_ASSERT(0);
-        break;
+        return RT_THREAD_SUSPEND_UNINTERRUPTIBLE;
     }
+}
+
+static void _thread_set_suspend_state(struct rt_thread *thread, int suspend_flag)
+{
+    rt_uint8_t stat;
+
+    RT_ASSERT(thread != RT_NULL);
+    stat = _thread_get_suspend_state(suspend_flag);
     RT_SCHED_CTX(thread).stat = stat | (RT_SCHED_CTX(thread).stat & ~RT_THREAD_STAT_MASK);

@@ -943,13 +944,25 @@ rt_err_t rt_thread_suspend_to_list(rt_thread_t thread, rt_list_t *susp_list, int
     RT_ASSERT(thread != RT_NULL);
     RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
 
-    LOG_D("thread suspend:  %s", thread->parent.name);
+    LOG_D("thread suspend: %s", thread->parent.name);
 
     rt_sched_lock(&slvl);
 
     stat = rt_sched_thread_get_stat(thread);
-    if (stat == RT_THREAD_SUSPEND)
+    if (stat & RT_THREAD_SUSPEND_MASK)
     {
+        if (RT_SCHED_CTX(thread).sched_flag_ttmr_set == 1)
+        {
+            /* The new suspend operation will halt the tick timer. */
+            LOG_D("Thread [%s]'s timer has been halted.\n", thread->parent.name);
+            rt_sched_thread_timer_stop(thread);
+        }
+        /* Upgrade suspend state if new state is stricter */
+        if (stat < _thread_get_suspend_state(suspend_flag))
+        {
+            _thread_set_suspend_state(thread, suspend_flag);
+        }
+
         rt_sched_unlock(slvl);
         /* Already suspended, just set status to success.  */
         return RT_EOK;

测试代码:

/*
 * 问题:线程A调用rt_thread_mdelay()进入延时挂起后,线程B调用rt_thread_suspend(A)
 *       旧代码:直接返回RT_EOK,不停止定时器,定时器超时后线程A被唤醒(BUG)
 */

#include <rtthread.h>

#define THREAD_STACK_SIZE    2048
#define THREAD_PRIORITY      25
#define THREAD_TIMESLICE     5

static volatile rt_bool_t thread_woken_up = RT_FALSE;
static rt_thread_t test_thread = RT_NULL;

/**
 * 测试线程入口
 */
static void delay_thread_entry(void *parameter)
{
    rt_uint32_t delay_ms = (rt_uint32_t)(rt_ubase_t)parameter;

    /* 进入延时挂起状态 */
    rt_thread_mdelay(delay_ms);

    /* 如果执行到这里,说明线程被唤醒了 */
    thread_woken_up = RT_TRUE;
    rt_kprintf("[Thread] Woken up!\n");

    while (1)
    {
        rt_thread_mdelay(10000);
    }
}

/**
 * 测试:验证对已延时挂起的线程再次挂起时,定时器是否被停止
 */
int test_pr10970(void)
{
    rt_err_t result;
    rt_base_t stat;
    rt_uint32_t thread_delay_ms = 300;
    rt_uint32_t wait_after_suspend = 500;

    rt_kprintf("\n=== PR #10970 Test: Timer halt on double suspend ===\n");

    thread_woken_up = RT_FALSE;

    /* 创建并启动测试线程 */
    test_thread = rt_thread_create("t_delay",
                                   delay_thread_entry,
                                   (void *)(rt_ubase_t)thread_delay_ms,
                                   THREAD_STACK_SIZE,
                                   THREAD_PRIORITY,
                                   THREAD_TIMESLICE);
    if (test_thread == RT_NULL)
    {
        rt_kprintf("[FAIL] Create thread failed!\n");
        return -1;
    }
    rt_thread_startup(test_thread);

    /* 等待线程进入 delay 状态 */
    rt_thread_mdelay(50);

    /* 对已在 delay 的线程调用 suspend */
    result = rt_thread_suspend(test_thread);
    rt_kprintf("rt_thread_suspend() = %d\n", result);
    rt_schedule();

    /* 等待超过线程原本的 delay 时间 */
    rt_kprintf("Waiting %d ms (thread delay was %d ms)...\n", wait_after_suspend, thread_delay_ms);
    rt_thread_mdelay(wait_after_suspend);

    /* 检查结果 */
    stat = RT_SCHED_CTX(test_thread).stat & RT_THREAD_STAT_MASK;
    rt_bool_t test_passed = (!thread_woken_up && (stat & RT_THREAD_SUSPEND_MASK));

    rt_kprintf("\n--- Result ---\n");
    rt_kprintf("Thread woken up: %s\n", thread_woken_up ? "YES" : "NO");
    rt_kprintf("Thread state: 0x%02x\n", (unsigned int)stat);

    if (test_passed)
    {
        rt_kprintf("[PASS] Timer stopped, PR #10970 working!\n");
    }
    else
    {
        rt_kprintf("[FAIL] Timer NOT stopped, PR #10970 NOT applied!\n");
    }

    /* 清理 */
    rt_thread_resume(test_thread);
    rt_thread_mdelay(50);
    rt_thread_delete(test_thread);
    test_thread = RT_NULL;

    return test_passed ? 0 : -1;
}
MSH_CMD_EXPORT(test_pr10970, Test PR 10970 - timer halt on double suspend);

@Kurngsy
Copy link
Contributor Author

Kurngsy commented Dec 9, 2025

@Kurngsy 我测试了下,没什么太大问题 ,然后我发现有部分代码有高度重合部分,所以微调了下,请作者看下谢谢

thread_suspend.patch

diff --git a/src/thread.c b/src/thread.c
index 481dfebeef..1a9b8f4027 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -885,26 +885,27 @@ RTM_EXPORT(rt_thread_control);
 #include <lwp_signal.h>
 #endif
 
-static void _thread_set_suspend_state(struct rt_thread *thread, int suspend_flag)
+/* Convert suspend_flag to corresponding thread suspend state value */
+static rt_uint8_t _thread_get_suspend_state(int suspend_flag)
 {
-    rt_uint8_t stat = RT_THREAD_SUSPEND_UNINTERRUPTIBLE;
-
-    RT_ASSERT(thread != RT_NULL);
     switch (suspend_flag)
     {
     case RT_INTERRUPTIBLE:
-        stat = RT_THREAD_SUSPEND_INTERRUPTIBLE;
-        break;
+        return RT_THREAD_SUSPEND_INTERRUPTIBLE;
     case RT_KILLABLE:
-        stat = RT_THREAD_SUSPEND_KILLABLE;
-        break;
+        return RT_THREAD_SUSPEND_KILLABLE;
     case RT_UNINTERRUPTIBLE:
-        stat = RT_THREAD_SUSPEND_UNINTERRUPTIBLE;
-        break;
     default:
-        RT_ASSERT(0);
-        break;
+        return RT_THREAD_SUSPEND_UNINTERRUPTIBLE;
     }
+}
+
+static void _thread_set_suspend_state(struct rt_thread *thread, int suspend_flag)
+{
+    rt_uint8_t stat;
+
+    RT_ASSERT(thread != RT_NULL);
+    stat = _thread_get_suspend_state(suspend_flag);
     RT_SCHED_CTX(thread).stat = stat | (RT_SCHED_CTX(thread).stat & ~RT_THREAD_STAT_MASK);

@@ -943,13 +944,25 @@ rt_err_t rt_thread_suspend_to_list(rt_thread_t thread, rt_list_t *susp_list, int
     RT_ASSERT(thread != RT_NULL);
     RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
 
-    LOG_D("thread suspend:  %s", thread->parent.name);
+    LOG_D("thread suspend: %s", thread->parent.name);
 
     rt_sched_lock(&slvl);
 
     stat = rt_sched_thread_get_stat(thread);
-    if (stat == RT_THREAD_SUSPEND)
+    if (stat & RT_THREAD_SUSPEND_MASK)
     {
+        if (RT_SCHED_CTX(thread).sched_flag_ttmr_set == 1)
+        {
+            /* The new suspend operation will halt the tick timer. */
+            LOG_D("Thread [%s]'s timer has been halted.\n", thread->parent.name);
+            rt_sched_thread_timer_stop(thread);
+        }
+        /* Upgrade suspend state if new state is stricter */
+        if (stat < _thread_get_suspend_state(suspend_flag))
+        {
+            _thread_set_suspend_state(thread, suspend_flag);
+        }
+
         rt_sched_unlock(slvl);
         /* Already suspended, just set status to success.  */
         return RT_EOK;

测试代码:

/*
 * 问题:线程A调用rt_thread_mdelay()进入延时挂起后,线程B调用rt_thread_suspend(A)
 *       旧代码:直接返回RT_EOK,不停止定时器,定时器超时后线程A被唤醒(BUG)
 */

#include <rtthread.h>

#define THREAD_STACK_SIZE    2048
#define THREAD_PRIORITY      25
#define THREAD_TIMESLICE     5

static volatile rt_bool_t thread_woken_up = RT_FALSE;
static rt_thread_t test_thread = RT_NULL;

/**
 * 测试线程入口
 */
static void delay_thread_entry(void *parameter)
{
    rt_uint32_t delay_ms = (rt_uint32_t)(rt_ubase_t)parameter;

    /* 进入延时挂起状态 */
    rt_thread_mdelay(delay_ms);

    /* 如果执行到这里,说明线程被唤醒了 */
    thread_woken_up = RT_TRUE;
    rt_kprintf("[Thread] Woken up!\n");

    while (1)
    {
        rt_thread_mdelay(10000);
    }
}

/**
 * 测试:验证对已延时挂起的线程再次挂起时,定时器是否被停止
 */
int test_pr10970(void)
{
    rt_err_t result;
    rt_base_t stat;
    rt_uint32_t thread_delay_ms = 300;
    rt_uint32_t wait_after_suspend = 500;

    rt_kprintf("\n=== PR #10970 Test: Timer halt on double suspend ===\n");

    thread_woken_up = RT_FALSE;

    /* 创建并启动测试线程 */
    test_thread = rt_thread_create("t_delay",
                                   delay_thread_entry,
                                   (void *)(rt_ubase_t)thread_delay_ms,
                                   THREAD_STACK_SIZE,
                                   THREAD_PRIORITY,
                                   THREAD_TIMESLICE);
    if (test_thread == RT_NULL)
    {
        rt_kprintf("[FAIL] Create thread failed!\n");
        return -1;
    }
    rt_thread_startup(test_thread);

    /* 等待线程进入 delay 状态 */
    rt_thread_mdelay(50);

    /* 对已在 delay 的线程调用 suspend */
    result = rt_thread_suspend(test_thread);
    rt_kprintf("rt_thread_suspend() = %d\n", result);
    rt_schedule();

    /* 等待超过线程原本的 delay 时间 */
    rt_kprintf("Waiting %d ms (thread delay was %d ms)...\n", wait_after_suspend, thread_delay_ms);
    rt_thread_mdelay(wait_after_suspend);

    /* 检查结果 */
    stat = RT_SCHED_CTX(test_thread).stat & RT_THREAD_STAT_MASK;
    rt_bool_t test_passed = (!thread_woken_up && (stat & RT_THREAD_SUSPEND_MASK));

    rt_kprintf("\n--- Result ---\n");
    rt_kprintf("Thread woken up: %s\n", thread_woken_up ? "YES" : "NO");
    rt_kprintf("Thread state: 0x%02x\n", (unsigned int)stat);

    if (test_passed)
    {
        rt_kprintf("[PASS] Timer stopped, PR #10970 working!\n");
    }
    else
    {
        rt_kprintf("[FAIL] Timer NOT stopped, PR #10970 NOT applied!\n");
    }

    /* 清理 */
    rt_thread_resume(test_thread);
    rt_thread_mdelay(50);
    rt_thread_delete(test_thread);
    test_thread = RT_NULL;

    return test_passed ? 0 : -1;
}
MSH_CMD_EXPORT(test_pr10970, Test PR 10970 - timer halt on double suspend);

( ͡• ͜ʖ ͡• ) 很好的改动,我还需要在重新修改后提交吗

@Rbb666
Copy link
Member

Rbb666 commented Dec 9, 2025

@Kurngsy 我测试了下,没什么太大问题 ,然后我发现有部分代码有高度重合部分,所以微调了下,请作者看下谢谢
thread_suspend.patch

diff --git a/src/thread.c b/src/thread.c
index 481dfebeef..1a9b8f4027 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -885,26 +885,27 @@ RTM_EXPORT(rt_thread_control);
 #include <lwp_signal.h>
 #endif
 
-static void _thread_set_suspend_state(struct rt_thread *thread, int suspend_flag)
+/* Convert suspend_flag to corresponding thread suspend state value */
+static rt_uint8_t _thread_get_suspend_state(int suspend_flag)
 {
-    rt_uint8_t stat = RT_THREAD_SUSPEND_UNINTERRUPTIBLE;
-
-    RT_ASSERT(thread != RT_NULL);
     switch (suspend_flag)
     {
     case RT_INTERRUPTIBLE:
-        stat = RT_THREAD_SUSPEND_INTERRUPTIBLE;
-        break;
+        return RT_THREAD_SUSPEND_INTERRUPTIBLE;
     case RT_KILLABLE:
-        stat = RT_THREAD_SUSPEND_KILLABLE;
-        break;
+        return RT_THREAD_SUSPEND_KILLABLE;
     case RT_UNINTERRUPTIBLE:
-        stat = RT_THREAD_SUSPEND_UNINTERRUPTIBLE;
-        break;
     default:
-        RT_ASSERT(0);
-        break;
+        return RT_THREAD_SUSPEND_UNINTERRUPTIBLE;
     }
+}
+
+static void _thread_set_suspend_state(struct rt_thread *thread, int suspend_flag)
+{
+    rt_uint8_t stat;
+
+    RT_ASSERT(thread != RT_NULL);
+    stat = _thread_get_suspend_state(suspend_flag);
     RT_SCHED_CTX(thread).stat = stat | (RT_SCHED_CTX(thread).stat & ~RT_THREAD_STAT_MASK);

@@ -943,13 +944,25 @@ rt_err_t rt_thread_suspend_to_list(rt_thread_t thread, rt_list_t *susp_list, int
     RT_ASSERT(thread != RT_NULL);
     RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
 
-    LOG_D("thread suspend:  %s", thread->parent.name);
+    LOG_D("thread suspend: %s", thread->parent.name);
 
     rt_sched_lock(&slvl);
 
     stat = rt_sched_thread_get_stat(thread);
-    if (stat == RT_THREAD_SUSPEND)
+    if (stat & RT_THREAD_SUSPEND_MASK)
     {
+        if (RT_SCHED_CTX(thread).sched_flag_ttmr_set == 1)
+        {
+            /* The new suspend operation will halt the tick timer. */
+            LOG_D("Thread [%s]'s timer has been halted.\n", thread->parent.name);
+            rt_sched_thread_timer_stop(thread);
+        }
+        /* Upgrade suspend state if new state is stricter */
+        if (stat < _thread_get_suspend_state(suspend_flag))
+        {
+            _thread_set_suspend_state(thread, suspend_flag);
+        }
+
         rt_sched_unlock(slvl);
         /* Already suspended, just set status to success.  */
         return RT_EOK;

测试代码:

/*
 * 问题:线程A调用rt_thread_mdelay()进入延时挂起后,线程B调用rt_thread_suspend(A)
 *       旧代码:直接返回RT_EOK,不停止定时器,定时器超时后线程A被唤醒(BUG)
 */

#include <rtthread.h>

#define THREAD_STACK_SIZE    2048
#define THREAD_PRIORITY      25
#define THREAD_TIMESLICE     5

static volatile rt_bool_t thread_woken_up = RT_FALSE;
static rt_thread_t test_thread = RT_NULL;

/**
 * 测试线程入口
 */
static void delay_thread_entry(void *parameter)
{
    rt_uint32_t delay_ms = (rt_uint32_t)(rt_ubase_t)parameter;

    /* 进入延时挂起状态 */
    rt_thread_mdelay(delay_ms);

    /* 如果执行到这里,说明线程被唤醒了 */
    thread_woken_up = RT_TRUE;
    rt_kprintf("[Thread] Woken up!\n");

    while (1)
    {
        rt_thread_mdelay(10000);
    }
}

/**
 * 测试:验证对已延时挂起的线程再次挂起时,定时器是否被停止
 */
int test_pr10970(void)
{
    rt_err_t result;
    rt_base_t stat;
    rt_uint32_t thread_delay_ms = 300;
    rt_uint32_t wait_after_suspend = 500;

    rt_kprintf("\n=== PR #10970 Test: Timer halt on double suspend ===\n");

    thread_woken_up = RT_FALSE;

    /* 创建并启动测试线程 */
    test_thread = rt_thread_create("t_delay",
                                   delay_thread_entry,
                                   (void *)(rt_ubase_t)thread_delay_ms,
                                   THREAD_STACK_SIZE,
                                   THREAD_PRIORITY,
                                   THREAD_TIMESLICE);
    if (test_thread == RT_NULL)
    {
        rt_kprintf("[FAIL] Create thread failed!\n");
        return -1;
    }
    rt_thread_startup(test_thread);

    /* 等待线程进入 delay 状态 */
    rt_thread_mdelay(50);

    /* 对已在 delay 的线程调用 suspend */
    result = rt_thread_suspend(test_thread);
    rt_kprintf("rt_thread_suspend() = %d\n", result);
    rt_schedule();

    /* 等待超过线程原本的 delay 时间 */
    rt_kprintf("Waiting %d ms (thread delay was %d ms)...\n", wait_after_suspend, thread_delay_ms);
    rt_thread_mdelay(wait_after_suspend);

    /* 检查结果 */
    stat = RT_SCHED_CTX(test_thread).stat & RT_THREAD_STAT_MASK;
    rt_bool_t test_passed = (!thread_woken_up && (stat & RT_THREAD_SUSPEND_MASK));

    rt_kprintf("\n--- Result ---\n");
    rt_kprintf("Thread woken up: %s\n", thread_woken_up ? "YES" : "NO");
    rt_kprintf("Thread state: 0x%02x\n", (unsigned int)stat);

    if (test_passed)
    {
        rt_kprintf("[PASS] Timer stopped, PR #10970 working!\n");
    }
    else
    {
        rt_kprintf("[FAIL] Timer NOT stopped, PR #10970 NOT applied!\n");
    }

    /* 清理 */
    rt_thread_resume(test_thread);
    rt_thread_mdelay(50);
    rt_thread_delete(test_thread);
    test_thread = RT_NULL;

    return test_passed ? 0 : -1;
}
MSH_CMD_EXPORT(test_pr10970, Test PR 10970 - timer halt on double suspend);

( ͡• ͜ʖ ͡• ) 很好的改动,我还需要在重新修改后提交吗

可以的,你这边检查没问题,可以覆盖这个PR的提交

@Rbb666
Copy link
Member

Rbb666 commented Dec 9, 2025

然后PR的标题建议修改下,简要说清楚这个PR主要修改的目的是什么,解决了什么问题

@Kurngsy Kurngsy changed the title [kernel] rt_thread_suspend_to_list函数补充 fix: [kernel] [thread] Resolve delayed thread wakeup bug when calling suspend repeatedly Dec 9, 2025
Refactor thread suspension logic to improve clarity and maintainability.
@Kurngsy
Copy link
Contributor Author

Kurngsy commented Dec 9, 2025

然后PR的标题建议修改下,简要说清楚这个PR主要修改的目的是什么,解决了什么问题

麻烦review一下

src/thread.c Outdated
case RT_KILLABLE:
stat = RT_THREAD_SUSPEND_KILLABLE;
break;
return RT_THREAD_SUSPEND_KILLABLE;
Copy link
Member

Choose a reason for hiding this comment

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

return后一个空格

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Kurngsy Kurngsy requested a review from Rbb666 December 10, 2025 13:44
@Rbb666 Rbb666 merged commit e4dce1d into RT-Thread:master Dec 11, 2025
3 checks passed
Dailingxiang1 pushed a commit to Dailingxiang1/rt-thread that referenced this pull request Dec 11, 2025
… suspend repeatedly (RT-Thread#10970)

* Enhance thread suspend function with stricter checks

Refactor thread suspension logic to improve clarity and correctness.

* Clean up formatting in thread.c

Removed unnecessary blank line in thread.c.

* Refactor thread suspend state handling

Refactor thread suspension logic to improve clarity and maintainability.

* Update thread.c

* Fix indentation for RT_THREAD_SUSPEND_KILLABLE case
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Kernel PR has src relate code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants