* Sets the thread lock and ts_cpu to match the requested cpu. Unlocks the * current lock and returns with the assigned queue locked. */
| 1199 | * current lock and returns with the assigned queue locked. |
| 1200 | */ |
| 1201 | static inline struct tdq * |
| 1202 | sched_setcpu(struct thread *td, int cpu, int flags) |
| 1203 | { |
| 1204 | |
| 1205 | struct tdq *tdq; |
| 1206 | struct mtx *mtx; |
| 1207 | |
| 1208 | THREAD_LOCK_ASSERT(td, MA_OWNED); |
| 1209 | tdq = TDQ_CPU(cpu); |
| 1210 | td_get_sched(td)->ts_cpu = cpu; |
| 1211 | /* |
| 1212 | * If the lock matches just return the queue. |
| 1213 | */ |
| 1214 | if (td->td_lock == TDQ_LOCKPTR(tdq)) { |
| 1215 | KASSERT((flags & SRQ_HOLD) == 0, |
| 1216 | ("sched_setcpu: Invalid lock for SRQ_HOLD")); |
| 1217 | return (tdq); |
| 1218 | } |
| 1219 | |
| 1220 | /* |
| 1221 | * The hard case, migration, we need to block the thread first to |
| 1222 | * prevent order reversals with other cpus locks. |
| 1223 | */ |
| 1224 | spinlock_enter(); |
| 1225 | mtx = thread_lock_block(td); |
| 1226 | if ((flags & SRQ_HOLD) == 0) |
| 1227 | mtx_unlock_spin(mtx); |
| 1228 | TDQ_LOCK(tdq); |
| 1229 | thread_lock_unblock(td, TDQ_LOCKPTR(tdq)); |
| 1230 | spinlock_exit(); |
| 1231 | return (tdq); |
| 1232 | } |
| 1233 | |
| 1234 | SCHED_STAT_DEFINE(pickcpu_intrbind, "Soft interrupt binding"); |
| 1235 | SCHED_STAT_DEFINE(pickcpu_idle_affinity, "Picked idle cpu based on affinity"); |
no test coverage detected