Przeglądaj źródła

fix[src][thread]: add defensive check for idle thread suspension

wdfk-prog 5 dni temu
rodzic
commit
29e5f61fb9
3 zmienionych plików z 40 dodań i 0 usunięć
  1. 1 0
      include/rtthread.h
  2. 38 0
      src/idle.c
  3. 1 0
      src/thread.c

+ 1 - 0
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

+ 38 - 0
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 */

+ 1 - 0
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);