thread 切换的判断

lk是按照时间片来运行thread,每个thread 默认运行5个时钟中断,
如果时间到了就在timer的中断中做thread 切换。下来我们看看具体的code
当我们通过thread_resume来让thread 运行时.会调用thread_yiled
void thread_yield(void)
{
enter_critical_section();


/* we are yielding the cpu, so stick ourselves into the tail of the run queue and reschedule */
current_thread->state = THREAD_READY;
current_thread->remaining_quantum = 0;
insert_in_run_queue_tail(current_thread);
thread_resched();


exit_critical_section();
}
这个函数会将current_thread->remaining_quantum = 0;而remaining_quantum
就是表示thread 可以运行的timer 中断的个数
继续看thread_resched
void thread_resched(void)
{
thread_t *oldthread;
thread_t *newthread;


/* set up quantum for the new thread if it was consumed */
if (newthread->remaining_quantum <= 0) {
newthread->remaining_quantum = 5; // XXX make this smarter
}


}
这个函数会将新thread的remaining_quantum 设定为5,也就是运行5个time 中断,如果一个timer中断是10ms的
话,每个thread 就默认运行50ms
明白这点后我们看看怎么在时钟中断中切换thread


在arm_irq中断中会根据中断的返回值来决定是否进行thread切换
FUNCTION(arm_irq)
/* XXX only deals with interrupting supervisor mode */




/* call into higher level code */
mov r0, sp /* iframe */
bl platform_irq


/* reschedule if the handler returns nonzero */
cmp     r0, #0
blne    thread_preempt

先看看platform_irq的实现
enum handler_return platform_irq(struct arm_iframe *frame)
{
ret = handler[num].func(handler[num].arg);
return ret;
}
会根据中断号,调用对应的函数
而handler中的func是通过register_int_handler来注册的.
void register_int_handler(unsigned int vector, int_handler func, void *arg)
{
if (vector >= NR_IRQS)
return;


enter_critical_section();
handler[vector].func = func;
handler[vector].arg = arg;
exit_critical_section();
}
看下面的函数handler是platform_tick,对应的timer中断号是INT_PIT
void platform_init_timer(void)
{
register_int_handler(INT_PIT, &platform_tick, NULL);
}
继续看platform_tick的实现
static enum handler_return platform_tick(void *arg)
{
*REG(PIT_CLEAR_INT) = 1;
if (t_callback) {
return t_callback(arg, current_time());
} else {
return INT_NO_RESCHEDULE;
}
}
调用t_callback,通过下面的函数设定t_callback
status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
{
enter_critical_section();


t_callback = callback;


return NO_ERROR;
}
所以t_callback == timer_tick
void timer_init(void)
{
list_initialize(&timer_queue);


/* register for a periodic timer tick */
platform_set_periodic_timer(timer_tick, NULL, 10); /* 10ms */
}
timer_tick 中继续call thread_timer_tick 来决定是否要进行thread 切换
static enum handler_return timer_tick(void *arg, time_t now)
{
timer_t *timer;
enum handler_return ret = INT_NO_RESCHEDULE;


#if THREAD_STATS
thread_stats.timer_ints++;
#endif


for (;;) {
/* let the scheduler have a shot to do quantum expiration, etc */
if (thread_timer_tick() == INT_RESCHEDULE)
ret = INT_RESCHEDULE;


return INT_RESCHEDULE;
}
而在thread_timer_tick 就是简单的判定当前thread的时间片是否用完,如果用完就切换
enum handler_return thread_timer_tick(void)
{
if (current_thread == idle_thread)
return INT_NO_RESCHEDULE;


current_thread->remaining_quantum--;
if (current_thread->remaining_quantum <= 0)
return INT_RESCHEDULE;
else
return INT_NO_RESCHEDULE;
}


如果返回INT_RESCHEDULE 也就是不等于0 ,也就是要切换thread,则在arm_irq中继续调用thread_preempt 进行thread 切换
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值