Linux内核深度解析
上QQ阅读APP看书,第一时间看更新

2.9.3 限期调度类的处理器负载均衡

限期调度类的处理器负载均衡比较简单,如图2.40所示。调度器选择下一个限期进程的时候,如果当前正在执行的进程是限期进程,将会试图从限期进程超载的处理器把限期进程拉过来。

图2.40 限期调度类的处理器负载均衡

限期进程超载的定义如下。

(1)限期运行队列至少有两个限期进程。

(2)至少有一个限期进程绑定到多个处理器。


函数pull_dl_task负责从限期进程超载的处理器把限期进程拉过来,其代码如下:

    kernel/sched/deadline.c
    1   static void pull_dl_task(struct rq *this_rq)
    2   {
    3    int this_cpu = this_rq->cpu, cpu;
    4    struct task_struct *p;
    5    bool resched = false;
    6    struct rq *src_rq;
    7    u64 dmin = LONG_MAX;
    8
    9    if (likely(! dl_overloaded(this_rq)))
    10        return;
    11
    12   for_each_cpu(cpu, this_rq->rd->dlo_mask) {
    13        if (this_cpu == cpu)
    14              continue;
    15
    16        src_rq = cpu_rq(cpu);
    17
    18        if (this_rq->dl.dl_nr_running &&
    19            dl_time_before(this_rq->dl.earliest_dl.curr,
    20                     src_rq->dl.earliest_dl.next))
    21              continue;
    22
    23        double_lock_balance(this_rq, src_rq);
    24
    25        if (src_rq->dl.dl_nr_running <= 1)
    26              goto skip;
    27
    28        p = pick_earliest_pushable_dl_task(src_rq, this_cpu);
    29
    30        if (p && dl_time_before(p->dl.deadline, dmin) &&
    31            (! this_rq->dl.dl_nr_running ||
    32             dl_time_before(p->dl.deadline,
    33                      this_rq->dl.earliest_dl.curr))) {
    34              if (dl_time_before(p->dl.deadline,
    35                           src_rq->curr->dl.deadline))
    36                   goto skip;
    37
    38              resched = true;
    39
    40              deactivate_task(src_rq, p, 0);
    41              set_task_cpu(p, this_cpu);
    42              activate_task(this_rq, p, 0);
    43              dmin = p->dl.deadline;
    44        }
    45   skip:
    46        double_unlock_balance(this_rq, src_rq);
    47   }
    48
    49   if (resched)
    50        resched_curr(this_rq);
    51   }

第9行代码,如果不存在限期进程超载的处理器,那么不需要处理。

第12行代码,针对每个限期进程超载的处理器t,处理如下。

1)第18~21行代码,如果当前处理器正在执行的限期进程的绝对期限小于处理器t的下一个限期进程的绝对期限,那么不需要拉限期进程过来。

2)第25行和第26行代码,如果处理器t上限期进程的数量小于2,那么不需要拉限期进程过来。

3)第28行代码,在处理器t上选择一个绝对期限最小、处于就绪状态并且绑定的处理器集合包含当前处理器的限期进程。

4)第30~33行代码,如果目标进程的绝对期限小于上一个拉过来的限期进程的绝对期限,并且小于当前处理器正在执行的限期进程的绝对期限,那么处理如下。

❑ 第34~36行代码,如果目标进程的绝对期限小于处理器t正在执行的限期进程的绝对期限,那么不要把目标进程拉过来。

❑ 第40~42行代码,当前处理器把目标进程从处理器t拉过来。