|
@@ -1005,6 +1005,23 @@ static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
|
|
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
|
|
+/*
|
|
|
+ * Is this task likely cache-hot:
|
|
|
+ */
|
|
|
+static inline int
|
|
|
+task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
|
|
|
+{
|
|
|
+ s64 delta;
|
|
|
+
|
|
|
+ if (p->sched_class != &fair_sched_class)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ delta = now - p->se.exec_start;
|
|
|
+
|
|
|
+ return delta < (s64)sysctl_sched_migration_cost;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
|
|
|
{
|
|
|
int old_cpu = task_cpu(p);
|
|
@@ -1022,6 +1039,11 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
|
|
|
p->se.sleep_start -= clock_offset;
|
|
|
if (p->se.block_start)
|
|
|
p->se.block_start -= clock_offset;
|
|
|
+ if (old_cpu != new_cpu) {
|
|
|
+ schedstat_inc(p, se.nr_migrations);
|
|
|
+ if (task_hot(p, old_rq->clock, NULL))
|
|
|
+ schedstat_inc(p, se.nr_forced2_migrations);
|
|
|
+ }
|
|
|
#endif
|
|
|
p->se.vruntime -= old_cfsrq->min_vruntime -
|
|
|
new_cfsrq->min_vruntime;
|
|
@@ -1394,8 +1416,13 @@ static int wake_idle(int cpu, struct task_struct *p)
|
|
|
if (sd->flags & SD_WAKE_IDLE) {
|
|
|
cpus_and(tmp, sd->span, p->cpus_allowed);
|
|
|
for_each_cpu_mask(i, tmp) {
|
|
|
- if (idle_cpu(i))
|
|
|
+ if (idle_cpu(i)) {
|
|
|
+ if (i != task_cpu(p)) {
|
|
|
+ schedstat_inc(p,
|
|
|
+ se.nr_wakeups_idle);
|
|
|
+ }
|
|
|
return i;
|
|
|
+ }
|
|
|
}
|
|
|
} else {
|
|
|
break;
|
|
@@ -1426,7 +1453,7 @@ static inline int wake_idle(int cpu, struct task_struct *p)
|
|
|
*/
|
|
|
static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
|
|
|
{
|
|
|
- int cpu, this_cpu, success = 0;
|
|
|
+ int cpu, orig_cpu, this_cpu, success = 0;
|
|
|
unsigned long flags;
|
|
|
long old_state;
|
|
|
struct rq *rq;
|
|
@@ -1445,6 +1472,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
|
|
|
goto out_running;
|
|
|
|
|
|
cpu = task_cpu(p);
|
|
|
+ orig_cpu = cpu;
|
|
|
this_cpu = smp_processor_id();
|
|
|
|
|
|
#ifdef CONFIG_SMP
|
|
@@ -1488,6 +1516,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
|
|
|
unsigned long tl = this_load;
|
|
|
unsigned long tl_per_task;
|
|
|
|
|
|
+ schedstat_inc(p, se.nr_wakeups_affine_attempts);
|
|
|
tl_per_task = cpu_avg_load_per_task(this_cpu);
|
|
|
|
|
|
/*
|
|
@@ -1507,6 +1536,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
|
|
|
* there is no bad imbalance.
|
|
|
*/
|
|
|
schedstat_inc(this_sd, ttwu_move_affine);
|
|
|
+ schedstat_inc(p, se.nr_wakeups_affine);
|
|
|
goto out_set_cpu;
|
|
|
}
|
|
|
}
|
|
@@ -1518,6 +1548,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
|
|
|
if (this_sd->flags & SD_WAKE_BALANCE) {
|
|
|
if (imbalance*this_load <= 100*load) {
|
|
|
schedstat_inc(this_sd, ttwu_move_balance);
|
|
|
+ schedstat_inc(p, se.nr_wakeups_passive);
|
|
|
goto out_set_cpu;
|
|
|
}
|
|
|
}
|
|
@@ -1543,6 +1574,15 @@ out_set_cpu:
|
|
|
|
|
|
out_activate:
|
|
|
#endif /* CONFIG_SMP */
|
|
|
+ schedstat_inc(p, se.nr_wakeups);
|
|
|
+ if (sync)
|
|
|
+ schedstat_inc(p, se.nr_wakeups_sync);
|
|
|
+ if (orig_cpu != cpu)
|
|
|
+ schedstat_inc(p, se.nr_wakeups_migrate);
|
|
|
+ if (cpu == this_cpu)
|
|
|
+ schedstat_inc(p, se.nr_wakeups_local);
|
|
|
+ else
|
|
|
+ schedstat_inc(p, se.nr_wakeups_remote);
|
|
|
update_rq_clock(rq);
|
|
|
activate_task(rq, p, 1);
|
|
|
/*
|
|
@@ -2118,22 +2158,6 @@ static void pull_task(struct rq *src_rq, struct task_struct *p,
|
|
|
check_preempt_curr(this_rq, p);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Is this task likely cache-hot:
|
|
|
- */
|
|
|
-static inline int
|
|
|
-task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
|
|
|
-{
|
|
|
- s64 delta;
|
|
|
-
|
|
|
- if (p->sched_class != &fair_sched_class)
|
|
|
- return 0;
|
|
|
-
|
|
|
- delta = now - p->se.exec_start;
|
|
|
-
|
|
|
- return delta < (s64)sysctl_sched_migration_cost;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* can_migrate_task - may task p from runqueue rq be migrated to this_cpu?
|
|
|
*/
|
|
@@ -2148,12 +2172,16 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
|
|
|
* 2) cannot be migrated to this CPU due to cpus_allowed, or
|
|
|
* 3) are cache-hot on their current CPU.
|
|
|
*/
|
|
|
- if (!cpu_isset(this_cpu, p->cpus_allowed))
|
|
|
+ if (!cpu_isset(this_cpu, p->cpus_allowed)) {
|
|
|
+ schedstat_inc(p, se.nr_failed_migrations_affine);
|
|
|
return 0;
|
|
|
+ }
|
|
|
*all_pinned = 0;
|
|
|
|
|
|
- if (task_running(rq, p))
|
|
|
+ if (task_running(rq, p)) {
|
|
|
+ schedstat_inc(p, se.nr_failed_migrations_running);
|
|
|
return 0;
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
|
* Aggressive migration if:
|
|
@@ -2163,14 +2191,18 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
|
|
|
|
|
|
if (sd->nr_balance_failed > sd->cache_nice_tries) {
|
|
|
#ifdef CONFIG_SCHEDSTATS
|
|
|
- if (task_hot(p, rq->clock, sd))
|
|
|
+ if (task_hot(p, rq->clock, sd)) {
|
|
|
schedstat_inc(sd, lb_hot_gained[idle]);
|
|
|
+ schedstat_inc(p, se.nr_forced_migrations);
|
|
|
+ }
|
|
|
#endif
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
- if (task_hot(p, rq->clock, sd))
|
|
|
+ if (task_hot(p, rq->clock, sd)) {
|
|
|
+ schedstat_inc(p, se.nr_failed_migrations_hot);
|
|
|
return 0;
|
|
|
+ }
|
|
|
return 1;
|
|
|
}
|
|
|
|