* Switch threads. This function has to handle threads coming in while * blocked for some reason, running, or idle. It also must deal with * migrating a thread from one queue to another as running threads may * be assigned elsewhere via binding. */
| 2044 | * be assigned elsewhere via binding. |
| 2045 | */ |
| 2046 | void |
| 2047 | sched_switch(struct thread *td, int flags) |
| 2048 | { |
| 2049 | struct thread *newtd; |
| 2050 | struct tdq *tdq; |
| 2051 | struct td_sched *ts; |
| 2052 | struct mtx *mtx; |
| 2053 | int srqflag; |
| 2054 | int cpuid, preempted; |
| 2055 | |
| 2056 | THREAD_LOCK_ASSERT(td, MA_OWNED); |
| 2057 | |
| 2058 | cpuid = PCPU_GET(cpuid); |
| 2059 | tdq = TDQ_SELF(); |
| 2060 | ts = td_get_sched(td); |
| 2061 | sched_pctcpu_update(ts, 1); |
| 2062 | ts->ts_rltick = ticks; |
| 2063 | td->td_lastcpu = td->td_oncpu; |
| 2064 | preempted = (td->td_flags & TDF_SLICEEND) == 0 && |
| 2065 | (flags & SW_PREEMPT) != 0; |
| 2066 | td->td_flags &= ~(TDF_NEEDRESCHED | TDF_SLICEEND); |
| 2067 | td->td_owepreempt = 0; |
| 2068 | tdq->tdq_owepreempt = 0; |
| 2069 | if (!TD_IS_IDLETHREAD(td)) |
| 2070 | tdq->tdq_switchcnt++; |
| 2071 | |
| 2072 | /* |
| 2073 | * Always block the thread lock so we can drop the tdq lock early. |
| 2074 | */ |
| 2075 | mtx = thread_lock_block(td); |
| 2076 | spinlock_enter(); |
| 2077 | if (TD_IS_IDLETHREAD(td)) { |
| 2078 | MPASS(mtx == TDQ_LOCKPTR(tdq)); |
| 2079 | TD_SET_CAN_RUN(td); |
| 2080 | } else if (TD_IS_RUNNING(td)) { |
| 2081 | MPASS(mtx == TDQ_LOCKPTR(tdq)); |
| 2082 | srqflag = preempted ? |
| 2083 | SRQ_OURSELF|SRQ_YIELDING|SRQ_PREEMPTED : |
| 2084 | SRQ_OURSELF|SRQ_YIELDING; |
| 2085 | #ifdef SMP |
| 2086 | if (THREAD_CAN_MIGRATE(td) && !THREAD_CAN_SCHED(td, ts->ts_cpu)) |
| 2087 | ts->ts_cpu = sched_pickcpu(td, 0); |
| 2088 | #endif |
| 2089 | if (ts->ts_cpu == cpuid) |
| 2090 | tdq_runq_add(tdq, td, srqflag); |
| 2091 | else |
| 2092 | mtx = sched_switch_migrate(tdq, td, srqflag); |
| 2093 | } else { |
| 2094 | /* This thread must be going to sleep. */ |
| 2095 | if (mtx != TDQ_LOCKPTR(tdq)) { |
| 2096 | mtx_unlock_spin(mtx); |
| 2097 | TDQ_LOCK(tdq); |
| 2098 | } |
| 2099 | tdq_load_rem(tdq, td); |
| 2100 | #ifdef SMP |
| 2101 | if (tdq->tdq_load == 0) |
| 2102 | tdq_trysteal(tdq); |
| 2103 | #endif |
no test coverage detected