在之前 rt_schedule中need_insert_from_thread的問(wèn)題提問(wèn)中,筆者提出了當(dāng)前時(shí)間片調(diào)度算法過(guò)于復(fù)雜,且高優(yōu)先級(jí)一旦打斷未執(zhí)行完時(shí)間片的任務(wù)會(huì)導(dǎo)致該任務(wù)重新插入到其優(yōu)先級(jí)readylist末尾,存在嚴(yán)重的不公平性(破壞了時(shí)間片的連續(xù))。
當(dāng)然筆者也PR了一個(gè)解決方案(暫未合并)
https://github.com/RT-Thread/rt-thread/pull/5954
最近又有一個(gè)小伙伴發(fā)現(xiàn)了時(shí)間片調(diào)度的issue
https://github.com/RT-Thread/rt-thread/issues/6092
大致的情況是:
1、低優(yōu)先級(jí)的存在任務(wù)A(ticks = a),B(ticks =b),; 高優(yōu)先級(jí)任務(wù)C
2、如果高優(yōu)先級(jí) C內(nèi)存在延時(shí)c 正好等于A的時(shí)間片a
3、結(jié)果就是低優(yōu)先級(jí)的任務(wù)只有A在一直運(yùn)行, B一直運(yùn)行不了
這種情況的根本原因其實(shí)還是筆者之前提到的高優(yōu)先級(jí)導(dǎo)致當(dāng)前低優(yōu)先級(jí)任務(wù)插入readylist位置不對(duì)的issue,
下面筆者再次配重新整理一下這個(gè)問(wèn)題,配合圖例逐步分析源碼并結(jié)合測(cè)試?yán)陶故静煌闆r下該issue導(dǎo)致的問(wèn)題,并嘗試解決。
源碼分析
rt_tick_increase
-
/**
-
* @brief This function will notify kernel there is one tick passed.
-
* Normally, this function is invoked by clock ISR.
-
*/
-
void rt_tick_increase(void)
-
{
-
struct rt_thread *thread;
-
rt_base_t level;
-
RT_OBJECT_HOOK_CALL(rt_tick_hook,());
-
-
level = rt_hw_interrupt_disable();
-
-
/* increase the global tick */
-
#ifdef RT_USING_SMP
-
rt_cpu_self()->tick ++;
-
#else
-
++ rt_tick;
-
#endif/* RT_USING_SMP */
-
-
/* check time slice */
-
thread = rt_thread_self();
-
-
-- thread->remaining_tick;
-
if(thread->remaining_tick ==0)
-
{
-
/* change to initialized tick */
-
thread->remaining_tick = thread->init_tick;
-
thread->stat |= RT_THREAD_STAT_YIELD;
-
-
rt_hw_interrupt_enable(level);
-
rt_schedule();
-
}
-
else
-
{
-
rt_hw_interrupt_enable(level);
-
}
-
-
/* check timer */
-
rt_timer_check();
-
}
里面只做了兩件事:
1、當(dāng)前任務(wù)的時(shí)間片遞減, 如果用完了,置位RT_THREAD_STAT_YIELD狀態(tài),調(diào)用rt_schedule,2、檢測(cè)是否有任務(wù)的超時(shí)了(等待資源或延時(shí)超時(shí)),如果超時(shí),最終也會(huì)調(diào)用rt_schedulert_schedule
Who calling
排除componets中使用的情況,rt_schedule主要在下面情況中被使用1、clock.c : 就是剛剛提及的在Systick中斷中兩種比較重要的調(diào)度:時(shí)間片調(diào)度和超時(shí)調(diào)度2、ipc.c ,mempool.c: 另外一種比較重要的調(diào)度:資源阻塞和就緒調(diào)度(資源調(diào)度)3、scheduler.c, thread.c:本身調(diào)度器和線程API的使用導(dǎo)致的直接API調(diào)度4、timer.c : 軟定時(shí)器超時(shí)調(diào)度,使用的也是_thread_timeout超時(shí)函數(shù),也是超時(shí)調(diào)度 鑒于API調(diào)度一般使用在初始化階段,Application運(yùn)行中主要使用的是時(shí)間片調(diào)度,超時(shí)調(diào)度,資源調(diào)度。后面的討論中主要繞后三種展開(kāi):
源碼
-
/**
-
* @brief This function will perform scheduling once. It will select one thread
-
* with the highest priority, and switch to it immediately.
-
*/
-
void rt_schedule(void)
-
{
-
rt_base_t level;
-
struct rt_thread *to_thread;
-
struct rt_thread *from_thread;
-
-
/* disable interrupt */
-
level = rt_hw_interrupt_disable();
-
-
/* check the scheduler is enabled or not */
-
if(rt_scheduler_lock_nest ==0)
-
{
-
rt_ubase_t highest_ready_priority;
-
-
if(rt_thread_ready_priority_group !=0)
-
{
-
/* need_insert_from_thread: need to insert from_thread to ready queue */
-
int need_insert_from_thread =0;
-
-
to_thread = _scheduler_get_highest_priority_thread(&highest_ready_priority);
-
-
if((rt_current_thread->stat & RT_THREAD_STAT_MASK)== RT_THREAD_RUNNING)
-
{
-
if(rt_current_thread->current_priority < highest_ready_priority)
-
{
-
to_thread = rt_current_thread;
-
}
-
elseif(rt_current_thread->current_priority == highest_ready_priority &&(rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK)==0)
-
{
-
to_thread = rt_current_thread;
-
}
-
else
-
{
-
need_insert_from_thread =1;
-
}
-
rt_current_thread->stat &=~RT_THREAD_STAT_YIELD_MASK;
-
}
-
-
if(to_thread != rt_current_thread)
-
{
-
/* if the destination thread is not the same as current thread */
-
rt_current_priority =(rt_uint8_t)highest_ready_priority;
-
from_thread = rt_current_thread;
-
rt_current_thread = to_thread;
-
-
RT_OBJECT_HOOK_CALL(rt_scheduler_hook,(from_thread, to_thread));
-
-
if(need_insert_from_thread)
-
{
-
rt_schedule_insert_thread(from_thread);
-
}
-
-
rt_schedule_remove_thread(to_thread);
-
to_thread->stat = RT_THREAD_RUNNING |(to_thread->stat &~RT_THREAD_STAT_MASK);
-
-
/* switch to new thread */
-
RT_DEBUG_LOG(RT_DEBUG_SCHEDULER,
-
("[%d]switch to priority#%d "
-
"thread:%.*s(sp:0x%08x), "
-
"from thread:%.*s(sp: 0x%08x) ",
-
rt_interrupt_nest, highest_ready_priority,
-
RT_NAME_MAX, to_thread->name, to_thread->sp,
-
RT_NAME_MAX, from_thread->name, from_thread->sp));
-
-
#ifdef RT_USING_OVERFLOW_CHECK
-
_rt_scheduler_stack_check(to_thread);
-
#endif/* RT_USING_OVERFLOW_CHECK */
-
-
if(rt_interrupt_nest ==0)
-
{
-
externvoid rt_thread_handle_sig(rt_bool_t clean_state);
-
-
RT_OBJECT_HOOK_CALL(rt_scheduler_switch_hook,(from_thread));
-
-
rt_hw_context_switch((rt_ubase_t)&from_thread->sp,
-
(rt_ubase_t)&to_thread->sp);
-
-
/* enable interrupt */
-
rt_hw_interrupt_enable(level);
-
-
#ifdef RT_USING_SIGNALS
-
/* check stat of thread for signal */
-
level = rt_hw_interrupt_disable();
-
if(rt_current_thread->stat & RT_THREAD_STAT_SIGNAL_PENDING)
-
{
-
externvoid rt_thread_handle_sig(rt_bool_t clean_state);
-
-
rt_current_thread->stat &=~RT_THREAD_STAT_SIGNAL_PENDING;
-
-
rt_hw_interrupt_enable(level);
-
-
/* check signal status */
-
rt_thread_handle_sig(RT_TRUE);
-
}
-
else
-
{
-
rt_hw_interrupt_enable(level);
-
}
-
#endif/* RT_USING_SIGNALS */
-
goto __exit;
-
}
-
else
-
{
-
RT_DEBUG_LOG(RT_DEBUG_SCHEDULER,("switch in interrupt "));
-
-
rt_hw_context_switch_interrupt((rt_ubase_t)&from_thread->sp,
-
(rt_ubase_t)&to_thread->sp);
-
}
-
}
-
else
-
{
-
rt_schedule_remove_thread(rt_current_thread);
-
rt_current_thread->stat = RT_THREAD_RUNNING |(rt_current_thread->stat &~RT_THREAD_STAT_MASK);
-
}
-
}
-
}
-
-
/* enable interrupt */
-
rt_hw_interrupt_enable(level);
-
-
__exit:
-
return;
-
}
得到to_thread的再判斷
之所以搞的這么復(fù)雜,是因?yàn)楫?dāng)前的調(diào)度策略是把運(yùn)行的任務(wù),移出了readylist,那么獲取的highest_ready_priority,to_thread只是紅色圈中的,還需要結(jié)合正在運(yùn)行的 thread 再次判斷,下面將結(jié)合下圖說(shuō)明上圖中的1,2,3 中情況
假設(shè) 當(dāng)前rt_thread_priority_table中存在三個(gè)優(yōu)先級(jí)列表,下標(biāo)分別為h, m, l (h
1. 當(dāng)前優(yōu)先級(jí)小于highest_ready_priority
-
if(rt_current_thread->current_priority < highest_ready_priority)
1.1 低優(yōu)先級(jí)就緒
存在 B,D,E3個(gè)任務(wù), 當(dāng)前 E 因資源阻塞或者延時(shí)中,B正在運(yùn)行;某一時(shí)刻任務(wù)E就緒(資源就緒或者超時(shí)),插入對(duì)應(yīng)readylist后發(fā)起一次調(diào)度:highest_ready_priority = l > m
對(duì)于某一任務(wù)的阻塞,圖例僅展示資源阻塞(調(diào)度),或者延時(shí)阻塞(調(diào)度)中的一種,下同,不再說(shuō)明
1.2 當(dāng)前運(yùn)行任務(wù)的時(shí)間片用完
同樣存在 B,D,E 3個(gè)任務(wù),當(dāng)前B在運(yùn)行; 某一時(shí)刻B的時(shí)間片用完,thread->stat |= RT_THREAD_STAT_YIELD,發(fā)起一次調(diào)度:highest_ready_priority = l > m因?yàn)樽罡邇?yōu)先級(jí)m下,只有B一個(gè)任務(wù),所以盡管其時(shí)間片已經(jīng)使用完,還會(huì)復(fù)位ticks,再次運(yùn)行。
這兩種情況,最后運(yùn)行的還是當(dāng)前任務(wù)
2. 當(dāng)前優(yōu)先級(jí)等于highest_ready_priority,且當(dāng)前任務(wù)時(shí)間片未用完
-
if(rt_current_thread->current_priority == highest_ready_priority &&(rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK)==0)
最后運(yùn)行的也當(dāng)前任務(wù)
3 需要切換新的任務(wù)
可以直接列出剩余的三種情況,
3.1 當(dāng)前優(yōu)先級(jí)等于highest_ready_priority,且當(dāng)前任務(wù)時(shí)間片用完
-
if(rt_current_thread->current_priority == highest_ready_priority &&(rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK)!=0)
需要禮讓,把當(dāng)前任務(wù)B插入對(duì)應(yīng)優(yōu)先級(jí)readylist后, 然后切換到C
3.2 當(dāng)前優(yōu)先級(jí)大于highest_ready_priority,且當(dāng)前任務(wù)時(shí)間片用完
-
if(rt_current_thread->current_priority > highest_ready_priority &&(rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK)!=0)
-
if(rt_current_thread->current_priority > highest_ready_priority &&(rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK)==0)
高優(yōu)先級(jí)就緒后會(huì)把當(dāng)前任務(wù)插入的readylist最后,也就是這個(gè)插入導(dǎo)致了眾多的問(wèn)題出現(xiàn)。
rt_schedule_insert_thread
-
void rt_schedule_insert_thread(struct rt_thread *thread)
-
{
-
registerrt_base_t temp;
-
-
RT_ASSERT(thread != RT_NULL);
-
-
/* disable interrupt */
-
temp = rt_hw_interrupt_disable();
-
-
/* it's current thread, it should be RUNNING thread */
-
if(thread == rt_current_thread)
-
{
-
thread->stat = RT_THREAD_RUNNING |(thread->stat &~RT_THREAD_STAT_MASK);
-
goto __exit;
-
}
-
-
/* READY thread, insert to ready queue */
-
thread->stat = RT_THREAD_READY |(thread->stat &~RT_THREAD_STAT_MASK);
-
/* insert thread to ready list */
-
rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
-
&(thread->tlist));
-
-
RT_DEBUG_LOG(RT_DEBUG_SCHEDULER,("insert thread[%.*s], the priority: %d ",
-
RT_NAME_MAX, thread->name, thread->current_priority));
-
-
/* set priority mask */
-
#if RT_THREAD_PRIORITY_MAX > 32
-
rt_thread_ready_table[thread->number]|= thread->high_mask;
-
#endif/* RT_THREAD_PRIORITY_MAX > 32 */
-
rt_thread_ready_priority_group |= thread->number_mask;
-
-
__exit:
-
/* enable interrupt */
-
rt_hw_interrupt_enable(temp);
-
}
問(wèn)題
因?yàn)楫?dāng)前運(yùn)行線程是remove出readylist的, 再插入readylist是必需的,但是使用rt_list_insert_before把未執(zhí)行完時(shí)間片的任務(wù)插入到readylist的最后面,下次輪到該優(yōu)先級(jí)時(shí),會(huì)直接執(zhí)行C,B的時(shí)間片被分成了兩次或以上來(lái)執(zhí)行,同理C也可能面臨同樣的情況。這就導(dǎo)致了很多問(wèn)題。
測(cè)試
測(cè)試環(huán)境:基于stm32f4disc1開(kāi)發(fā)板,創(chuàng)建3個(gè)線程分別控制LED3,LED4,LED5閃爍1、rt_led1_thread:優(yōu)先級(jí)9,時(shí)間片1,延時(shí) t1 = 5ms閃爍LED42、rt_led2_thread:優(yōu)先級(jí)11,時(shí)間片t2 =4(ms),自定義200延時(shí)閃爍LED53、rt_led3_thread:優(yōu)先級(jí)11,時(shí)間片t3 = 2(ms),自定義300延時(shí)閃爍LED3創(chuàng)建線程
-
int main(void)
-
{
-
rt_thread_init(&rt_led1_thread,
-
"LED1",
-
led1_thread_entry,
-
RT_NULL,
-
&rt_led1_thread_stack[0],
-
sizeof(rt_led1_thread_stack),
-
6,
-
1);
-
rt_thread_startup(&rt_led1_thread);
-
-
rt_thread_init(&rt_led2_thread,
-
"LED2",
-
led2_thread_entry,
-
RT_NULL,
-
&rt_led2_thread_stack[0],
-
sizeof(rt_led2_thread_stack),
-
11,
-
4);
-
rt_thread_startup(&rt_led2_thread);
-
-
-
rt_thread_init(&rt_led3_thread,
-
"LED3",
-
led3_thread_entry,
-
RT_NULL,
-
&rt_led3_thread_stack[0],
-
sizeof(rt_led3_thread_stack),
-
11,
-
2);
-
-
rt_thread_startup(&rt_led3_thread);
-
while(1)
-
{
-
rt_thread_mdelay(1000);
-
}
-
-
return RT_EOK;
-
}
線程入口函數(shù)
-
/* customer short delay */
-
void delay (uint32_t count)
-
{
-
for(; count!=0; count--);
-
}
-
-
void led1_thread_entry(void*p_arg )
-
{
-
for(;;)
-
{
-
HAL_GPIO_WritePin(GPIOD, LD4_Pin, GPIO_PIN_SET);
-
rt_thread_delay(5);
-
HAL_GPIO_WritePin(GPIOD, LD4_Pin, GPIO_PIN_RESET);
-
rt_thread_delay(5);
-
}
-
}
-
-
void led2_thread_entry(void*p_arg )
-
{
-
for(;;)
-
{
-
HAL_GPIO_WritePin(GPIOD, LD5_Pin, GPIO_PIN_SET);
-
delay(300);
-
HAL_GPIO_WritePin(GPIOD, LD5_Pin, GPIO_PIN_RESET);
-
delay(300);
-
}
-
}
-
-
void led3_thread_entry(void*p_arg )
-
{
-
for(;;)
-
{
-
HAL_GPIO_WritePin(GPIOD, LD3_Pin, GPIO_PIN_SET);
-
delay(300);
-
HAL_GPIO_WritePin(GPIOD, LD3_Pin, GPIO_PIN_RESET);
-
delay(300);
-
}
-
}
不同時(shí)間片對(duì)調(diào)度的影響
1)t1 = 5, t2 = 4, t3=2
新就緒的任務(wù)優(yōu)先級(jí)高于當(dāng)前任務(wù),當(dāng)前任務(wù)時(shí)間片有剩余
通過(guò)邏輯分析儀抓取三個(gè)LED pin 電平
波形中可以明顯看出thread2時(shí)間片 4ms(4 ticks) ,執(zhí)行3ms后因?yàn)楦邇?yōu)先級(jí)thread1打斷,剩余的1ms會(huì)在thread3執(zhí)行完后才執(zhí)行。thread3甚至出現(xiàn)了連續(xù)執(zhí)行的情況,稍后分析??傊畷r(shí)間片調(diào)度完全亂掉了。2)t1 = 5, t2 = 3, t3=2新就緒的任務(wù)優(yōu)先級(jí)高于當(dāng)前任務(wù),當(dāng)前任務(wù)時(shí)間片無(wú)剩余
還記得我們上面提到了3.2 不能同時(shí)滿足的條件嗎?
-
if(rt_current_thread->current_priority > highest_ready_priority &&(rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK)!=0)
這種情況造成的結(jié)果比較明顯,導(dǎo)致thread3一直沒(méi)有運(yùn)行的機(jī)會(huì)了,也就是小伙伴發(fā)現(xiàn)的issuehttps://github.com/RT-Thread/rt-thread/issues/6092從現(xiàn)象上看情況3是最極端,最嚴(yán)重的,但是你可以立即發(fā)現(xiàn)。不像情況1,2雖然表面上每個(gè)thread還在執(zhí)行,內(nèi)部的時(shí)間片已經(jīng)完全亂掉,往往這種隱形的issue會(huì)導(dǎo)致更加嚴(yán)重的后果。
解決辦法
既然看到了時(shí)間片調(diào)度的眾多issue,也知道了問(wèn)題的原因:高優(yōu)先級(jí)打斷未執(zhí)行完時(shí)間片的任務(wù)導(dǎo)致該任務(wù)被重新插入到其優(yōu)先級(jí)readylist末尾那么就開(kāi)始著手解決。方案一
先看下小伙伴同時(shí)提出的解決辦法:https://github.com/RT-Thread/rt-thread/pull/6095/files他增加了一個(gè)RT_THREAD_STAT_SCHEDULING 狀態(tài)來(lái)判斷和避免issue
這種做法應(yīng)該沒(méi)啥問(wèn)題,暫未測(cè)試
方案二
直擊問(wèn)題本質(zhì),既然是插入的問(wèn)題導(dǎo)致的,調(diào)整一下插入順序即可
除了時(shí)間片使用完,需要yield,插入其readylist的末尾,其他情況均插入readylist的頭部
再次測(cè)試t1 = 5, t2 = 5, t3=2,結(jié)果如下:
可以看到,ticks連續(xù)執(zhí)行了,線程沒(méi)有重復(fù)執(zhí)行,沒(méi)有跳過(guò),也沒(méi)有不被執(zhí)行的,完美解決。
方案三
更近一步,可不可以不把運(yùn)行的thread移除readylist呢?如果可以,沒(méi)有remove,也就沒(méi)有了insert,沒(méi)有了issue
其實(shí)FreeRTOS使用的就是這種方案:
taskSELECT_HIGHEST_PRIORITY_TASK()
-
#define taskSELECT_HIGHEST_PRIORITY_TASK()
-
{
-
UBaseType_t uxTopPriority;
-
-
/* Find the highest priority list that contains ready tasks. */
-
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );
-
configASSERT( listCURRENT_LIST_LENGTH(&( pxReadyTasksLists[ uxTopPriority ]))>0);
-
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB,&( pxReadyTasksLists[ uxTopPriority ]));
-
}/* taskSELECT_HIGHEST_PRIORITY_TASK() */
listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )
-
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )
-
{
-
List_t*const pxConstList =( pxList );
-
/* Increment the index to the next item and return the item, ensuring */
-
/* we don't return the marker used at the end of the list. */
-
( pxConstList )->pxIndex =( pxConstList )->pxIndex->pxNext;
-
if((void*)( pxConstList )->pxIndex ==(void*)&(( pxConstList )->xListEnd ))
-
{
-
( pxConstList )->pxIndex =( pxConstList )->pxIndex->pxNext;
-
}
-
( pxTCB )=( pxConstList )->pxIndex->pvOwner;
-
}
https://github.com/RT-Thread/rt-thread/pull/5954
就是基于該方案。rt_list_jump_next
雖然rt_list_t也是一個(gè)雙向鏈表,但是少了一個(gè)成員變量index,不能像FreeRTOS那樣直接移動(dòng)完成時(shí)間片的調(diào)度首先我們需要新增一個(gè)rt_list_t操作函數(shù)rt_list_jump_next,完成rt_list_t頭部往后移動(dòng)一次,同時(shí)要保證list成員相對(duì)順序不變-
/**
-
-
* @brief move the list to its next's next position
-
*
-
* @param l list to insert it
-
*/
-
rt_inline void rt_list_jump_next(rt_list_t*l)
-
{
-
l->next->prev = l->prev;
-
l->prev->next= l->next;
-
-
-
l->prev = l->next;
-
-
l->next->next->prev = l;
-
l->next= l->next->next;
-
-
l->prev->next= l;
-
-
}
大致操作如下:
這種直接移動(dòng)list head的做法,一次調(diào)度會(huì)有6次指針賦值操作,
而原來(lái)的一次調(diào)度remove(4次), insert(4次)加起來(lái)是8次指針賦值操作
重定義_scheduler_get_highest_priority_thread
-
--- a/src/scheduler.c
-
+++ b/src/scheduler.c
-
@@-180,6+180,19@@staticstruct rt_thread* _scheduler_get_highest_priority_thread(rt_ubase_t*high
-
highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group)-1;
-
#endif/* RT_THREAD_PRIORITY_MAX > 32 */
-
-
+/* if current thread is yield , move the head of priority list to next and change its status to READY */
-
+if((rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK)!=0)
-
+{
-
+if(rt_current_thread->tlist.next!= rt_current_thread->tlist.prev)
-
+{
-
+/* multiple threads, move the list head to next */
-
+ rt_list_jump_next(&rt_thread_priority_table[rt_current_thread->current_priority]);
-
+}
-
+
-
+/* clear YIELD and ready thread*/
-
+ rt_current_thread->stat = RT_THREAD_READY |(rt_current_thread->stat &~(RT_THREAD_STAT_YIELD_MASK|RT_THREAD_STAT_MASK));
-
+}
-
+
-
/* get highest ready priority thread */
-
highest_priority_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,
-
struct rt_thread,
簡(jiǎn)化rt_schedule
上面的分析可知,rt_schedule之所以搞的復(fù)雜,是因?yàn)楂@取的highest_ready_priority,to_thread不包含對(duì)當(dāng)前正在運(yùn)行thread的計(jì)算。現(xiàn)在我們不把rt_current_thread 移除其readylist,獲得的highest_ready_priority,to_thread就是最終的-
@@-258,7+271,6@@void rt_system_scheduler_start(void)
-
rt_current_thread = to_thread;
-
#endif/* RT_USING_SMP */
-
-
- rt_schedule_remove_thread(to_thread);
-
to_thread->stat = RT_THREAD_RUNNING;
-
-
/* switch to new thread */
-
@@-436,28+448,8@@void rt_schedule(void)
-
-
if(rt_thread_ready_priority_group !=0)
-
{
-
-/* need_insert_from_thread: need to insert from_thread to ready queue */
-
-int need_insert_from_thread =0;
-
-
-
to_thread = _scheduler_get_highest_priority_thread(&highest_ready_priority);
-
-
-if((rt_current_thread->stat & RT_THREAD_STAT_MASK)== RT_THREAD_RUNNING)
-
-{
-
-if(rt_current_thread->current_priority < highest_ready_priority)
-
-{
-
- to_thread = rt_current_thread;
-
-}
-
-elseif(rt_current_thread->current_priority == highest_ready_priority &&(rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK)==0)
-
-{
-
- to_thread = rt_current_thread;
-
-}
-
-else
-
-{
-
- need_insert_from_thread =1;
-
-}
-
- rt_current_thread->stat &=~RT_THREAD_STAT_YIELD_MASK;
-
-}
-
-
-
if(to_thread != rt_current_thread)
-
{
-
/* if the destination thread is not the same as current thread */
-
@@-467,12+459,6@@void rt_schedule(void)
-
-
RT_OBJECT_HOOK_CALL(rt_scheduler_hook,(from_thread, to_thread));
-
-
-if(need_insert_from_thread)
-
-{
-
- rt_schedule_insert_thread(from_thread);
-
-}
-
-
-
- rt_schedule_remove_thread(to_thread);
-
to_thread->stat = RT_THREAD_RUNNING |(to_thread->stat &~RT_THREAD_STAT_MASK);
-
-
/* switch to new thread */
-
@@-531,7+517,6@@void rt_schedule(void)
-
}
-
else
-
{
-
- rt_schedule_remove_thread(rt_current_thread);
-
rt_current_thread->stat = RT_THREAD_RUNNING |(rt_current_thread->stat &~RT_THREAD_STAT_MASK);
-
}
-
}
-
(END)
rt_system_scheduler_start
-
@@-258,7+271,6@@void rt_system_scheduler_start(void)
-
rt_current_thread = to_thread;
-
#endif/* RT_USING_SMP */
-
-
- rt_schedule_remove_thread(to_thread);
-
to_thread->stat = RT_THREAD_RUNNING;
-
-
/* switch to new thread */
同樣測(cè)試t1 = 5, t2 = 5, t3=2,結(jié)果正常如下:
審核編輯:湯梓紅
-
源碼
+關(guān)注
關(guān)注
8文章
626瀏覽量
28966 -
調(diào)度算法
+關(guān)注
關(guān)注
1文章
68瀏覽量
11954 -
ISSUE
+關(guān)注
關(guān)注
1文章
5瀏覽量
8081
原文標(biāo)題:關(guān)于時(shí)間片調(diào)度算法issue的分析與解決
文章出處:【微信號(hào):RTThread,微信公眾號(hào):RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論