前言
多任務系統,線程和中斷是兩個競爭關系的各自獨立的實體。很多 api 是禁止在中斷中調用的。
和線程運行息息相關的函數,要求必須在任務調度運行起來以后才能使用。
以及,一些 api 被設計出來是用來在某線程操作另外一個線程,是不可以某線程針對自己使用的。
今天就說說哪些 api 禁止在中斷中調用、哪些必須在任務調度器運行以后才能使用、哪些不能線程用在自己身上。
禁止在中斷調用的 api 列表
內存堆操作類
rt_system_heap_init
rt_malloc
rt_realloc
rt_free
內存池類
rt_mp_create
rt_mp_delete
rt_mp_alloc
內核對象類
rt_object_allocate
rt_object_find
idle 線程
rt_defunct_execute
ipc 同步和消息機制類
rt_sem_create
rt_sem_delete
rt_mutex_create
rt_mutex_trytake
rt_mutex_delete
rt_event_create
rt_event_delete
rt_mb_create
rt_mb_delete
rt_mq_create
rt_mq_delete
完成量
rt_completion_wait
隊列類
rt_wqueue_wait
rt_data_queue_push
rt_data_queue_pop
延時
rt_thread_sleep
rt_thread_delay
rt_thread_delay_until
rt_thread_mdelay
注:源碼中摘錄,并無理論考證,更無實際驗證
所有被禁止在中斷中調用的函數都有個相似的特征 —— 它可能是阻塞的,導致中斷無法短時間內返回;或者它想調用可能發生阻塞的 api 。
任何引用了他們的函數也被帶跑了,不能在中斷中使用。
RT_DEBUG_NOT_IN_INTERRUPT 調試宏定義
rt-thread 定義了一個宏,當我們開啟調試的時候,它可以幫我檢查當前函數是否被中斷調用了。其實現如下:
#define RT_DEBUG_NOT_IN_INTERRUPT \
do \
{ \
rt_base_t level; \
level = rt_hw_interrupt_disable(); \
if (rt_interrupt_get_nest() != 0) \
{ \
rt_kprintf("Function[%s] shall not be used in ISR\n", __FUNCTION__); \
RT_ASSERT(0) \
} \
rt_hw_interrupt_enable(level); \
} \
while (0)
當你在源碼里看見某個函數體中有一行
引用 RT_DEBUG_NOT_IN_INTERRUPT 調試宏的幾點問題
1. rt-thread 中有多處引用了這個宏,上面函數列表里絕大部分有;
2. 有一些沒有,比如 memheap.c 文件中的 `rt_memheap_alloc` `rt_memheap_realloc` 等操作。
3. 仔細查看引用了 `RT_DEBUG_NOT_IN_INTERRUPT` 的所有函數,有部分使用宏的地方真讓人揪心,以 `rt_defunct_execute` 函數為例:
static void rt_defunct_execute(void)
{
// Loop until there is no dead thread.
// So one call to rt_defunct_execute
// will do all the cleanups. */
while (1)
{
register rt_base_t level;
rt_thread_t thread;
void (*cleanup)(struct rt_thread *tid);
#ifdef RT_USING_MODULE
struct rt_dlmodule *module = RT_NULL;
#endif
RT_DEBUG_NOT_IN_INTERRUPT; // <<--
為什么放 while 里?不是 while 之前?不應該放到函數開頭醒目的地方嗎?有人反駁了啊,放哪兒不一樣,放哪也是一行代碼的事兒!
RT_DEBUG_IN_THREAD_CONTEXT 也有用樣的使用不當,放到某個判斷內部,而不是函數開頭就引用。
4. 那么我還有個疑問:這是 idle 線程的內部調用的局部函數,會被中斷調用了?!誰有權限在中斷里引用它?!**`rt_defunct_execute` 函數應該從上面的列表里刪除掉**,這個筆者已經在 github 上 pr 修改過了
必須在線程上下文調用的 api 列表
rt_signal_wait
ipc 同步和消息機制
rt_sem_take
rt_mutex_take
rt_mutex_release
rt_event_recv
rt_mb_send_wait
rt_mb_recv
rt_mq_send_wait
rt_mq_recv
線程操作類
rt_thread_detach
rt_thread_delete
rt_thread_yield
rt_thread_delay
rt_thread_delay_until
rt_thread_mdelay
rt_thread_suspend
rt_thread_resume
其它
rt_tick_get
rt_enter_critical
rt_exit_critical
可以這么說,任務調度器啟動前,只允許 init/create/startup 某線程。
雖然,沒有發現有誰在任務調度器啟動前調用 `rt_thread_suspend` ,但是,有一大批人想使用 `rt_thread_mdelay` 幾個延時函數。以上這幾個函數開頭都應該添加 `RT_DEBUG_IN_THREAD_CONTEXT` 檢測,在源碼中用于明示此 api 的使用限制。
RT_DEBUG_IN_THREAD_CONTEXT 調試宏定義
首先,貼出來它的定義
#define RT_DEBUG_IN_THREAD_CONTEXT \
RT_DEBUG_NOT_IN_INTERRUPT; \
do \
{ \
rt_base_t level; \
level = rt_hw_interrupt_disable(); \
if (rt_thread_self() == RT_NULL) \
{ \
rt_kprintf("Function[%s] shall not be used before scheduler start\n", \
__FUNCTION__); \
RT_ASSERT(0) \
} \
rt_hw_interrupt_enable(level); \
} \
while (0)
#else
#define RT_DEBUG_NOT_IN_INTERRUPT
#define RT_DEBUG_IN_THREAD_CONTEXT
#endif
注:此定義代碼略有改動。
在線程上下文調用的函數有兩個特征:
1. 不能在中斷中調用。
2. 不能在任務調度器啟動前調用,必須線程啟動后,被線程入口函數調用。
因此,函數體中添加了此宏引用的函數,也不能在中斷響應過程中被調用。
鑒于此,本篇開頭的***“禁止在中斷調用的 api 列表” 需要進行擴充,添加上 “必須在線程上下文調用的 api 列表” 中的所有 api***。
不能用在線程自己身上的 api
首先,這類 api 有個特征,那就是形參有個 rt_thread_t 類型參數。
rt_thread_detach
rt_thread_delete
這倆不多說,一個針對靜態線程對象,一個針對動態線程對象。作用均是退出線程、清理線程。當前線程退出可以直接從 while 循環里跳出來,從線程入口函數 return 就可以。
`rt_thread_startup` 當一個線程正在運行的時候,它自己再 startup 自己是不是就很詭異了。
`rt_thread_resume` 線程掛起由得自己,喚醒就由不得自己了。
`rt_thread_control` 控制某線程的動作可能有:改變優先級、啟動線程、關閉線程、以及多核cpu上綁定線程到某 cpu。某線程偷偷修改自己的運行優先級也說得過去;自己想換個 cpu 核心做依靠,看似也可以,但是,知道當前核的感受嗎?有 cpu 資源可用已經不錯了,不是嗎?
因此,這個 api 只能用來修改自己的優先級。
特別的,目前 rt-thread 只支持當前線程自己主動 suspend ,然后等待中斷或者其它線程 resume 它。而且,僅限于定時、線程間同步和通信機制里使用。不支持 A 線程 suspend B 線程,然后某個時機再 resume B。不支持 `rt_thread_suspend` `rt_thread_resume` 直接調用。
雖然 `rt_thread_detach` `rt_thread_delete` 用來退出線程,但是,不了解線程運行機制,千萬別隨意使用這倆函數退出其它線程。如果有需要,使用消息機制讓現在自己跳出線程入口函數的 while 循環,自己從線程入口函數返回,這樣更安全可靠。
結束
感謝您的閱讀,歡迎各位提出意見,對文中的不當之處不吝賜教。
審核編輯:湯梓紅
-
API
+關注
關注
2文章
1485瀏覽量
61817 -
多任務系統
+關注
關注
0文章
11瀏覽量
6867 -
RT-Thread
+關注
關注
31文章
1272瀏覽量
39924
發布評論請先 登錄
相關推薦
評論