FreeBSD/sys/kern/subr_trap.c
/*
 * Process an asynchronous software trap.
 * This is relatively easy.
 * This function will return with preemption disabled.
 */
Process an asynchronous software trap.
This is relatively easy.
This function will return with preemption disabled.
Process an asynchronous software trap . This is relatively easy . This function will return with preemption disabled .
void
ast(struct trapframe *framep)
{
	struct thread *td;
	struct proc *p;
	int flags;
	int sig;
	td = curthread;
	p = td->td_proc;
	CTR3(KTR_SYSC, "ast: thread %p (pid %d, %s)", td, p->p_pid,
            p->p_comm);
	KASSERT(TRAPF_USERMODE(framep), ("ast in kernel mode"));
	WITNESS_WARN(WARN_PANIC, NULL, "Returning to user mode");
	mtx_assert(&Giant, MA_NOTOWNED);
	THREAD_LOCK_ASSERT(td, MA_NOTOWNED);
	td->td_frame = framep;
	td->td_pticks = 0;
	thread_lock(td);
	flags = td->td_flags;
	td->td_flags &= ~(TDF_ASTPENDING | TDF_NEEDSIGCHK | TDF_NEEDSUSPCHK |
	    TDF_NEEDRESCHED | TDF_ALRMPEND | TDF_PROFPEND | TDF_MACPEND);
	thread_unlock(td);
	PCPU_INC(cnt.v_trap);
	if (td->td_cowgen != p->p_cowgen)
		thread_cow_update(td);
	if (td->td_pflags & TDP_OWEUPC && p->p_flag & P_PROFIL) {
		addupc_task(td, td->td_profil_addr, td->td_profil_ticks);
		td->td_profil_ticks = 0;
		td->td_pflags &= ~TDP_OWEUPC;
	}
#ifdef HWPMC_HOOKS
	if (PMC_IS_PENDING_CALLCHAIN(td))
		PMC_CALL_HOOK_UNLOCKED(td, PMC_FN_USER_CALLCHAIN_SOFT, (void *) framep);
#endif
	if (flags & TDF_ALRMPEND) {
		PROC_LOCK(p);
		kern_psignal(p, SIGVTALRM);
		PROC_UNLOCK(p);
	}
	if (flags & TDF_PROFPEND) {
		PROC_LOCK(p);
		kern_psignal(p, SIGPROF);
		PROC_UNLOCK(p);
	}
#ifdef MAC
	if (flags & TDF_MACPEND)
		mac_thread_userret(td);
#endif
	if (flags & TDF_NEEDRESCHED) {
#ifdef KTRACE
		if (KTRPOINT(td, KTR_CSW))
			ktrcsw(1, 1, __func__);
#endif
		thread_lock(td);
		sched_prio(td, td->td_user_pri);
		mi_switch(SW_INVOL | SWT_NEEDRESCHED, NULL);
		thread_unlock(td);
#ifdef KTRACE
		if (KTRPOINT(td, KTR_CSW))
			ktrcsw(0, 1, __func__);
#endif
	}
#ifdef DIAGNOSTIC
	if (p->p_numthreads == 1 && (flags & TDF_NEEDSIGCHK) == 0) {
		PROC_LOCK(p);
		thread_lock(td);
		if ((p->p_flag & P_PPWAIT) == 0) {
			KASSERT(!SIGPENDING(td) || (td->td_flags &
			    (TDF_NEEDSIGCHK | TDF_ASTPENDING)) ==
			    (TDF_NEEDSIGCHK | TDF_ASTPENDING),
			    ("failed2 to set signal flags for ast p %p td %p "
			    "fl %x %x", p, td, flags, td->td_flags));
		}
		thread_unlock(td);
		PROC_UNLOCK(p);
	}
#endif
	if (flags & TDF_NEEDSIGCHK || p->p_pendingcnt > 0 ||
	    !SIGISEMPTY(p->p_siglist)) {
		PROC_LOCK(p);
		mtx_lock(&p->p_sigacts->ps_mtx);
		while ((sig = cursig(td)) != 0)
			postsig(sig);
		mtx_unlock(&p->p_sigacts->ps_mtx);
		PROC_UNLOCK(p);
	}
	if (flags & TDF_NEEDSUSPCHK) {
		PROC_LOCK(p);
		thread_suspend_check(0);
		PROC_UNLOCK(p);
	}
	if (td->td_pflags & TDP_OLDMASK) {
		td->td_pflags &= ~TDP_OLDMASK;
		kern_sigprocmask(td, SIG_SETMASK, &td->td_oldsigmask, NULL, 0);
	}
	userret(td, framep);
}
void ast ( struct trapframe * framep ) { struct thread * td ; struct proc * p ; int flags ; int sig ; td = curthread ; p = td -> td_proc ; CTR3 ( KTR_SYSC , " " , td , p -> p_pid , p -> p_comm ) ; KASSERT ( TRAPF_USERMODE ( framep ) , ( " " ) ) ; WITNESS_WARN ( WARN_PANIC , NULL , " " ) ; mtx_assert ( & Giant , MA_NOTOWNED ) ; THREAD_LOCK_ASSERT ( td , MA_NOTOWNED ) ; td -> td_frame = framep ; td -> td_pticks = 0 ; thread_lock ( td ) ; flags = td -> td_flags ; td -> td_flags &= ~ ( TDF_ASTPENDING | TDF_NEEDSIGCHK | TDF_NEEDSUSPCHK | TDF_NEEDRESCHED | TDF_ALRMPEND | TDF_PROFPEND | TDF_MACPEND ) ; thread_unlock ( td ) ; PCPU_INC ( cnt . v_trap ) ; if ( td -> td_cowgen != p -> p_cowgen ) thread_cow_update ( td ) ; if ( td -> td_pflags & TDP_OWEUPC && p -> p_flag & P_PROFIL ) { addupc_task ( td , td -> td_profil_addr , td -> td_profil_ticks ) ; td -> td_profil_ticks = 0 ; td -> td_pflags &= ~ TDP_OWEUPC ; } #ifdef HWPMC_HOOKS if ( PMC_IS_PENDING_CALLCHAIN ( td ) ) PMC_CALL_HOOK_UNLOCKED ( td , PMC_FN_USER_CALLCHAIN_SOFT , ( void * ) framep ) ; #endif if ( flags & TDF_ALRMPEND ) { PROC_LOCK ( p ) ; kern_psignal ( p , SIGVTALRM ) ; PROC_UNLOCK ( p ) ; } if ( flags & TDF_PROFPEND ) { PROC_LOCK ( p ) ; kern_psignal ( p , SIGPROF ) ; PROC_UNLOCK ( p ) ; } #ifdef MAC if ( flags & TDF_MACPEND ) mac_thread_userret ( td ) ; #endif if ( flags & TDF_NEEDRESCHED ) { #ifdef KTRACE if ( KTRPOINT ( td , KTR_CSW ) ) ktrcsw ( 1 , 1 , __func__ ) ; #endif thread_lock ( td ) ; sched_prio ( td , td -> td_user_pri ) ; mi_switch ( SW_INVOL | SWT_NEEDRESCHED , NULL ) ; thread_unlock ( td ) ; #ifdef KTRACE if ( KTRPOINT ( td , KTR_CSW ) ) ktrcsw ( 0 , 1 , __func__ ) ; #endif } #ifdef DIAGNOSTIC if ( p -> p_numthreads == 1 && ( flags & TDF_NEEDSIGCHK ) == 0 ) { PROC_LOCK ( p ) ; thread_lock ( td ) ; if ( ( p -> p_flag & P_PPWAIT ) == 0 ) { KASSERT ( ! SIGPENDING ( td ) || ( td -> td_flags & ( TDF_NEEDSIGCHK | TDF_ASTPENDING ) ) == ( TDF_NEEDSIGCHK | TDF_ASTPENDING ) , ( " " " " , p , td , flags , td -> td_flags ) ) ; } thread_unlock ( td ) ; PROC_UNLOCK ( p ) ; } #endif if ( flags & TDF_NEEDSIGCHK || p -> p_pendingcnt > 0 || ! SIGISEMPTY ( p -> p_siglist ) ) { PROC_LOCK ( p ) ; mtx_lock ( & p -> p_sigacts -> ps_mtx ) ; while ( ( sig = cursig ( td ) ) != 0 ) postsig ( sig ) ; mtx_unlock ( & p -> p_sigacts -> ps_mtx ) ; PROC_UNLOCK ( p ) ; } if ( flags & TDF_NEEDSUSPCHK ) { PROC_LOCK ( p ) ; thread_suspend_check ( 0 ) ; PROC_UNLOCK ( p ) ; } if ( td -> td_pflags & TDP_OLDMASK ) { td -> td_pflags &= ~ TDP_OLDMASK ; kern_sigprocmask ( td , SIG_SETMASK , & td -> td_oldsigmask , NULL , 0 ) ; } userret ( td , framep ) ; }
Process an asynchronous software trap.
Process an asynchronous software trap .
/*
	 * This updates the td_flag's for the checks below in one
	 * "atomic" operation with turning off the astpending flag.
	 * If another AST is triggered while we are handling the
	 * AST's saved in flags, the astpending flag will be set and
	 * ast() will be called again.
	 */ /* Handle Software PMC callchain capture. */ /*
		 * Note that TDF_NEEDSIGCHK should be re-read from
		 * td_flags, since signal might have been delivered
		 * after we cleared td_flags above.  This is one of
		 * the reason for looping check for AST condition.
		 * See comment in userret() about P_PPWAIT.
		 */ /*
	 * Check for signals. Unlocked reads of p_pendingcnt or
	 * p_siglist might cause process-directed signal to be handled
	 * later.
	 */ /*
	 * We need to check to see if we have to exit or wait due to a
	 * single threading requirement or some other STOP condition.
	 */