FreeBSD/sys/kern/sched_ule.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)
{
	struct thread *newtd;
	struct tdq *tdq;
	tdq = TDQ_SELF();
	if (td == NULL) {
		TDQ_LOCK(tdq);
		spinlock_exit();
		PCPU_SET(switchtime, cpu_ticks());
		PCPU_SET(switchticks, ticks);
	} else {
		MPASS(td->td_lock == TDQ_LOCKPTR(tdq));
		tdq_load_rem(tdq, td);
		lock_profile_release_lock(&TDQ_LOCKPTR(tdq)->lock_object);
		td->td_lastcpu = td->td_oncpu;
		td->td_oncpu = NOCPU;
	}
	KASSERT(curthread->td_md.md_spinlock_count == 1, ("invalid count"));
	newtd = choosethread();
	TDQ_LOCKPTR(tdq)->mtx_lock = (uintptr_t)newtd;
	cpu_throw(td, newtd);		
}
void sched_throw ( struct thread * td ) { struct thread * newtd ; struct tdq * tdq ; tdq = TDQ_SELF ( ) ; if ( td == NULL ) { TDQ_LOCK ( tdq ) ; spinlock_exit ( ) ; PCPU_SET ( switchtime , cpu_ticks ( ) ) ; PCPU_SET ( switchticks , ticks ) ; } else { MPASS ( td -> td_lock == TDQ_LOCKPTR ( tdq ) ) ; tdq_load_rem ( tdq , td ) ; lock_profile_release_lock ( & TDQ_LOCKPTR ( tdq ) -> lock_object ) ; td -> td_lastcpu = td -> td_oncpu ; td -> td_oncpu = NOCPU ; } KASSERT ( curthread -> td_md . md_spinlock_count == 1 , ( " " ) ) ; newtd = choosethread ( ) ; TDQ_LOCKPTR ( tdq ) -> mtx_lock = ( uintptr_t ) newtd ; cpu_throw ( td , newtd ) ; }
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 and acquire the correct lock. */ /* doesn't return */