Threadx os 線程調度方法:
1,基於優先級的調度,高優先級線程搶佔低優先級線程
2,同一優先級線程可以採用基於時間片輪轉調度方式
3,線程主動掛起,其他線程獲得調度執行
幾種方式同時採用,聯合進行線程調度。
通過創建線程時設置時間片爲0,可以禁止基於時間片輪轉調度。
基於優先級搶佔調度
通過中斷或消息驅動進行調度。
1,高優先級線程搶佔低優先級線程
2,只要有高優先級線程執行,低優先級線程無法執行
3,高優先級線程可以主動掛起,低優先級線程恢復執行
4,系統中所有線程優先級相同,需要執行線程主動掛起,下一就緒線程纔有機會得到調度執行。
舉例:
1,線程a執行,發送消息給線程b,線程b優先級高,保證實時性,線程b立即搶佔線程a,獲得處理器執行
2,線程b執行過程中,發生硬件中斷,進行中斷處理。中斷處理中喚醒了線程c。
3,中斷處理完成返回時,由於線程c優先級最高,切換到線程c執行。
4,線程c處理完,主動掛起,由於之前線程b被搶佔,並且是系統中優先級最高線程,線程b獲取執行權限。
5,線程b給線程a發送消息,這是線程a並沒有立即執行。因爲線程a優先級低於線程b。
6,線程b處理完,主動掛起。線程a成爲系統中優先級最高線程,切換到線程a執行。
## 基於時間片輪轉調度方式
針對相同優先級線程進行調度,需要時鐘中斷進行驅動。一般設置週期性定時器,中斷處理時,計算執行線程時間片是否用盡,如果時間片用盡,切換到下一個線程執行。相當於相同優先級幾個線程平均分配處理器資源。
VOID _tx_timer_interrupt(VOID)
{
_tx_timer_system_clock++; /* 系統滴答時間加 */
if (_tx_timer_time_slice) { /* 如果有剩餘的時間片 */
_tx_timer_time_slice--; /* 時間片調整、減一 */
if (_tx_timer_time_slice == 0) { /* 如果當前時間片耗盡 */
_tx_timer_expired_time_slice = TX_TRUE; /* 設置標識 */
}
}
if (*_tx_timer_current_ptr) { /* 是否有定時器需要處理 */
_tx_timer_expired = TX_TRUE;
} else {
_tx_timer_current_ptr++; /* 指向下一時刻定時器就緒鏈表頭*/
if (_tx_timer_current_ptr == _tx_timer_list_end){
_tx_timer_current_ptr = _tx_timer_list_start;
}
}
if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) { /* 有事情要做 */
if (_tx_timer_expired) {
_tx_timer_expired = TX_FALSE;
_tx_thread_preempt_disable++;
_tx_thread_resume(&_tx_timer_thread); /* 回覆定時器線程 */
}
/* 時間片用盡 */
if (_tx_timer_expired_time_slice) {
_tx_timer_expired_time_slice = TX_FALSE;
if (_tx_thread_time_slice() == TX_FALSE) { /* 不需要切換,載入分配的時間片*/
_tx_timer_time_slice = _tx_thread_current_ptr -> tx_time_slice;
}
}
}
}
執行線程時間片用盡,調用_tx_thread_time_slice判斷是否進行線程切換。
UINT _tx_thread_time_slice(VOID)
{
TX_INTERRUPT_SAVE_AREA
REG_1 UINT status; /* Time-slice status flag */
REG_2 TX_THREAD *thread_ptr; /* Thread priority head pointer */
/* Pickup the current thread pointer. */
thread_ptr = _tx_thread_current_ptr;
/* Default time-slice status to false. A true value indicates this
routine did indeed perform a time-slice. */
status = TX_FALSE;
/* Lockout interrupts while thread attempts to relinquish control. */
TX_DISABLE
/* Make sure the thread is still active, i.e. not suspended. */
if (thread_ptr -> tx_state == TX_READY)
{
/* Setup a fresh time-slice for the thread. */
thread_ptr -> tx_time_slice = thread_ptr -> tx_new_time_slice;
/* Check to make sure preemption is enabled. */
if (_tx_thread_preempt_disable)
{
/* Preemption is disabled by the system, set time-slice to 1 for retry. */
thread_ptr -> tx_time_slice = 1;
/* Set status to false. */
status = TX_FALSE;
}
/* Determine if there is another thread at the same priority. */
#def 同優先級就緒隊列有其他線程,那麼進行切換
else if ((thread_ptr -> tx_ready_next != thread_ptr) &&
(thread_ptr -> tx_priority == thread_ptr -> tx_preempt_threshold))
{
/* There is another thread at this priority, make it the highest at
this priority level. */
#def 就緒隊列頭部指向下一個線程,同時相當於當前執行線程移動到了隊列尾部
_tx_thread_priority_list[thread_ptr -> tx_priority] = thread_ptr -> tx_ready_next;
/* Designate the highest priority thread as the one to execute. Don't use this
thread's priority as an index just in case a higher priority thread is now
ready! */
#def 選出新的執行線程
_tx_thread_execute_ptr = _tx_thread_priority_list[_tx_thread_highest_priority];
/* Set the status to true to indicate a preemption is going to take
place. */
status = TX_TRUE;
}
}
/* Restore previous interrupt posture. */
TX_RESTORE
/* Return to caller. */
return(status);
}