We've met problems that occasionally tasks with full cpumask (e.g. by putting it into a cpuset or setting to full affinity) were migrated to our isolated cpus in production environment. After some analysis, we found that it is due to the current select_idle_smt() not considering the sched_domain mask. Steps to reproduce on my 31-CPU hyperthreads machine: 1. with boot parameter: "isolcpus=domain,2-31" (thread lists: 0,16 and 1,17) 2. cgcreate -g cpu:test; cgexec -g cpu:test "test_threads" 3. some threads will be migrated to the isolated cpu16~17. Fix it by checking the valid domain mask in select_idle_smt().
Unified · Split
| @@ -6080,7 +6080,7 @@ static int select_idle_core(struct task_struct *p, struct sched_domain *sd, int · 6079 unmodified lines | ||
| 6080 | 6080 | /* |
| 6081 | 6081 | * Scan the local SMT mask for idle CPUs. |
| 6082 | 6082 | */ |
| 6083 | −static int select_idle_smt(struct task_struct *p, int target) | |
| 6083 | +static int select_idle_smt(struct task_struct *p, struct sched_domain *sd, int target) | |
| 6084 | 6084 | { |
| 6085 | 6085 | int cpu; |
| 6086 | 6086 | |
| @@ -6088,7 +6088,8 @@ static int select_idle_smt(struct task_struct *p, int target) · 1 unmodified line | ||
| 6088 | 6088 | return -1; |
| 6089 | 6089 | |
| 6090 | 6090 | for_each_cpu(cpu, cpu_smt_mask(target)) { |
| 6091 | − if (!cpumask_test_cpu(cpu, p->cpus_ptr)) | |
| 6091 | + if (!cpumask_test_cpu(cpu, p->cpus_ptr) || | |
| 6092 | + !cpumask_test_cpu(cpu, sched_domain_span(sd))) | |
| 6092 | 6093 | continue; |
| 6093 | 6094 | if (available_idle_cpu(cpu) || sched_idle_cpu(cpu)) |
| 6094 | 6095 | return cpu; |
| @@ -6104,7 +6105,7 @@ static inline int select_idle_core(struct task_struct *p, struct sched_domain *s · 9 unmodified lines | ||
| 6104 | 6105 | return -1; |
| 6105 | 6106 | } |
| 6106 | 6107 | |
| 6107 | −static inline int select_idle_smt(struct task_struct *p, int target) | |
| 6108 | +static inline int select_idle_smt(struct task_struct *p, struct sched_domain *sd, int target) | |
| 6108 | 6109 | { |
| 6109 | 6110 | return -1; |
| 6110 | 6111 | } |
| @@ -6279,7 +6280,7 @@ symmetric: · 168 unmodified lines | ||
| 6279 | 6280 | if ((unsigned)i < nr_cpumask_bits) |
| 6280 | 6281 | return i; |
| 6281 | 6282 | |
| 6282 | − i = select_idle_smt(p, target); | |
| 6283 | + i = select_idle_smt(p, sd, target); | |
| 6283 | 6284 | if ((unsigned)i < nr_cpumask_bits) |
| 6284 | 6285 | return i; |
| 6285 | 6286 | |