int __swapcontext (ucontext_t *oucp, const ucontext_t *ucp) { struct rv rv = __getcontext (oucp); if (rv.first_return) __setcontext (ucp); return 0; }
int __swapcontext (ucontext_t *oucp, const ucontext_t *ucp) { extern void __swapcontext_ret (void); /* Save the current machine context to oucp. */ __getcontext (oucp); /* Modify oucp to skip the __setcontext call on reactivation. */ oucp->uc_mcontext.mc_gregs[MC_PC] = (long) __swapcontext_ret; oucp->uc_mcontext.mc_gregs[MC_NPC] = ((long) __swapcontext_ret) + 4; /* Restore the machine context in ucp. */ __setcontext (ucp, 1); return 0; }
int __swapcontext (ucontext_t *oucp, const ucontext_t *ucp) { /* Save the current machine context to oucp. */ __getcontext (oucp); /* mark sc_sar flag to skip the setcontext call on reactivation. */ if (oucp->uc_mcontext.sc_sar == 0) { oucp->uc_mcontext.sc_sar++; /* Restore the machine context in ucp. */ __setcontext (ucp); } return 0; }
int setcontext(const ucontext_t *ucp) { ulwp_t *self = curthread; int ret; ucontext_t uc; /* * Returning from the main context (uc_link == NULL) causes * the thread to exit. See setcontext(2) and makecontext(3C). */ if (ucp == NULL) thr_exit(NULL); (void) memcpy(&uc, ucp, sizeof (uc)); /* * Restore previous signal mask and context link. */ if (uc.uc_flags & UC_SIGMASK) { block_all_signals(self); delete_reserved_signals(&uc.uc_sigmask); self->ul_sigmask = uc.uc_sigmask; if (self->ul_cursig) { /* * We have a deferred signal present. * The signal mask will be set when the * signal is taken in take_deferred_signal(). */ ASSERT(self->ul_critical + self->ul_sigdefer != 0); uc.uc_flags &= ~UC_SIGMASK; } } self->ul_siglink = uc.uc_link; /* * We don't know where this context structure has been. * Preserve the curthread pointer, at least. * * Allow this feature to be disabled if a particular process * requests it. */ if (setcontext_enforcement) { #if defined(__sparc) uc.uc_mcontext.gregs[REG_G7] = (greg_t)self; #elif defined(__amd64) uc.uc_mcontext.gregs[REG_FS] = (greg_t)0; /* null for fsbase */ #elif defined(__i386) uc.uc_mcontext.gregs[GS] = (greg_t)LWPGS_SEL; #else #error "none of __sparc, __amd64, __i386 defined" #endif } /* * Make sure that if we return to a call to __lwp_park() * or ___lwp_cond_wait() that it returns right away * (giving us a spurious wakeup but not a deadlock). */ set_parking_flag(self, 0); self->ul_sp = 0; ret = __setcontext(&uc); /* * It is OK for setcontext() to return if the user has not specified * UC_CPU. */ if (uc.uc_flags & UC_CPU) thr_panic("setcontext(): __setcontext() returned"); return (ret); }
void sigacthandler(int sig, siginfo_t *sip, void *uvp) { ucontext_t *ucp = uvp; ulwp_t *self = curthread; /* * Do this in case we took a signal while in a cancelable system call. * It does no harm if we were not in such a system call. */ self->ul_sp = 0; if (sig != SIGCANCEL) self->ul_cancel_async = self->ul_save_async; /* * If this thread has performed a longjmp() from a signal handler * back to main level some time in the past, it has left the kernel * thinking that it is still in the signal context. We repair this * possible damage by setting ucp->uc_link to NULL if we know that * we are actually executing at main level (self->ul_siglink == NULL). * See the code for setjmp()/longjmp() for more details. */ if (self->ul_siglink == NULL) ucp->uc_link = NULL; /* * If we are not in a critical region and are * not deferring signals, take the signal now. */ if ((self->ul_critical + self->ul_sigdefer) == 0) { call_user_handler(sig, sip, ucp); /* * On the surface, the following call seems redundant * because call_user_handler() cannot return. However, * we don't want to return from here because the compiler * might recycle our frame. We want to keep it on the * stack to assist debuggers such as pstack in identifying * signal frames. The call to thr_panic() serves to prevent * tail-call optimisation here. */ thr_panic("sigacthandler(): call_user_handler() returned"); } /* * We are in a critical region or we are deferring signals. When * we emerge from the region we will call take_deferred_signal(). */ ASSERT(self->ul_cursig == 0); self->ul_cursig = (char)sig; if (sip != NULL) (void) memcpy(&self->ul_siginfo, sip, sizeof (siginfo_t)); else self->ul_siginfo.si_signo = 0; /* * Make sure that if we return to a call to __lwp_park() * or ___lwp_cond_wait() that it returns right away * (giving us a spurious wakeup but not a deadlock). */ set_parking_flag(self, 0); /* * Return to the previous context with all signals blocked. * We will restore the signal mask in take_deferred_signal(). * Note that we are calling the system call trap here, not * the setcontext() wrapper. We don't want to change the * thread's ul_sigmask by this operation. */ ucp->uc_sigmask = maskset; (void) __setcontext(ucp); thr_panic("sigacthandler(): __setcontext() returned"); }