提交 2a3bb3c0 编写于 作者: T tanghui 提交者: Zhong Jinghua

sched: Adjust wakeup cpu range according CPU util dynamicly

hulk inclusion
category: feature
bugzilla: 186575, https://gitee.com/openeuler/kernel/issues/I526XC

--------------------------------

Compare taskgroup 'util_avg' in perferred cpu with capacity preferred cpu,
dynamicly adjust cpu range for task wakeup process.
Signed-off-by: Ntanghui <tanghui20@huawei.com>
Signed-off-by: NZheng Zucheng <zhengzucheng@huawei.com>
Reviewed-by: NZhang Qiao <zhangqiao22@huawei.com>
上级 ebeb84ad
...@@ -1424,10 +1424,11 @@ struct task_struct { ...@@ -1424,10 +1424,11 @@ struct task_struct {
KABI_USE(7, void *pf_io_worker) KABI_USE(7, void *pf_io_worker)
#if defined(CONFIG_QOS_SCHED_DYNAMIC_AFFINITY) && !defined(__GENKSYMS__) #if defined(CONFIG_QOS_SCHED_DYNAMIC_AFFINITY) && !defined(__GENKSYMS__)
KABI_USE(8, cpumask_t *prefer_cpus) KABI_USE(8, cpumask_t *prefer_cpus)
KABI_USE(9, const cpumask_t *select_cpus)
#else #else
KABI_RESERVE(8) KABI_RESERVE(8)
#endif
KABI_RESERVE(9) KABI_RESERVE(9)
#endif
KABI_RESERVE(10) KABI_RESERVE(10)
KABI_RESERVE(11) KABI_RESERVE(11)
KABI_RESERVE(12) KABI_RESERVE(12)
......
...@@ -31,6 +31,10 @@ extern unsigned int sysctl_sched_min_granularity; ...@@ -31,6 +31,10 @@ extern unsigned int sysctl_sched_min_granularity;
extern unsigned int sysctl_sched_wakeup_granularity; extern unsigned int sysctl_sched_wakeup_granularity;
extern unsigned int sysctl_sched_child_runs_first; extern unsigned int sysctl_sched_child_runs_first;
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
extern int sysctl_sched_util_low_pct;
#endif
enum sched_tunable_scaling { enum sched_tunable_scaling {
SCHED_TUNABLESCALING_NONE, SCHED_TUNABLESCALING_NONE,
SCHED_TUNABLESCALING_LOG, SCHED_TUNABLESCALING_LOG,
......
...@@ -6092,7 +6092,11 @@ find_idlest_group_cpu(struct sched_group *group, struct task_struct *p, int this ...@@ -6092,7 +6092,11 @@ find_idlest_group_cpu(struct sched_group *group, struct task_struct *p, int this
return cpumask_first(sched_group_span(group)); return cpumask_first(sched_group_span(group));
/* Traverse only the allowed CPUs */ /* Traverse only the allowed CPUs */
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
for_each_cpu_and(i, sched_group_span(group), p->select_cpus) {
#else
for_each_cpu_and(i, sched_group_span(group), p->cpus_ptr) { for_each_cpu_and(i, sched_group_span(group), p->cpus_ptr) {
#endif
struct rq *rq = cpu_rq(i); struct rq *rq = cpu_rq(i);
if (!sched_core_cookie_match(rq, p)) if (!sched_core_cookie_match(rq, p))
...@@ -6139,7 +6143,11 @@ static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p ...@@ -6139,7 +6143,11 @@ static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p
{ {
int new_cpu = cpu; int new_cpu = cpu;
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
if (!cpumask_intersects(sched_domain_span(sd), p->select_cpus))
#else
if (!cpumask_intersects(sched_domain_span(sd), p->cpus_ptr)) if (!cpumask_intersects(sched_domain_span(sd), p->cpus_ptr))
#endif
return prev_cpu; return prev_cpu;
/* /*
...@@ -6266,7 +6274,11 @@ static int select_idle_core(struct task_struct *p, int core, struct cpumask *cpu ...@@ -6266,7 +6274,11 @@ static int select_idle_core(struct task_struct *p, int core, struct cpumask *cpu
if (!available_idle_cpu(cpu)) { if (!available_idle_cpu(cpu)) {
idle = false; idle = false;
if (*idle_cpu == -1) { if (*idle_cpu == -1) {
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
if (sched_idle_cpu(cpu) && cpumask_test_cpu(cpu, p->select_cpus)) {
#else
if (sched_idle_cpu(cpu) && cpumask_test_cpu(cpu, p->cpus_ptr)) { if (sched_idle_cpu(cpu) && cpumask_test_cpu(cpu, p->cpus_ptr)) {
#endif
*idle_cpu = cpu; *idle_cpu = cpu;
break; break;
} }
...@@ -6322,7 +6334,11 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int t ...@@ -6322,7 +6334,11 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int t
if (!this_sd) if (!this_sd)
return -1; return -1;
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
cpumask_and(cpus, sched_domain_span(sd), p->select_cpus);
#else
cpumask_and(cpus, sched_domain_span(sd), p->cpus_ptr); cpumask_and(cpus, sched_domain_span(sd), p->cpus_ptr);
#endif
if (sched_feat(SIS_PROP) && !smt) { if (sched_feat(SIS_PROP) && !smt) {
u64 avg_cost, avg_idle, span_avg; u64 avg_cost, avg_idle, span_avg;
...@@ -6460,6 +6476,9 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) ...@@ -6460,6 +6476,9 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
lockdep_assert_irqs_disabled(); lockdep_assert_irqs_disabled();
if ((available_idle_cpu(target) || sched_idle_cpu(target)) && if ((available_idle_cpu(target) || sched_idle_cpu(target)) &&
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
cpumask_test_cpu(target, p->select_cpus) &&
#endif
asym_fits_capacity(task_util, target)) { asym_fits_capacity(task_util, target)) {
SET_STAT(found_idle_cpu_easy); SET_STAT(found_idle_cpu_easy);
return target; return target;
...@@ -6470,6 +6489,9 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) ...@@ -6470,6 +6489,9 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
*/ */
if (prev != target && cpus_share_cache(prev, target) && if (prev != target && cpus_share_cache(prev, target) &&
(available_idle_cpu(prev) || sched_idle_cpu(prev)) && (available_idle_cpu(prev) || sched_idle_cpu(prev)) &&
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
cpumask_test_cpu(prev, p->select_cpus) &&
#endif
asym_fits_capacity(task_util, prev)) { asym_fits_capacity(task_util, prev)) {
SET_STAT(found_idle_cpu_easy); SET_STAT(found_idle_cpu_easy);
return prev; return prev;
...@@ -6498,7 +6520,11 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) ...@@ -6498,7 +6520,11 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
recent_used_cpu != target && recent_used_cpu != target &&
cpus_share_cache(recent_used_cpu, target) && cpus_share_cache(recent_used_cpu, target) &&
(available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) && (available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) &&
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
cpumask_test_cpu(p->recent_used_cpu, p->select_cpus) &&
#else
cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr) && cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr) &&
#endif
asym_fits_capacity(task_util, recent_used_cpu)) { asym_fits_capacity(task_util, recent_used_cpu)) {
/* /*
* Replace recent_used_cpu with prev as it is a potential * Replace recent_used_cpu with prev as it is a potential
...@@ -6921,6 +6947,82 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) ...@@ -6921,6 +6947,82 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
return -1; return -1;
} }
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
/*
* Low utilization threshold for CPU
*
* (default: 85%), units: percentage of CPU utilization)
*/
int sysctl_sched_util_low_pct = 85;
static inline bool prefer_cpus_valid(struct task_struct *p)
{
return p->prefer_cpus &&
!cpumask_empty(p->prefer_cpus) &&
!cpumask_equal(p->prefer_cpus, p->cpus_ptr) &&
cpumask_subset(p->prefer_cpus, p->cpus_ptr);
}
/*
* set_task_select_cpus: select the cpu range for task
* @p: the task whose available cpu range will to set
* @idlest_cpu: the cpu which is the idlest in prefer cpus
*
* If sum of 'util_avg' among 'preferred_cpus' lower than the percentage
* 'sysctl_sched_util_low_pct' of 'preferred_cpus' capacity, select
* 'preferred_cpus' range for task, otherwise select 'preferred_cpus' for task.
*
* The available cpu range set to p->select_cpus. Idlest cpu in preferred cpus
* set to @idlest_cpu, which is set to wakeup cpu when fast path wakeup cpu
* without p->select_cpus.
*/
static void set_task_select_cpus(struct task_struct *p, int *idlest_cpu,
int sd_flag)
{
unsigned long util_avg_sum = 0;
unsigned long tg_capacity = 0;
long min_util = INT_MIN;
struct task_group *tg;
long spare;
int cpu;
p->select_cpus = p->cpus_ptr;
if (!prefer_cpus_valid(p))
return;
rcu_read_lock();
tg = task_group(p);
for_each_cpu(cpu, p->prefer_cpus) {
if (unlikely(!tg->se[cpu]))
continue;
if (idlest_cpu && available_idle_cpu(cpu)) {
*idlest_cpu = cpu;
} else if (idlest_cpu) {
spare = (long)(capacity_of(cpu) - tg->se[cpu]->avg.util_avg);
if (spare > min_util) {
min_util = spare;
*idlest_cpu = cpu;
}
}
if (available_idle_cpu(cpu)) {
rcu_read_unlock();
p->select_cpus = p->prefer_cpus;
return;
}
util_avg_sum += tg->se[cpu]->avg.util_avg;
tg_capacity += capacity_of(cpu);
}
rcu_read_unlock();
if (tg_capacity > cpumask_weight(p->prefer_cpus) &&
util_avg_sum * 100 <= tg_capacity * sysctl_sched_util_low_pct)
p->select_cpus = p->prefer_cpus;
}
#endif
/* /*
* select_task_rq_fair: Select target runqueue for the waking task in domains * 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, * that have the 'sd_flag' flag set. In practice, this is SD_BALANCE_WAKE,
...@@ -6946,6 +7048,9 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f ...@@ -6946,6 +7048,9 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
cpumask_t *cpus; cpumask_t *cpus;
int ret; int ret;
#endif #endif
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
int idlest_cpu = 0;
#endif
time = schedstat_start_time(); time = schedstat_start_time();
...@@ -6953,6 +7058,11 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f ...@@ -6953,6 +7058,11 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
* required for stable ->cpus_allowed * required for stable ->cpus_allowed
*/ */
lockdep_assert_held(&p->pi_lock); lockdep_assert_held(&p->pi_lock);
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
set_task_select_cpus(p, &idlest_cpu, sd_flag);
#endif
if (sd_flag & SD_BALANCE_WAKE) { if (sd_flag & SD_BALANCE_WAKE) {
record_wakee(p); record_wakee(p);
...@@ -6963,7 +7073,11 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f ...@@ -6963,7 +7073,11 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
new_cpu = prev_cpu; new_cpu = prev_cpu;
} }
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
want_affine = !wake_wide(p) && cpumask_test_cpu(cpu, p->select_cpus);
#else
want_affine = !wake_wide(p) && cpumask_test_cpu(cpu, p->cpus_ptr); want_affine = !wake_wide(p) && cpumask_test_cpu(cpu, p->cpus_ptr);
#endif
} }
rcu_read_lock(); rcu_read_lock();
...@@ -7000,7 +7114,13 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f ...@@ -7000,7 +7114,13 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
*/ */
if (want_affine && (tmp->flags & SD_WAKE_AFFINE) && if (want_affine && (tmp->flags & SD_WAKE_AFFINE) &&
cpumask_test_cpu(prev_cpu, sched_domain_span(tmp))) { cpumask_test_cpu(prev_cpu, sched_domain_span(tmp))) {
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
new_cpu = cpu;
if (cpu != prev_cpu &&
cpumask_test_cpu(prev_cpu, p->select_cpus))
#else
if (cpu != prev_cpu) if (cpu != prev_cpu)
#endif
new_cpu = wake_affine(tmp, p, cpu, prev_cpu, sync); new_cpu = wake_affine(tmp, p, cpu, prev_cpu, sync);
sd = NULL; /* Prefer wake_affine over balance flags */ sd = NULL; /* Prefer wake_affine over balance flags */
...@@ -7038,6 +7158,12 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f ...@@ -7038,6 +7158,12 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
#endif #endif
rcu_read_unlock(); rcu_read_unlock();
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
if (!cpumask_test_cpu(new_cpu, p->select_cpus))
new_cpu = idlest_cpu;
#endif
schedstat_end_time(cpu_rq(cpu), time); schedstat_end_time(cpu_rq(cpu), time);
return new_cpu; return new_cpu;
...@@ -9712,8 +9838,13 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu) ...@@ -9712,8 +9838,13 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
int local_group; int local_group;
/* Skip over this group if it has no CPUs allowed */ /* Skip over this group if it has no CPUs allowed */
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
if (!cpumask_intersects(sched_group_span(group),
p->select_cpus))
#else
if (!cpumask_intersects(sched_group_span(group), if (!cpumask_intersects(sched_group_span(group),
p->cpus_ptr)) p->cpus_ptr))
#endif
continue; continue;
/* Skip over this group if no cookie matched */ /* Skip over this group if no cookie matched */
......
...@@ -2728,6 +2728,17 @@ static struct ctl_table kern_table[] = { ...@@ -2728,6 +2728,17 @@ static struct ctl_table kern_table[] = {
.extra1 = SYSCTL_ZERO, .extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE, .extra2 = SYSCTL_ONE,
}, },
#endif
#ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY
{
.procname = "sched_util_low_pct",
.data = &sysctl_sched_util_low_pct,
.maxlen = sizeof(sysctl_sched_util_low_pct),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = SYSCTL_ZERO,
.extra2 = &one_hundred,
},
#endif #endif
{ } { }
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册