FreeBSD/sys/kern/subr_trap.c
/*
 * Define the code needed before returning to user mode, for trap and
 * syscall.
 */
Define the code needed before returning to user mode, for trap and
syscall.
Define the code needed before returning to user mode for trap and syscall .
void
userret(struct thread *td, struct trapframe *frame)
{
	struct proc *p = td->td_proc;
	CTR3(KTR_SYSC, "userret: thread %p (pid %d, %s)", td, p->p_pid,
            td->td_name);
	KASSERT((p->p_flag & P_WEXIT) == 0,
	    ("Exiting process returns to usermode"));
#ifdef DIAGNOSTIC
	if (p->p_numthreads == 1) {
		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),
			    ("failed to set signal flags for ast p %p "
			    "td %p fl %x", p, td, td->td_flags));
		}
		thread_unlock(td);
		PROC_UNLOCK(p);
	}
#endif
#ifdef KTRACE
	KTRUSERRET(td);
#endif
	if (softdep_ast_cleanup != NULL)
		softdep_ast_cleanup();
	if (td->td_pflags & TDP_GEOM)
		g_waitidle();
	if (p->p_flag & P_PROFIL)
		addupc_task(td, TRAPF_PC(frame), td->td_pticks * psratio);
	sched_userret(td);
	WITNESS_WARN(WARN_PANIC, NULL, "userret: returning");
	KASSERT(td->td_critnest == 0,
	    ("userret: Returning in a critical section"));
	KASSERT(td->td_locks == 0,
	    ("userret: Returning with %d locks held", td->td_locks));
	KASSERT(td->td_rw_rlocks == 0,
	    ("userret: Returning with %d rwlocks held in read mode",
	    td->td_rw_rlocks));
	KASSERT((td->td_pflags & TDP_NOFAULTING) == 0,
	    ("userret: Returning with pagefaults disabled"));
	KASSERT(td->td_no_sleeping == 0,
	    ("userret: Returning with sleep disabled"));
	KASSERT(td->td_pinned == 0 || (td->td_pflags & TDP_CALLCHAIN) != 0,
	    ("userret: Returning with with pinned thread"));
	KASSERT(td->td_vp_reserv == 0,
	    ("userret: Returning while holding vnode reservation"));
	KASSERT((td->td_flags & (TDF_SBDRY | TDF_SEINTR | TDF_SERESTART)) == 0,
	    ("userret: Returning with stop signals deferred"));
	KASSERT(td->td_su == NULL,
	    ("userret: Returning with SU cleanup request not handled"));
#ifdef VIMAGE
	VNET_ASSERT(curvnet == NULL,
	    ("%s: Returning on td %p (pid %d, %s) with vnet %p set in %s",
	    __func__, td, p->p_pid, td->td_name, curvnet,
	    (td->td_vnet_lpush != NULL) ? td->td_vnet_lpush : "N/A"));
#endif
#ifdef RACCT
	if (racct_enable && p->p_throttled != 0) {
		PROC_LOCK(p);
		while (p->p_throttled != 0) {
			msleep(p->p_racct, &p->p_mtx, 0, "racct",
			    p->p_throttled < 0 ? 0 : p->p_throttled);
			if (p->p_throttled > 0)
				p->p_throttled = 0;
		}
		PROC_UNLOCK(p);
	}
#endif
}
void userret ( struct thread * td , struct trapframe * frame ) { struct proc * p = td -> td_proc ; CTR3 ( KTR_SYSC , " " , td , p -> p_pid , td -> td_name ) ; KASSERT ( ( p -> p_flag & P_WEXIT ) == 0 , ( " " ) ) ; #ifdef DIAGNOSTIC if ( p -> p_numthreads == 1 ) { 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 , td -> td_flags ) ) ; } thread_unlock ( td ) ; PROC_UNLOCK ( p ) ; } #endif #ifdef KTRACE KTRUSERRET ( td ) ; #endif if ( softdep_ast_cleanup != NULL ) softdep_ast_cleanup ( ) ; if ( td -> td_pflags & TDP_GEOM ) g_waitidle ( ) ; if ( p -> p_flag & P_PROFIL ) addupc_task ( td , TRAPF_PC ( frame ) , td -> td_pticks * psratio ) ; sched_userret ( td ) ; WITNESS_WARN ( WARN_PANIC , NULL , " " ) ; KASSERT ( td -> td_critnest == 0 , ( " " ) ) ; KASSERT ( td -> td_locks == 0 , ( " " , td -> td_locks ) ) ; KASSERT ( td -> td_rw_rlocks == 0 , ( " " , td -> td_rw_rlocks ) ) ; KASSERT ( ( td -> td_pflags & TDP_NOFAULTING ) == 0 , ( " " ) ) ; KASSERT ( td -> td_no_sleeping == 0 , ( " " ) ) ; KASSERT ( td -> td_pinned == 0 || ( td -> td_pflags & TDP_CALLCHAIN ) != 0 , ( " " ) ) ; KASSERT ( td -> td_vp_reserv == 0 , ( " " ) ) ; KASSERT ( ( td -> td_flags & ( TDF_SBDRY | TDF_SEINTR | TDF_SERESTART ) ) == 0 , ( " " ) ) ; KASSERT ( td -> td_su == NULL , ( " " ) ) ; #ifdef VIMAGE VNET_ASSERT ( curvnet == NULL , ( " " , __func__ , td , p -> p_pid , td -> td_name , curvnet , ( td -> td_vnet_lpush != NULL ) ? td -> td_vnet_lpush : " " ) ) ; #endif #ifdef RACCT if ( racct_enable && p -> p_throttled != 0 ) { PROC_LOCK ( p ) ; while ( p -> p_throttled != 0 ) { msleep ( p -> p_racct , & p -> p_mtx , 0 , " " , p -> p_throttled < 0 ? 0 : p -> p_throttled ) ; if ( p -> p_throttled > 0 ) p -> p_throttled = 0 ; } PROC_UNLOCK ( p ) ; } #endif }
Define the code needed before returning to user mode, for trap and
 syscall.
Define the code needed before returning to user mode for trap and syscall .
/*
	 * Check that we called signotify() enough.  For
	 * multi-threaded processes, where signal distribution might
	 * change due to other threads changing sigmask, the check is
	 * racy and cannot be performed reliably.
	 * If current process is vfork child, indicated by P_PPWAIT, then
	 * issignal() ignores stops, so we block the check to avoid
	 * classifying pending signals.
	 */ /*
	 * If this thread tickled GEOM, we need to wait for the giggling to
	 * stop before we return to userland
	 */ /*
	 * Charge system time if profiling.
	 */ /*
	 * Let the scheduler adjust our priority etc.
	 */ /*
	 * Check for misbehavior.
	 *
	 * In case there is a callchain tracing ongoing because of
	 * hwpmc(4), skip the scheduler pinning check.
	 * hwpmc(4) subsystem, infact, will collect callchain informations
	 * at ast() checkpoint, which is past userret().
	 */ /* Unfortunately td_vnet_lpush needs VNET_DEBUG. */