(__sigreturn): Arg is not const.

After restoring SCP->sc_mask, check for pending signals (newly unblocked);
if any, set SS->context to SCP, clear SS->intr_port, and send sig_post
to the signal thread to deliver the pending signals.
Don't write $1 value into the user stack.  Instead, write it into the word
just past SCP->sc_pc; then point $1 at SCP->sc_pc and use `op_sigreturn'
pseudo-instruction to restore the PC and $1 from that.
This commit is contained in:
Roland McGrath 1994-08-22 09:06:46 +00:00
parent 62833ce689
commit 92ae11d456

View File

@ -19,45 +19,75 @@ Cambridge, MA 02139, USA. */
#include <hurd.h>
#include <hurd/signal.h>
#include <hurd/threadvar.h>
#include <stdlib.h>
int
__sigreturn (const struct sigcontext *scp)
__sigreturn (struct sigcontext *scp)
{
struct hurd_sigstate *ss;
mach_port_t *reply_port;
if (scp == NULL)
if (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK))
{
errno = EINVAL;
return -1;
}
ss = _hurd_self_sigstate ();
ss = _hurd_self_sigstate (); /* SS->lock now locked. */
/* Restore the set of blocked signals, and the intr_port slot. */
ss->blocked = scp->sc_mask;
ss->intr_port = scp->sc_intr_port;
/* Check for pending signals that were blocked by the old set. */
if (ss->pending & ~ss->blocked)
{
/* There are pending signals that just became unblocked. Wake up the
signal thread to deliver them. But first, squirrel away SCP where
the signal thread will notice it if it runs another handler, and
arrange to have us called over again in the new reality. */
ss->context = scp;
/* Clear the intr_port slot, since we are not in fact doing
an interruptible RPC right now. If SS->intr_port is not null,
the SCP context is doing an interruptible RPC, but the signal
thread will examine us while we are blocked in the sig_post RPC. */
ss->intr_port = MACH_PORT_NULL;
__mutex_unlock (&ss->lock);
__sig_post (_hurd_msgport, 0, __mach_task_self ());
/* If a pending signal was handled, sig_post never returned. */
__mutex_lock (&ss->lock);
}
if (scp->sc_onstack)
ss->sigaltstack.ss_flags &= ~SA_ONSTACK; /* XXX threadvars */
__mutex_unlock (&ss->lock);
{
ss->sigaltstack.ss_flags &= ~SA_ONSTACK; /* XXX threadvars */
/* XXX cannot unlock until off sigstack */
abort ();
}
else
__mutex_unlock (&ss->lock);
/* Destroy the MiG reply port used by the signal handler, and restore the
reply port in use by the thread when interrupted. */
reply_port =
(mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY);
if (*reply_port != MACH_PORT_NULL)
if (*reply_port)
__mach_port_destroy (__mach_task_self (), *reply_port);
*reply_port = scp->sc_reply_port;
if (scp->sc_coproc_used & SC_COPROC_USE_FPU)
{
/* XXX should restore FPU state here */
abort ();
}
/* Load all the registers from the sigcontext. */
#define restore_gpr(n) \
asm volatile ("lw $" #n ",%0" : : "m" (scpreg->sc_gpr[n - 1]))
{
register const struct sigcontext *const scpreg asm ("$1") = scp;
/* Just beyond the top of the user stack, store the user's value for $1
(which we are using for SCPREG). We restore this register as the
very last thing, below. */
((int *) scpreg->sc_gpr[29 - 1])[-1] = scpreg->sc_gpr[0];
register int *at asm ("$1");
/* First restore the multiplication result registers. The compiler
will use some temporary registers, so we do this before restoring
@ -65,6 +95,9 @@ __sigreturn (const struct sigcontext *scp)
asm volatile ("mtlo %0" : : "r" (scpreg->sc_mdlo));
asm volatile ("mthi %0" : : "r" (scpreg->sc_mdhi));
/* In the word after the saved PC, store the saved $1 value. */
(&scpreg->sc_pc)[1] = scpreg->sc_gpr[0];
asm volatile (".set noreorder; .set noat;");
/* Restore the normal registers. */
@ -98,11 +131,10 @@ __sigreturn (const struct sigcontext *scp)
restore_gpr (30); /* Frame pointer. */
restore_gpr (31); /* Return address. */
/* Now jump to the saved PC. */
asm volatile ("lw $1, %0\n" /* Load saved PC into $1. */
"j $1\n" /* Jump to the saved PC value. */
"lw $1, -4(sp)\n" /* Restore $1 from stack in delay slot. */
: : "m" (scpreg->sc_pc));
at = &scpreg->sc_pc;
/* This is an emulated instruction that will find at the address in $1
two words: the PC value to restore, and the $1 value to restore. */
asm volatile (".word op_sigreturn");
asm volatile (".set reorder; .set at;");
}