sched: notify cpufreq on over/underprovisioned CPUs
After a migration occurs the source and destination CPUs may not be running at frequencies which match the new task load on those CPUs. Previously, the scheduler was notifying cpufreq anytime a task greater than a certain size migrates. This is suboptimal however since this does not take into account the CPU's current frequency and other task activity that may be present. Change-Id: I5092bda3a517e1343f97e5a455957c25ee19b549 Signed-off-by: Steve Muckle <smuckle@codeaurora.org>
This commit is contained in:
parent
dbd2db2471
commit
80753c7e5e
|
@ -43,7 +43,10 @@ extern unsigned int sysctl_sched_window_stats_policy;
|
|||
extern unsigned int sysctl_sched_init_task_load_pct;
|
||||
#endif
|
||||
|
||||
extern unsigned int sysctl_sched_task_migrate_notify_pct;
|
||||
#ifdef CONFIG_SCHED_FREQ_INPUT
|
||||
extern int sysctl_sched_freq_inc_notify_slack_pct;
|
||||
extern int sysctl_sched_freq_dec_notify_slack_pct;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCHED_HMP
|
||||
extern unsigned int sysctl_sched_enable_hmp_task_placement;
|
||||
|
|
|
@ -1019,27 +1019,29 @@ unsigned int __read_mostly sched_use_pelt;
|
|||
unsigned int max_possible_efficiency = 1024;
|
||||
unsigned int min_possible_efficiency = 1024;
|
||||
|
||||
__read_mostly unsigned int sysctl_sched_task_migrate_notify_pct = 25;
|
||||
unsigned int sched_task_migrate_notify;
|
||||
__read_mostly int sysctl_sched_freq_inc_notify_slack_pct;
|
||||
__read_mostly int sysctl_sched_freq_dec_notify_slack_pct = 25;
|
||||
|
||||
int sched_migrate_notify_proc_handler(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
/* Returns how undercommitted a CPU is given its current frequency and
|
||||
* task load (as measured in the previous window). Returns this value
|
||||
* as a percentage of the CPU's maximum frequency. A negative value
|
||||
* means the CPU is overcommitted at its current frequency.
|
||||
*/
|
||||
int rq_freq_margin(struct rq *rq)
|
||||
{
|
||||
int ret;
|
||||
unsigned int *data = (unsigned int *)table->data;
|
||||
unsigned int freq_required;
|
||||
int margin;
|
||||
|
||||
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
||||
if (ret || !write)
|
||||
return ret;
|
||||
freq_required = scale_task_load(rq->prev_runnable_sum, rq->cpu);
|
||||
freq_required *= 128;
|
||||
freq_required /= max_task_load();
|
||||
freq_required *= rq->max_possible_freq;
|
||||
freq_required /= 128;
|
||||
|
||||
if (*data > 100)
|
||||
return -EINVAL;
|
||||
|
||||
sched_task_migrate_notify = div64_u64((u64)*data *
|
||||
(u64)max_task_load(), 100);
|
||||
|
||||
return 0;
|
||||
margin = rq->cur_freq - freq_required;
|
||||
margin *= 100;
|
||||
margin /= (int)rq->max_possible_freq;
|
||||
return margin;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1366,6 +1368,11 @@ update_task_ravg(struct task_struct *p, struct rq *rq,
|
|||
{
|
||||
}
|
||||
|
||||
static inline int rq_freq_margin(struct rq *rq)
|
||||
{
|
||||
return INT_MAX;
|
||||
}
|
||||
|
||||
static inline void init_cpu_efficiency(void) {}
|
||||
|
||||
static inline void mark_task_starting(struct task_struct *p) {}
|
||||
|
@ -1448,23 +1455,33 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
|
|||
if (p->state == TASK_WAKING)
|
||||
double_rq_unlock(src_rq, dest_rq);
|
||||
|
||||
/* Is p->ravg.prev_window significant? Trigger a load
|
||||
alert notifier if so. */
|
||||
if (p->ravg.prev_window > sched_task_migrate_notify &&
|
||||
!cpumask_test_cpu(new_cpu,
|
||||
&src_rq->freq_domain_cpumask)) {
|
||||
atomic_notifier_call_chain(
|
||||
&load_alert_notifier_head, 0,
|
||||
(void *)task_cpu(p));
|
||||
if (cpumask_test_cpu(new_cpu,
|
||||
&src_rq->freq_domain_cpumask))
|
||||
goto done;
|
||||
|
||||
/* Evaluate possible frequency notifications for
|
||||
* source and destination CPUs in different frequency
|
||||
* domains. */
|
||||
if (rq_freq_margin(dest_rq) <
|
||||
sysctl_sched_freq_inc_notify_slack_pct)
|
||||
atomic_notifier_call_chain(
|
||||
&load_alert_notifier_head, 0,
|
||||
(void *)new_cpu);
|
||||
}
|
||||
|
||||
if (rq_freq_margin(src_rq) >
|
||||
sysctl_sched_freq_dec_notify_slack_pct)
|
||||
atomic_notifier_call_chain(
|
||||
&load_alert_notifier_head, 0,
|
||||
(void *)task_cpu(p));
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SCHED_FREQ_INPUT) || defined(CONFIG_SCHED_HMP)
|
||||
done:
|
||||
#endif
|
||||
__set_task_cpu(p, new_cpu);
|
||||
}
|
||||
|
||||
|
@ -1978,6 +1995,14 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
|
|||
if (src_cpu != cpu) {
|
||||
wake_flags |= WF_MIGRATED;
|
||||
set_task_cpu(p, cpu);
|
||||
} else {
|
||||
#ifdef CONFIG_SCHED_FREQ_INPUT
|
||||
if (rq_freq_margin(cpu_rq(cpu)) <
|
||||
sysctl_sched_freq_inc_notify_slack_pct)
|
||||
atomic_notifier_call_chain(
|
||||
&load_alert_notifier_head, 0,
|
||||
(void *)cpu);
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
|
@ -2245,6 +2270,13 @@ void wake_up_new_task(struct task_struct *p)
|
|||
|
||||
rq = __task_rq_lock(p);
|
||||
mark_task_starting(p);
|
||||
#ifdef CONFIG_SCHED_FREQ_INPUT
|
||||
if (rq_freq_margin(task_rq(p)) <
|
||||
sysctl_sched_freq_inc_notify_slack_pct)
|
||||
atomic_notifier_call_chain(
|
||||
&load_alert_notifier_head, 0,
|
||||
(void *)task_cpu(p));
|
||||
#endif
|
||||
activate_task(rq, p, 0);
|
||||
p->on_rq = 1;
|
||||
trace_sched_wakeup_new(p, true);
|
||||
|
|
|
@ -296,11 +296,18 @@ static struct ctl_table kern_table[] = {
|
|||
},
|
||||
#ifdef CONFIG_SCHED_FREQ_INPUT
|
||||
{
|
||||
.procname = "sched_task_migrate_notify",
|
||||
.data = &sysctl_sched_task_migrate_notify_pct,
|
||||
.procname = "sched_freq_inc_notify_slack_pct",
|
||||
.data = &sysctl_sched_freq_inc_notify_slack_pct,
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = sched_migrate_notify_proc_handler,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
{
|
||||
.procname = "sched_freq_dec_notify_slack_pct",
|
||||
.data = &sysctl_sched_freq_dec_notify_slack_pct,
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
#endif
|
||||
#if defined(CONFIG_SCHED_FREQ_INPUT) || defined(CONFIG_SCHED_HMP)
|
||||
|
|
Loading…
Reference in New Issue