Back to index

glibc  2.9
sigreturn.c
Go to the documentation of this file.
00001 /* Return from signal handler for Hurd.  PowerPC version.
00002    Copyright (C) 1996,97,98,2001 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <hurd.h>
00021 #include <hurd/signal.h>
00022 #include <hurd/threadvar.h>
00023 #include <stdlib.h>
00024 
00025 int
00026 __sigreturn (struct sigcontext *scp)
00027 {
00028   struct hurd_sigstate *ss;
00029   mach_port_t *reply_port;
00030 
00031   if (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK))
00032     {
00033       errno = EINVAL;
00034       return -1;
00035     }
00036 
00037   ss = _hurd_self_sigstate ();
00038   __spin_lock (&ss->lock);
00039 
00040   /* Restore the set of blocked signals, and the intr_port slot.  */
00041   ss->blocked = scp->sc_mask;
00042   ss->intr_port = scp->sc_intr_port;
00043 
00044   /* Check for pending signals that were blocked by the old set.  */
00045   if (ss->pending & ~ss->blocked)
00046     {
00047       /* There are pending signals that just became unblocked.  Wake up the
00048         signal thread to deliver them.  But first, squirrel away SCP where
00049         the signal thread will notice it if it runs another handler, and
00050         arrange to have us called over again in the new reality.  */
00051       ss->context = scp;
00052       __spin_unlock (&ss->lock);
00053       __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
00054       /* If a pending signal was handled, sig_post never returned.  */
00055       __spin_lock (&ss->lock);
00056       ss->context = NULL;
00057     }
00058 
00059   if (scp->sc_onstack)
00060     {
00061       ss->sigaltstack.ss_flags &= ~SS_ONSTACK; /* XXX threadvars */
00062       /* XXX cannot unlock until off sigstack */
00063       abort ();
00064     }
00065   else
00066     __spin_unlock (&ss->lock);
00067 
00068   /* Destroy the MiG reply port used by the signal handler, and restore the
00069      reply port in use by the thread when interrupted.  */
00070   reply_port =
00071     (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY);
00072   if (*reply_port)
00073     {
00074       mach_port_t port = *reply_port;
00075 
00076       /* Assigning MACH_PORT_DEAD here tells libc's mig_get_reply_port not to
00077         get another reply port, but avoids mig_dealloc_reply_port trying to
00078         deallocate it after the receive fails (which it will, because the
00079         reply port will be bogus, whether we do this or not).  */
00080       *reply_port = MACH_PORT_DEAD;
00081 
00082       __mach_port_destroy (__mach_task_self (), port);
00083     }
00084   *reply_port = scp->sc_reply_port;
00085 
00086   /* Restore FPU state.  */
00087 #define restore_fpr(n) \
00088   asm volatile ("lfd " #n ",%0(31)" : : "i" (n * 4))
00089 
00090   asm volatile ("mr 31,%0" : : "r" (scp->sc_fprs));
00091 
00092   /* Restore the floating-point control/status register.  */
00093   asm volatile ("lfd 0,256(31)");
00094   asm volatile ("mtfsf 0xff,0");
00095 
00096   /* Restore floating-point registers. */
00097   restore_fpr (0);
00098   restore_fpr (1);
00099   restore_fpr (2);
00100   restore_fpr (3);
00101   restore_fpr (4);
00102   restore_fpr (5);
00103   restore_fpr (6);
00104   restore_fpr (7);
00105   restore_fpr (8);
00106   restore_fpr (9);
00107   restore_fpr (10);
00108   restore_fpr (11);
00109   restore_fpr (12);
00110   restore_fpr (13);
00111   restore_fpr (14);
00112   restore_fpr (15);
00113   restore_fpr (16);
00114   restore_fpr (17);
00115   restore_fpr (18);
00116   restore_fpr (19);
00117   restore_fpr (20);
00118   restore_fpr (21);
00119   restore_fpr (22);
00120   restore_fpr (23);
00121   restore_fpr (24);
00122   restore_fpr (25);
00123   restore_fpr (26);
00124   restore_fpr (27);
00125   restore_fpr (28);
00126   restore_fpr (29);
00127   restore_fpr (30);
00128   restore_fpr (31);
00129 
00130   /* Load all the registers from the sigcontext.  */
00131 #define restore_gpr(n) \
00132   asm volatile ("lwz " #n ",%0(31)" : : "i" (n * 4))
00133 
00134   asm volatile ("addi 31,31,-188");  /* r31 = scp->gprs */
00135 
00136   /* Restore the special purpose registers.  */
00137   asm volatile ("lwz 0,128(31); mtcr 0");
00138   asm volatile ("lwz 0,132(31); mtxer 0");
00139   asm volatile ("lwz 0,136(31); mtlr 0");
00140   asm volatile ("lwz 0,-8(31); mtctr 0");  /* XXX this is the PC */
00141 #if 0
00142   asm volatile ("lwz 0,144(31); mtmq %0");  /* PPC601 only */
00143 #endif
00144 
00145   /* Restore the normal registers.  */
00146   restore_gpr (0);
00147   restore_gpr (1);
00148   restore_gpr (2);
00149   restore_gpr (3);
00150   restore_gpr (4);
00151   restore_gpr (5);
00152   restore_gpr (6);
00153   restore_gpr (7);
00154   restore_gpr (8);
00155   restore_gpr (9);
00156   restore_gpr (10);
00157   restore_gpr (11);
00158   restore_gpr (12);
00159   restore_gpr (13);
00160   restore_gpr (14);
00161   restore_gpr (15);
00162   restore_gpr (16);
00163   restore_gpr (17);
00164   restore_gpr (18);
00165   restore_gpr (19);
00166   restore_gpr (20);
00167   restore_gpr (21);
00168   restore_gpr (22);
00169   restore_gpr (23);
00170   restore_gpr (24);
00171   restore_gpr (25);
00172   restore_gpr (26);
00173   restore_gpr (27);
00174   restore_gpr (28);
00175   restore_gpr (29);
00176   restore_gpr (30);
00177   restore_gpr (31);
00178 
00179   /* Return. */
00180   asm volatile ("bctr");  /* XXX CTR is not restored! */
00181 
00182   /* NOTREACHED */
00183   return -1;
00184 }
00185 
00186 weak_alias (__sigreturn, sigreturn)