From bc023e1d2127175e1fd3a4c05fe406cd5711e4a2 Mon Sep 17 00:00:00 2001 From: wdfk-prog <1425075683@qq.com> Date: Tue, 7 Apr 2026 13:38:34 +0800 Subject: [PATCH] fix[src][thread]: add defensive check for idle thread suspension --- include/rtthread.h | 1 + src/idle.c | 38 ++++++++++++++++++++++++++++++++++++++ src/thread.c | 1 + 3 files changed, 40 insertions(+) diff --git a/include/rtthread.h b/include/rtthread.h index 08c57f58101..486ad7a3028 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -218,6 +218,7 @@ rt_err_t rt_thread_idle_sethook(void (*hook)(void)); rt_err_t rt_thread_idle_delhook(void (*hook)(void)); #endif /* defined(RT_USING_HOOK) || defined(RT_USING_IDLE_HOOK) */ rt_thread_t rt_thread_idle_gethandler(void); +rt_bool_t rt_thread_is_idle_thread(rt_thread_t thread); /* * schedule service diff --git a/src/idle.c b/src/idle.c index 9a048061990..64ee6156c56 100644 --- a/src/idle.c +++ b/src/idle.c @@ -212,4 +212,42 @@ rt_thread_t rt_thread_idle_gethandler(void) return (rt_thread_t)(&idle_thread[id]); } +/** + * @brief Check whether the specified thread is one of the system idle threads. + * + * @details + * RT-Thread creates an idle thread for each CPU. These idle threads are special + * scheduler-owned threads that act as the fallback runnable threads when no + * other ready thread exists. + * + * This helper is mainly used for defensive checks in code paths that may block + * or suspend a thread, because an idle thread must never enter a blocking or + * suspended state. Suspending an idle thread may leave the system with no ready + * thread and break scheduling. + * + * @param thread The thread to test. + * + * @return RT_TRUE if @p thread is an idle thread of any CPU; otherwise RT_FALSE. + * + * @note + * - In SMP configurations, there is one idle thread per CPU, so this function + * checks against all idle thread objects. + * - Passing RT_NULL returns RT_FALSE. + */ +rt_bool_t rt_thread_is_idle_thread(rt_thread_t thread) +{ + rt_ubase_t i; + + if (thread != RT_NULL) + { + for (i = 0; i < _CPUS_NR; i++) + { + if (thread == &idle_thread[i]) + return RT_TRUE; + } + } + + return RT_FALSE; +} + /** @} group_thread_management */ diff --git a/src/thread.c b/src/thread.c index 15e4ee45e85..ce685791772 100644 --- a/src/thread.c +++ b/src/thread.c @@ -943,6 +943,7 @@ rt_err_t rt_thread_suspend_to_list(rt_thread_t thread, rt_list_t *susp_list, int /* parameter check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); + RT_ASSERT(!rt_thread_is_idle_thread(thread)); LOG_D("thread suspend: %s", thread->parent.name);