* A CPU is entering for the first time or a thread is exiting. */
| 2890 | * A CPU is entering for the first time or a thread is exiting. |
| 2891 | */ |
| 2892 | void |
| 2893 | sched_throw(struct thread *td) |
| 2894 | { |
| 2895 | struct thread *newtd; |
| 2896 | struct tdq *tdq; |
| 2897 | |
| 2898 | if (__predict_false(td == NULL)) { |
| 2899 | #ifdef SMP |
| 2900 | PCPU_SET(sched, DPCPU_PTR(tdq)); |
| 2901 | #endif |
| 2902 | /* Correct spinlock nesting and acquire the correct lock. */ |
| 2903 | tdq = TDQ_SELF(); |
| 2904 | TDQ_LOCK(tdq); |
| 2905 | spinlock_exit(); |
| 2906 | PCPU_SET(switchtime, cpu_ticks()); |
| 2907 | PCPU_SET(switchticks, ticks); |
| 2908 | PCPU_GET(idlethread)->td_lock = TDQ_LOCKPTR(tdq); |
| 2909 | } else { |
| 2910 | tdq = TDQ_SELF(); |
| 2911 | THREAD_LOCK_ASSERT(td, MA_OWNED); |
| 2912 | THREAD_LOCKPTR_ASSERT(td, TDQ_LOCKPTR(tdq)); |
| 2913 | tdq_load_rem(tdq, td); |
| 2914 | td->td_lastcpu = td->td_oncpu; |
| 2915 | td->td_oncpu = NOCPU; |
| 2916 | thread_lock_block(td); |
| 2917 | } |
| 2918 | newtd = choosethread(); |
| 2919 | spinlock_enter(); |
| 2920 | TDQ_UNLOCK(tdq); |
| 2921 | KASSERT(curthread->td_md.md_spinlock_count == 1, |
| 2922 | ("invalid count %d", curthread->td_md.md_spinlock_count)); |
| 2923 | /* doesn't return */ |
| 2924 | if (__predict_false(td == NULL)) |
| 2925 | cpu_throw(td, newtd); /* doesn't return */ |
| 2926 | else |
| 2927 | cpu_switch(td, newtd, TDQ_LOCKPTR(tdq)); |
| 2928 | } |
| 2929 | |
| 2930 | /* |
| 2931 | * This is called from fork_exit(). Just acquire the correct locks and |
no test coverage detected