更新时间片 -- scheduler_tick()

时钟中断处理程序中会调用函数scheduler_tick():
    函数scheduler_tick()更新当前进程的time_slice;并根据time_slice的使用情况(剩余还是耗尽),来做进一步处理.scheduler_tick( ) Keeps the time_slice counter of current up-to-date


void scheduler_tick(void)
{
    int cpu = smp_processor_id();
    runqueue_t *rq = this_rq();
    task_t *p = current;
    unsigned long long now = sched_clock();
    update_cpu_clock(p, rq, now);

更新运行队列的最新时钟中断时间戳为当前时间
|----------------------------------|
|   rq->timestamp_last_tick = now; |
|----------------------------------|

如果当前进程为本地CPU的swapper进程
|-------------------------------------------|
|   if (p == rq->idle) {                    |
|       if (wake_priority_sleeper(rq))      |
|           goto out;                       |
|       rebalance_tick(cpu, rq, SCHED_IDLE);|
|       return;                             |
|   }                                       |
|-------------------------------------------|

如果当前进程不是活跃(active)进程
|---------------------------------|
|   if (p->array != rq->active) { |
|       set_tsk_need_resched(p);  |
|       goto out;                 |
|   }                             |
|---------------------------------|

    spin_lock(&rq->lock);

如果当前进程是实时进程;如果调度策略为SCHED_RR,并且其时间片已经耗尽;为该进程重新计算时间片;清除first_time_slice域;设置task_struct.thread_info.flags域;将该任务插入其所在活跃队列的尾部.
|----------------------------------------------------------|
|   if (rt_task(p)) {                                      |
|       if ((p->policy == SCHED_RR) && !--p->time_slice) { |
|           p->time_slice = task_timeslice(p);             |
|           p->first_time_slice = 0;                       |
|           set_tsk_need_resched(p);                       |
|           requeue_task(p, rq->active);                   |
|       }                                                  |
|       goto out_unlock;                                   |
|   }                                                      |
|----------------------------------------------------------|


当前进程为普通进程,如果其时间片已经耗尽;将该进程从活跃队列中删除;设置task_struct.thread_info.flags域;重新计算动态优先级prio;重新计算时间片;清除first_time_slice域;如果过期队列为空,将更新 runqueue.expired_timestamp;Inserts the current process either in the active set or in the expired set
|------------------------------------------------------------|
|   if (!--p->time_slice) {                                  |
|       dequeue_task(p, rq->active);                         |
|       set_tsk_need_resched(p);                             |
|       p->prio = effective_prio(p);                         |
|       p->time_slice = task_timeslice(p);                   |
|       p->first_time_slice = 0;                             |
|                                                            |
|       if (!rq->expired_timestamp)                          |
|           rq->expired_timestamp = jiffies;                 |
|       if (!TASK_INTERACTIVE(p) || EXPIRED_STARVING(rq)) {  |
|           enqueue_task(p, rq->expired);                    |
|           if (p->static_prio < rq->best_expired_prio)      |
|               rq->best_expired_prio = p->static_prio;      |
|       } else                                               |
|           enqueue_task(p, rq->active);                     |
|------------------------------------------------------------|

如果时间片没有耗尽,并且剩余时间片过长;则将该进程插入其所在队列的尾部;并设置task_struct.thread_info.flags域
if the time quantum is not exhausted (current->time_slice is not zero), checks whether the remaining time slice of the current process is too long.
|-----------------------------------------------------------------------------|
|   } else {                                                                  |
|       if ( TASK_INTERACTIVE(p) &&                                           |
|         !((task_timeslice(p) - p->time_slice) % TIMESLICE_GRANULARITY(p)) &&|
|         (p->time_slice >= TIMESLICE_GRANULARITY(p)) &&                      |
|         (p->array == rq->active)) {                                         |
|           requeue_task(p, rq->active);                                      |
|                                                                             |
|           set_tsk_need_resched(p);                                          |
|       }                                                                     |
|   }                                                                         |
|-----------------------------------------------------------------------------|
out_unlock:
    spin_unlock(&rq->lock);
out:
    rebalance_tick(cpu, rq, NOT_IDLE);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章