diff options
Diffstat (limited to 'kernel/sched/fair.c')
-rw-r--r-- | kernel/sched/fair.c | 54 |
1 files changed, 35 insertions, 19 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 1422765d4b86..09aac90df89e 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c | |||
@@ -1052,6 +1052,20 @@ unlock: | |||
1052 | rcu_read_unlock(); | 1052 | rcu_read_unlock(); |
1053 | } | 1053 | } |
1054 | 1054 | ||
1055 | static void task_numa_find_cpu(struct task_numa_env *env, long imp) | ||
1056 | { | ||
1057 | int cpu; | ||
1058 | |||
1059 | for_each_cpu(cpu, cpumask_of_node(env->dst_nid)) { | ||
1060 | /* Skip this CPU if the source task cannot migrate */ | ||
1061 | if (!cpumask_test_cpu(cpu, tsk_cpus_allowed(env->p))) | ||
1062 | continue; | ||
1063 | |||
1064 | env->dst_cpu = cpu; | ||
1065 | task_numa_compare(env, imp); | ||
1066 | } | ||
1067 | } | ||
1068 | |||
1055 | static int task_numa_migrate(struct task_struct *p) | 1069 | static int task_numa_migrate(struct task_struct *p) |
1056 | { | 1070 | { |
1057 | struct task_numa_env env = { | 1071 | struct task_numa_env env = { |
@@ -1068,7 +1082,8 @@ static int task_numa_migrate(struct task_struct *p) | |||
1068 | }; | 1082 | }; |
1069 | struct sched_domain *sd; | 1083 | struct sched_domain *sd; |
1070 | unsigned long faults; | 1084 | unsigned long faults; |
1071 | int nid, cpu, ret; | 1085 | int nid, ret; |
1086 | long imp; | ||
1072 | 1087 | ||
1073 | /* | 1088 | /* |
1074 | * Pick the lowest SD_NUMA domain, as that would have the smallest | 1089 | * Pick the lowest SD_NUMA domain, as that would have the smallest |
@@ -1085,28 +1100,29 @@ static int task_numa_migrate(struct task_struct *p) | |||
1085 | 1100 | ||
1086 | faults = task_faults(p, env.src_nid); | 1101 | faults = task_faults(p, env.src_nid); |
1087 | update_numa_stats(&env.src_stats, env.src_nid); | 1102 | update_numa_stats(&env.src_stats, env.src_nid); |
1103 | env.dst_nid = p->numa_preferred_nid; | ||
1104 | imp = task_faults(env.p, env.dst_nid) - faults; | ||
1105 | update_numa_stats(&env.dst_stats, env.dst_nid); | ||
1088 | 1106 | ||
1089 | /* Find an alternative node with relatively better statistics */ | 1107 | /* |
1090 | for_each_online_node(nid) { | 1108 | * If the preferred nid has capacity then use it. Otherwise find an |
1091 | long imp; | 1109 | * alternative node with relatively better statistics. |
1092 | 1110 | */ | |
1093 | if (nid == env.src_nid) | 1111 | if (env.dst_stats.has_capacity) { |
1094 | continue; | 1112 | task_numa_find_cpu(&env, imp); |
1095 | 1113 | } else { | |
1096 | /* Only consider nodes that recorded more faults */ | 1114 | for_each_online_node(nid) { |
1097 | imp = task_faults(p, nid) - faults; | 1115 | if (nid == env.src_nid || nid == p->numa_preferred_nid) |
1098 | if (imp < 0) | 1116 | continue; |
1099 | continue; | ||
1100 | 1117 | ||
1101 | env.dst_nid = nid; | 1118 | /* Only consider nodes that recorded more faults */ |
1102 | update_numa_stats(&env.dst_stats, env.dst_nid); | 1119 | imp = task_faults(env.p, nid) - faults; |
1103 | for_each_cpu(cpu, cpumask_of_node(nid)) { | 1120 | if (imp < 0) |
1104 | /* Skip this CPU if the source task cannot migrate */ | ||
1105 | if (!cpumask_test_cpu(cpu, tsk_cpus_allowed(p))) | ||
1106 | continue; | 1121 | continue; |
1107 | 1122 | ||
1108 | env.dst_cpu = cpu; | 1123 | env.dst_nid = nid; |
1109 | task_numa_compare(&env, imp); | 1124 | update_numa_stats(&env.dst_stats, env.dst_nid); |
1125 | task_numa_find_cpu(&env, imp); | ||
1110 | } | 1126 | } |
1111 | } | 1127 | } |
1112 | 1128 | ||