|
@@ -23,6 +23,7 @@
|
|
|
#include <linux/latencytop.h>
|
|
|
#include <linux/sched.h>
|
|
|
#include <linux/cpumask.h>
|
|
|
+#include <linux/cpuidle.h>
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/profile.h>
|
|
|
#include <linux/interrupt.h>
|
|
@@ -4415,20 +4416,46 @@ static int
|
|
|
find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
|
|
|
{
|
|
|
unsigned long load, min_load = ULONG_MAX;
|
|
|
- int idlest = -1;
|
|
|
+ unsigned int min_exit_latency = UINT_MAX;
|
|
|
+ u64 latest_idle_timestamp = 0;
|
|
|
+ int least_loaded_cpu = this_cpu;
|
|
|
+ int shallowest_idle_cpu = -1;
|
|
|
int i;
|
|
|
|
|
|
/* Traverse only the allowed CPUs */
|
|
|
for_each_cpu_and(i, sched_group_cpus(group), tsk_cpus_allowed(p)) {
|
|
|
- load = weighted_cpuload(i);
|
|
|
-
|
|
|
- if (load < min_load || (load == min_load && i == this_cpu)) {
|
|
|
- min_load = load;
|
|
|
- idlest = i;
|
|
|
+ if (idle_cpu(i)) {
|
|
|
+ struct rq *rq = cpu_rq(i);
|
|
|
+ struct cpuidle_state *idle = idle_get_state(rq);
|
|
|
+ if (idle && idle->exit_latency < min_exit_latency) {
|
|
|
+ /*
|
|
|
+ * We give priority to a CPU whose idle state
|
|
|
+ * has the smallest exit latency irrespective
|
|
|
+ * of any idle timestamp.
|
|
|
+ */
|
|
|
+ min_exit_latency = idle->exit_latency;
|
|
|
+ latest_idle_timestamp = rq->idle_stamp;
|
|
|
+ shallowest_idle_cpu = i;
|
|
|
+ } else if ((!idle || idle->exit_latency == min_exit_latency) &&
|
|
|
+ rq->idle_stamp > latest_idle_timestamp) {
|
|
|
+ /*
|
|
|
+ * If equal or no active idle state, then
|
|
|
+ * the most recently idled CPU might have
|
|
|
+ * a warmer cache.
|
|
|
+ */
|
|
|
+ latest_idle_timestamp = rq->idle_stamp;
|
|
|
+ shallowest_idle_cpu = i;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ load = weighted_cpuload(i);
|
|
|
+ if (load < min_load || (load == min_load && i == this_cpu)) {
|
|
|
+ min_load = load;
|
|
|
+ least_loaded_cpu = i;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return idlest;
|
|
|
+ return shallowest_idle_cpu != -1 ? shallowest_idle_cpu : least_loaded_cpu;
|
|
|
}
|
|
|
|
|
|
/*
|