History

sched/deadline: Make DL capacity-aware

The current SCHED_DEADLINE (DL) scheduler uses a global EDF scheduling algorithm w/o considering CPU capacity or task utilization. This works well on homogeneous systems where DL tasks are guaranteed to have a bounded tardiness but presents issues on heterogeneous systems. A DL task can migrate to a CPU which does not have enough CPU capacity to correctly serve the task (e.g. a task w/ 70ms runtime and 100ms period on a CPU w/ 512 capacity). Add the DL fitness function dl_task_fits_capacity() for DL admission control on heterogeneous systems. A task fits onto a CPU if: CPU original capacity / 1024 >= task runtime / task deadline Use this function on heterogeneous systems to try to find a CPU which meets this criterion during task wakeup, push and offline migration. On homogeneous systems the original behavior of the DL admission control should be retained.

Luca Abeni committed 6 years ago

Commit b4118981 parent 60ffd5e3 files · +42 −5Browse files

Showing the changes to kernel (3 of 3 files). Show all

Unified · Split

3 files
  1. kernel/sched/cpudeadline.c +13 −1
  2. kernel/sched/deadline.c +14 −4
  3. kernel/sched/sched.h +15 −0
kernel/sched/cpudeadline.c+13−1
@@ -121,7 +121,19 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p, · 120 unmodified lines
121 121
122 if (later_mask &&122 if (later_mask &&
123 cpumask_and(later_mask, cp->free_cpus, p->cpus_ptr)) {123 cpumask_and(later_mask, cp->free_cpus, p->cpus_ptr)) {
124 return 1;124 int cpu;
125
126 if (!static_branch_unlikely(&sched_asym_cpucapacity))
127 return 1;
128
129 /* Ensure the capacity of the CPUs fits the task. */
130 for_each_cpu(cpu, later_mask) {
131 if (!dl_task_fits_capacity(p, cpu))
132 cpumask_clear_cpu(cpu, later_mask);
133 }
134
135 if (!cpumask_empty(later_mask))
136 return 1;
125 } else {137 } else {
126 int best_cpu = cpudl_maximum(cp);138 int best_cpu = cpudl_maximum(cp);
127 139
kernel/sched/deadline.c+14−4
@@ -1643,6 +1643,7 @@ static int · 1642 unmodified lines
1643select_task_rq_dl(struct task_struct *p, int cpu, int sd_flag, int flags)1643select_task_rq_dl(struct task_struct *p, int cpu, int sd_flag, int flags)
1644{1644{
1645 struct task_struct *curr;1645 struct task_struct *curr;
1646 bool select_rq;
1646 struct rq *rq;1647 struct rq *rq;
1647 1648
1648 if (sd_flag != SD_BALANCE_WAKE)1649 if (sd_flag != SD_BALANCE_WAKE)
@@ -1662,10 +1663,19 @@ select_task_rq_dl(struct task_struct *p, int cpu, int sd_flag, int flags) · 13 unmodified lines
1662 * other hand, if it has a shorter deadline, we1663 * other hand, if it has a shorter deadline, we
1663 * try to make it stay here, it might be important.1664 * try to make it stay here, it might be important.
1664 */1665 */
1665 if (unlikely(dl_task(curr)) &&1666 select_rq = unlikely(dl_task(curr)) &&
1666 (curr->nr_cpus_allowed < 2 ||1667 (curr->nr_cpus_allowed < 2 ||
1667 !dl_entity_preempt(&p->dl, &curr->dl)) &&1668 !dl_entity_preempt(&p->dl, &curr->dl)) &&
1668 (p->nr_cpus_allowed > 1)) {1669 p->nr_cpus_allowed > 1;
1670
1671 /*
1672 * Take the capacity of the CPU into account to
1673 * ensure it fits the requirement of the task.
1674 */
1675 if (static_branch_unlikely(&sched_asym_cpucapacity))
1676 select_rq |= !dl_task_fits_capacity(p, cpu);
1677
1678 if (select_rq) {
1669 int target = find_later_rq(p);1679 int target = find_later_rq(p);
1670 1680
1671 if (target != -1 &&1681 if (target != -1 &&
kernel/sched/sched.h+15−0
@@ -317,6 +317,21 @@ static inline bool __dl_overflow(struct dl_bw *dl_b, unsigned long cap, · 316 unmodified lines
317 cap_scale(dl_b->bw, cap) < dl_b->total_bw - old_bw + new_bw;317 cap_scale(dl_b->bw, cap) < dl_b->total_bw - old_bw + new_bw;
318}318}
319 319
320/*
321 * Verify the fitness of task @p to run on @cpu taking into account the
322 * CPU original capacity and the runtime/deadline ratio of the task.
323 *
324 * The function will return true if the CPU original capacity of the
325 * @cpu scaled by SCHED_CAPACITY_SCALE >= runtime/deadline ratio of the
326 * task and false otherwise.
327 */
328static inline bool dl_task_fits_capacity(struct task_struct *p, int cpu)
329{
330 unsigned long cap = arch_scale_cpu_capacity(cpu);
331
332 return cap_scale(p->dl.dl_deadline, cap) >= p->dl.dl_runtime;
333}
334
320extern void init_dl_bw(struct dl_bw *dl_b);335extern void init_dl_bw(struct dl_bw *dl_b);
321extern int sched_dl_global_validate(void);336extern int sched_dl_global_validate(void);
322extern void sched_dl_do_global(void);337extern void sched_dl_do_global(void);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t