RT-Thread之執行緒實現就緒列表
阿新 • • 發佈:2021-06-30
1、定義就緒列表
執行緒建立好之後,我們需要把執行緒新增到就緒列表裡面,表示執行緒已經就緒,系統隨時可以排程。就緒列表在schedule.c中定義。
/* 執行緒就緒列表 */ rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
就緒列表實際上就是一個rt_list_t 型別的陣列,陣列的大小由決定最大執行緒優先順序的巨集RT_THREAD_PRIORITY_MAX決定,RT_THREAD_PRIORITY_MAX在rtconfig中預設定義為32.陣列的下標對應了執行緒的優先順序,同一優先順序的執行緒統一插入到就緒列表的同一連結串列中。一個空的就緒列表如下:
2、將執行緒插入到就緒列表
執行緒控制塊裡面有一個tlist成員,資料型別為rt_list_t,我們將執行緒插入到就緒列表裡面,就是通過將執行緒控制塊的tlist這個節點插入到就緒列表中來實現的。如果把就緒列表比作晾衣杆,執行緒就是衣服,那tlist就是晾衣架,就是為了把自己掛在各種不同的連結串列中。執行緒插入到就緒列表的示意圖。
3、實現排程器
排程器是作業系統的核心,其主要功能就是實現執行緒的切換,即從就緒列表裡面找到優先順序最高的的執行緒,然後去執行該執行緒。從程式碼上來看,排程器無非也就是由幾個全域性變數和一些可以實現執行緒切換的函式組成,全部都在schedule.c檔案中實現。
3.1排程器初始化
排程器在使用之前必須先初始化,具體如下:
/* 初始化系統排程器 */ void rt_system_scheduler_init(void) { register rt_base_t offset;// (1) /* 執行緒就緒列表初始化 */ for (offset = 0; offset < RT_THREAD_PRIORITY_MAX; offset ++) // (2) { rt_list_init(&rt_thread_priority_table[offset]); //(2) }(1) :定義一個區域性變數,用 C 語言關鍵詞 register 修飾,防止被編譯器優化。 (2) :初始化執行緒就緒列表,初始化完後,整個就緒列表為空,具體見圖:空的執行緒就緒列表。 (3) :初始化當前執行緒控制塊指標為空。rt_current_thread 是在 scheduler.c 中定義的一個 struct rt_thread 型別的全域性指標,用於指向當前正在執行的執行緒的執行緒 控制塊。 我們把排程器初始化一般放在硬體初始化之後,執行緒建立之前/* 初始化當前執行緒控制塊指標 */ rt_current_thread = RT_NULL;// (3) }
3、啟動排程器
排程器啟動由函式 rt_system_scheduler_start() 來完成。排程器在啟動的時候會從就緒列表中取出優先順序最高的執行緒的執行緒控制塊,然後切換到該執行緒。、4、第一次執行緒切換
rt_hw_context_switch_to() 函式,第一次切換到新的執行緒,該函式在 context_rvds.s 中實現,在 rthw.h 宣告,用於實現第一次執行緒切換。當一個彙編函式在 C 檔案中呼叫的時候,如果有一個形參,則執行的時候會將這個形參傳入到 CPU 暫存器 r0,如果有兩個形參,第二個則傳入到 r1。rt_hw_context_switch_to() 的具體實現見程式碼清單: 執行緒的定義-26。context_rvds.s 檔案中涉及到的 ARM 彙編指令具體參考ARM 常用匯編指令講解。5、系統排程
系統排程就是在就緒列表中尋找優先順序最高的就緒執行緒,然後去執行該執行緒。系統排程函式rt_schedule()。