summaryrefslogtreecommitdiffstats
path: root/meta-eas/recipes-kernel/linux/linux-renesas/0060-sched-fair-Energy-aware-wake-up-task-placement.patch
blob: d85d6fe643e2be07971aa6bb07f1e8a8f3d2883f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
From b0ba3376b094bcf111551ee7c5e14183fe15da79 Mon Sep 17 00:00:00 2001
From: Morten Rasmussen <morten.rasmussen@arm.com>
Date: Wed, 30 Mar 2016 14:29:48 +0100
Subject: [PATCH 60/92] sched/fair: Energy-aware wake-up task placement

When the systems is not overutilized, place waking tasks on the most
energy efficient cpu. Previous attempts reduced the search space by
matching task utilization to cpu capacity before consulting the energy
model as this is an expensive operation. The search heuristics didn't
work very well and lacking any better alternatives this patch takes the
brute-force route and tries all potential targets.

This approach doesn't scale, but it might be sufficient for many
embedded applications while work is continuing on a heuristic that can
minimize the necessary computations. The heuristic must be derrived from
the platform energy model rather than make additional assumptions, such
lower capacity implies better energy efficiency. PeterZ mentioned in the
past that we might be able to derrive some simpler deciding functions
using mathematical (modal?) analysis.

Signed-off-by: Morten Rasmussen <morten.rasmussen@arm.com>
(cherry picked from commit 8491fd68555c31e596e1888912796184d42138cc)
Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
---
 kernel/sched/fair.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index db732bd..58b468c 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6148,6 +6148,59 @@ static bool cpu_overutilized(int cpu)
 	return (capacity_of(cpu) * 1024) < (cpu_util(cpu) * capacity_margin);
 }
 
+static int select_energy_cpu_brute(struct task_struct *p, int prev_cpu)
+{
+	int i;
+	int min_diff = 0, energy_cpu = prev_cpu, spare_cpu = prev_cpu;
+	unsigned long max_spare = 0;
+	struct sched_domain *sd;
+
+	rcu_read_lock();
+
+	sd = rcu_dereference(per_cpu(sd_ea, prev_cpu));
+
+	if (!sd)
+		return prev_cpu;
+
+	for_each_cpu_and(i, tsk_cpus_allowed(p), sched_domain_span(sd)) {
+		int diff;
+		unsigned long spare;
+
+		struct energy_env eenv = {
+			.util_delta	= task_util(p),
+			.src_cpu	= prev_cpu,
+			.dst_cpu	= i,
+		};
+
+		spare = capacity_spare_wake(i, p);
+
+		if (i == prev_cpu)
+			continue;
+
+		if (spare > max_spare) {
+			max_spare = spare;
+			spare_cpu = i;
+		}
+
+		if (spare * 1024 < capacity_margin * task_util(p))
+			continue;
+
+		diff = energy_diff(&eenv);
+
+		if (diff < min_diff) {
+			min_diff = diff;
+			energy_cpu = i;
+		}
+	}
+
+	rcu_read_unlock();
+
+	if (energy_cpu == prev_cpu && !cpu_overutilized(prev_cpu))
+		return prev_cpu;
+
+	return energy_cpu != prev_cpu ? energy_cpu : spare_cpu;
+}
+
 /*
  * select_task_rq_fair: Select target runqueue for the waking task in domains
  * that have the 'sd_flag' flag set. In practice, this is SD_BALANCE_WAKE,
@@ -6175,6 +6228,9 @@ static bool cpu_overutilized(int cpu)
 			      && cpumask_test_cpu(cpu, tsk_cpus_allowed(p));
 	}
 
+	if (energy_aware() && !(cpu_rq(prev_cpu)->rd->overutilized))
+		return select_energy_cpu_brute(p, prev_cpu);
+
 	rcu_read_lock();
 	for_each_domain(cpu, tmp) {
 		if (!(tmp->flags & SD_LOAD_BALANCE))
-- 
1.9.1