FreeBSD/sys/kern/sched_4bsd.c
/*
 * A CPU is entering for the first time or a thread is exiting.
 */
A CPU is entering for the first time or a thread is exiting.
A CPU is entering for the first time or a thread is exiting .
void
sched_throw(struct thread *td)
{
	if (td == NULL) {
		mtx_lock_spin(&sched_lock);
		spinlock_exit();
		PCPU_SET(switchtime, cpu_ticks());
		PCPU_SET(switchticks, ticks);
	} else {
		lock_profile_release_lock(&sched_lock.lock_object);
		MPASS(td->td_lock == &sched_lock);
		td->td_lastcpu = td->td_oncpu;
		td->td_oncpu = NOCPU;
	}
	mtx_assert(&sched_lock, MA_OWNED);
	KASSERT(curthread->td_md.md_spinlock_count == 1, ("invalid count"));
	cpu_throw(td, choosethread());	
}
void sched_throw ( struct thread * td ) { if ( td == NULL ) { mtx_lock_spin ( & sched_lock ) ; spinlock_exit ( ) ; PCPU_SET ( switchtime , cpu_ticks ( ) ) ; PCPU_SET ( switchticks , ticks ) ; } else { lock_profile_release_lock ( & sched_lock . lock_object ) ; MPASS ( td -> td_lock == & sched_lock ) ; td -> td_lastcpu = td -> td_oncpu ; td -> td_oncpu = NOCPU ; } mtx_assert ( & sched_lock , MA_OWNED ) ; KASSERT ( curthread -> td_md . md_spinlock_count == 1 , ( " " ) ) ; cpu_throw ( td , choosethread ( ) ) ; }
A CPU is entering for the first time or a thread is exiting.
A CPU is entering for the first time or a thread is exiting .
/*
	 * Correct spinlock nesting.  The idle thread context that we are
	 * borrowing was created so that it would start out with a single
	 * spin lock (sched_lock) held in fork_trampoline().  Since we've
	 * explicitly acquired locks in this function, the nesting count
	 * is now 2 rather than 1.  Since we are nested, calling
	 * spinlock_exit() will simply adjust the counts without allowing
	 * spin lock using code to interrupt us.
	 */ /* doesn't return */