[PATCH] uml: Move signal handlers to arch code

Have most signals go through an arch-provided handler which recovers the
sigcontext and then calls a generic handler.  This replaces the
ARCH_GET_SIGCONTEXT macro, which was somewhat fragile.  On x86_64, recovering
%rdx (which holds the sigcontext pointer) must be the first thing that
happens.  sig_handler duly invokes that first, but there is no guarantee that
I can see that instructions won't be reordered such that %rdx is used before
that.  Having the arch provide the handler seems much more robust.

Some signals in some parts of UML require their own handlers - these places
don't call set_handler any more.  They call sigaction or signal themselves.

Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Jeff Dike
2006-09-25 23:33:04 -07:00
committed by Linus Torvalds
parent 19bdf0409f
commit 4b84c69b5f
12 changed files with 102 additions and 89 deletions

View File

@ -15,7 +15,6 @@
#include "user.h"
#include "signal_kern.h"
#include "sysdep/sigcontext.h"
#include "sysdep/signal.h"
#include "sigcontext.h"
#include "mode.h"
#include "os.h"
@ -38,18 +37,10 @@
static int signals_enabled = 1;
static int pending = 0;
void sig_handler(ARCH_SIGHDLR_PARAM)
void sig_handler(int sig, struct sigcontext *sc)
{
struct sigcontext *sc;
int enabled;
/* Must be the first thing that this handler does - x86_64 stores
* the sigcontext in %rdx, and we need to save it before it has a
* chance to get trashed.
*/
ARCH_GET_SIGCONTEXT(sc, sig);
enabled = signals_enabled;
if(!enabled && (sig == SIGIO)){
pending |= SIGIO_MASK;
@ -84,13 +75,10 @@ static void real_alarm_handler(int sig, struct sigcontext *sc)
}
void alarm_handler(ARCH_SIGHDLR_PARAM)
void alarm_handler(int sig, struct sigcontext *sc)
{
struct sigcontext *sc;
int enabled;
ARCH_GET_SIGCONTEXT(sc, sig);
enabled = signals_enabled;
if(!signals_enabled){
if(sig == SIGVTALRM)
@ -126,6 +114,10 @@ void remove_sigstack(void)
panic("disabling signal stack failed, errno = %d\n", errno);
}
void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
extern void hard_handler(int sig);
void set_handler(int sig, void (*handler)(int), int flags, ...)
{
struct sigaction action;
@ -133,13 +125,16 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
sigset_t sig_mask;
int mask;
va_start(ap, flags);
action.sa_handler = handler;
handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
action.sa_handler = hard_handler;
sigemptyset(&action.sa_mask);
while((mask = va_arg(ap, int)) != -1){
va_start(ap, flags);
while((mask = va_arg(ap, int)) != -1)
sigaddset(&action.sa_mask, mask);
}
va_end(ap);
action.sa_flags = flags;
action.sa_restorer = NULL;
if(sigaction(sig, &action, NULL) < 0)