/* * Handle signals, upcalls, profiling, and other AST's and/or tasks that * must be completed before we can return to or try to return to userland. * * Note that td_sticks is a 64 bit quantity, but there's no point doing 64 * arithmatic on the delta calculation so the absolute tick values are * truncated to an integer. */ static void userret(struct lwp *lp, struct trapframe *frame, int sticks) { struct proc *p = lp->lwp_proc; int sig; int ptok; /* * Charge system time if profiling. Note: times are in microseconds. * This may do a copyout and block, so do it first even though it * means some system time will be charged as user time. */ if (p->p_flags & P_PROFIL) { addupc_task(p, frame->tf_rip, (u_int)((int)lp->lwp_thread->td_sticks - sticks)); } recheck: /* * Specific on-return-to-usermode checks (LWP_MP_WEXIT, * LWP_MP_VNLRU, etc). */ if (lp->lwp_mpflags & LWP_MP_URETMASK) lwpuserret(lp); /* * Block here if we are in a stopped state. */ if (STOPLWP(p, lp)) { lwkt_gettoken(&p->p_token); tstop(); lwkt_reltoken(&p->p_token); goto recheck; } while (dump_stop_usertds) { tsleep(&dump_stop_usertds, 0, "dumpstp", 0); } /* * Post any pending upcalls. If running a virtual kernel be sure * to restore the virtual kernel's vmspace before posting the upcall. */ if (p->p_flags & (P_SIGVTALRM | P_SIGPROF)) { lwkt_gettoken(&p->p_token); if (p->p_flags & P_SIGVTALRM) { p->p_flags &= ~P_SIGVTALRM; ksignal(p, SIGVTALRM); } if (p->p_flags & P_SIGPROF) { p->p_flags &= ~P_SIGPROF; ksignal(p, SIGPROF); } lwkt_reltoken(&p->p_token); goto recheck; } /* * Post any pending signals. If running a virtual kernel be sure * to restore the virtual kernel's vmspace before posting the signal. * * WARNING! postsig() can exit and not return. */ if ((sig = CURSIG_LCK_TRACE(lp, &ptok)) != 0) { postsig(sig, ptok); goto recheck; } /* * block here if we are swapped out, but still process signals * (such as SIGKILL). proc0 (the swapin scheduler) is already * aware of our situation, we do not have to wake it up. */ if (p->p_flags & P_SWAPPEDOUT) { lwkt_gettoken(&p->p_token); p->p_flags |= P_SWAPWAIT; swapin_request(); if (p->p_flags & P_SWAPWAIT) tsleep(p, PCATCH, "SWOUT", 0); p->p_flags &= ~P_SWAPWAIT; lwkt_reltoken(&p->p_token); goto recheck; } /* * In a multi-threaded program it is possible for a thread to change * signal state during a system call which temporarily changes the * signal mask. In this case postsig() might not be run and we * have to restore the mask ourselves. */ if (lp->lwp_flags & LWP_OLDMASK) { lp->lwp_flags &= ~LWP_OLDMASK; lp->lwp_sigmask = lp->lwp_oldsigmask; goto recheck; } }
/* * Handle signals, upcalls, profiling, and other AST's and/or tasks that * must be completed before we can return to or try to return to userland. * * Note that td_sticks is a 64 bit quantity, but there's no point doing 64 * arithmatic on the delta calculation so the absolute tick values are * truncated to an integer. */ static void userret(struct lwp *lp, struct trapframe *frame, int sticks) { struct proc *p = lp->lwp_proc; void (*hook)(void); int sig; if (p->p_userret != NULL) { hook = p->p_userret; p->p_userret = NULL; (*hook)(); } /* * Charge system time if profiling. Note: times are in microseconds. * This may do a copyout and block, so do it first even though it * means some system time will be charged as user time. */ if (p->p_flags & P_PROFIL) { addupc_task(p, frame->tf_eip, (u_int)((int)lp->lwp_thread->td_sticks - sticks)); } recheck: /* * If the jungle wants us dead, so be it. */ if (lp->lwp_mpflags & LWP_MP_WEXIT) { lwkt_gettoken(&p->p_token); lwp_exit(0); lwkt_reltoken(&p->p_token); /* NOT REACHED */ } /* * Block here if we are in a stopped state. */ if (p->p_stat == SSTOP || dump_stop_usertds) { lwkt_gettoken(&p->p_token); tstop(); lwkt_reltoken(&p->p_token); goto recheck; } /* * Post any pending upcalls. If running a virtual kernel be sure * to restore the virtual kernel's vmspace before posting the upcall. */ if (p->p_flags & (P_SIGVTALRM | P_SIGPROF | P_UPCALLPEND)) { lwkt_gettoken(&p->p_token); if (p->p_flags & P_SIGVTALRM) { p->p_flags &= ~P_SIGVTALRM; ksignal(p, SIGVTALRM); } if (p->p_flags & P_SIGPROF) { p->p_flags &= ~P_SIGPROF; ksignal(p, SIGPROF); } if (p->p_flags & P_UPCALLPEND) { p->p_flags &= ~P_UPCALLPEND; postupcall(lp); } lwkt_reltoken(&p->p_token); goto recheck; } /* * Post any pending signals. If running a virtual kernel be sure * to restore the virtual kernel's vmspace before posting the signal. * * WARNING! postsig() can exit and not return. */ if ((sig = CURSIG_TRACE(lp)) != 0) { lwkt_gettoken(&p->p_token); postsig(sig); lwkt_reltoken(&p->p_token); goto recheck; } /* * block here if we are swapped out, but still process signals * (such as SIGKILL). proc0 (the swapin scheduler) is already * aware of our situation, we do not have to wake it up. */ if (p->p_flags & P_SWAPPEDOUT) { lwkt_gettoken(&p->p_token); get_mplock(); p->p_flags |= P_SWAPWAIT; swapin_request(); if (p->p_flags & P_SWAPWAIT) tsleep(p, PCATCH, "SWOUT", 0); p->p_flags &= ~P_SWAPWAIT; rel_mplock(); lwkt_reltoken(&p->p_token); goto recheck; } /* * In a multi-threaded program it is possible for a thread to change * signal state during a system call which temporarily changes the * signal mask. In this case postsig() might not be run and we * have to restore the mask ourselves. */ if (lp->lwp_flags & LWP_OLDMASK) { lp->lwp_flags &= ~LWP_OLDMASK; lp->lwp_sigmask = lp->lwp_oldsigmask; goto recheck; } }