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);
}