上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拉过来。