Ejemplo n.º 1
0
int
__swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
{
  struct rv rv = __getcontext (oucp);
  if (rv.first_return)
    __setcontext (ucp);
  return 0;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
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");
}