| 1239 | SCHED_STAT_DEFINE(pickcpu_migration, "Selection may have caused migration"); |
| 1240 | |
| 1241 | static int |
| 1242 | sched_pickcpu(struct thread *td, int flags) |
| 1243 | { |
| 1244 | struct cpu_group *cg, *ccg; |
| 1245 | struct td_sched *ts; |
| 1246 | struct tdq *tdq; |
| 1247 | cpuset_t mask; |
| 1248 | int cpu, pri, self, intr; |
| 1249 | |
| 1250 | self = PCPU_GET(cpuid); |
| 1251 | ts = td_get_sched(td); |
| 1252 | KASSERT(!CPU_ABSENT(ts->ts_cpu), ("sched_pickcpu: Start scheduler on " |
| 1253 | "absent CPU %d for thread %s.", ts->ts_cpu, td->td_name)); |
| 1254 | if (smp_started == 0) |
| 1255 | return (self); |
| 1256 | /* |
| 1257 | * Don't migrate a running thread from sched_switch(). |
| 1258 | */ |
| 1259 | if ((flags & SRQ_OURSELF) || !THREAD_CAN_MIGRATE(td)) |
| 1260 | return (ts->ts_cpu); |
| 1261 | /* |
| 1262 | * Prefer to run interrupt threads on the processors that generate |
| 1263 | * the interrupt. |
| 1264 | */ |
| 1265 | if (td->td_priority <= PRI_MAX_ITHD && THREAD_CAN_SCHED(td, self) && |
| 1266 | curthread->td_intr_nesting_level) { |
| 1267 | tdq = TDQ_SELF(); |
| 1268 | if (tdq->tdq_lowpri >= PRI_MIN_IDLE) { |
| 1269 | SCHED_STAT_INC(pickcpu_idle_affinity); |
| 1270 | return (self); |
| 1271 | } |
| 1272 | ts->ts_cpu = self; |
| 1273 | intr = 1; |
| 1274 | cg = tdq->tdq_cg; |
| 1275 | goto llc; |
| 1276 | } else { |
| 1277 | intr = 0; |
| 1278 | tdq = TDQ_CPU(ts->ts_cpu); |
| 1279 | cg = tdq->tdq_cg; |
| 1280 | } |
| 1281 | /* |
| 1282 | * If the thread can run on the last cpu and the affinity has not |
| 1283 | * expired and it is idle, run it there. |
| 1284 | */ |
| 1285 | if (THREAD_CAN_SCHED(td, ts->ts_cpu) && |
| 1286 | tdq->tdq_lowpri >= PRI_MIN_IDLE && |
| 1287 | SCHED_AFFINITY(ts, CG_SHARE_L2)) { |
| 1288 | if (cg->cg_flags & CG_FLAG_THREAD) { |
| 1289 | /* Check all SMT threads for being idle. */ |
| 1290 | for (cpu = CPU_FFS(&cg->cg_mask) - 1; ; cpu++) { |
| 1291 | if (CPU_ISSET(cpu, &cg->cg_mask) && |
| 1292 | TDQ_CPU(cpu)->tdq_lowpri < PRI_MIN_IDLE) |
| 1293 | break; |
| 1294 | if (cpu >= mp_maxid) { |
| 1295 | SCHED_STAT_INC(pickcpu_idle_affinity); |
| 1296 | return (ts->ts_cpu); |
| 1297 | } |
| 1298 | } |
no test coverage detected