upgrade to linux 2.6.10-1.12_FC2
[linux-2.6.git] / arch / mips / kernel / signal32.c
index a449a56..12c2104 100644 (file)
 #include <linux/ptrace.h>
 #include <linux/compat.h>
 #include <linux/suspend.h>
+#include <linux/compiler.h>
 
 #include <asm/asm.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
 #include <asm/cacheflush.h>
 #include <asm/sim.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/fpu.h>
 
+#define SI_PAD_SIZE32   ((SI_MAX_SIZE/sizeof(int)) - 3)
+
+typedef union sigval32 {
+       int sival_int;
+       s32 sival_ptr;
+} sigval_t32;
+
+typedef struct siginfo32 {
+       int si_signo;
+       int si_code;
+       int si_errno;
+
+       union {
+               int _pad[SI_PAD_SIZE32];
+
+               /* kill() */
+               struct {
+                       compat_pid_t _pid;      /* sender's pid */
+                       compat_uid_t _uid;      /* sender's uid */
+               } _kill;
+
+               /* SIGCHLD */
+               struct {
+                       compat_pid_t _pid;      /* which child */
+                       compat_uid_t _uid;      /* sender's uid */
+                       int _status;            /* exit code */
+                       compat_clock_t _utime;
+                       compat_clock_t _stime;
+               } _sigchld;
+
+               /* IRIX SIGCHLD */
+               struct {
+                       compat_pid_t _pid;      /* which child */
+                       compat_clock_t _utime;
+                       int _status;            /* exit code */
+                       compat_clock_t _stime;
+               } _irix_sigchld;
+
+               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+               struct {
+                       s32 _addr; /* faulting insn/memory ref. */
+               } _sigfault;
+
+               /* SIGPOLL, SIGXFSZ (To do ...)  */
+               struct {
+                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
+                       int _fd;
+               } _sigpoll;
+
+               /* POSIX.1b timers */
+               struct {
+                       unsigned int _timer1;
+                       unsigned int _timer2;
+               } _timer;
+
+               /* POSIX.1b signals */
+               struct {
+                       compat_pid_t _pid;      /* sender's pid */
+                       compat_uid_t _uid;      /* sender's uid */
+                       sigval_t32 _sigval;
+               } _rt;
+
+       } _sifields;
+} siginfo_t32;
+
 /*
  * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
  */
@@ -127,7 +193,8 @@ static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t *ubuf)
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 save_static_function(sys32_sigsuspend);
-static_unused int _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
+__attribute_used__ noinline static int
+_sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
 {
        compat_sigset_t *uset;
        sigset_t newset, saveset;
@@ -154,7 +221,8 @@ static_unused int _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
 }
 
 save_static_function(sys32_rt_sigsuspend);
-static_unused int _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+__attribute_used__ noinline static int
+_sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
 {
        compat_sigset_t *uset;
        sigset_t newset, saveset;
@@ -295,6 +363,8 @@ static asmlinkage int restore_sigcontext32(struct pt_regs *regs,
 
        err |= __get_user(current->used_math, &sc->sc_used_math);
 
+       preempt_disable();
+
        if (current->used_math) {
                /* restore fpu context if we have used it before */
                own_fpu();
@@ -304,6 +374,8 @@ static asmlinkage int restore_sigcontext32(struct pt_regs *regs,
                lose_fpu();
        }
 
+       preempt_enable();
+
        return err;
 }
 
@@ -489,12 +561,16 @@ static inline int setup_sigcontext32(struct pt_regs *regs,
         * Save FPU state to signal context.  Signal handler will "inherit"
         * current FPU state.
         */
+       preempt_disable();
+
        if (!is_fpu_owner()) {
                own_fpu();
                restore_fp(current);
        }
        err |= save_fp_context32(sc);
 
+       preempt_enable();
+
 out:
        return err;
 }
@@ -649,10 +725,8 @@ give_sigsegv:
 }
 
 static inline void handle_signal(unsigned long sig, siginfo_t *info,
-       sigset_t *oldset, struct pt_regs * regs)
+       struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
 {
-       struct k_sigaction *ka = &current->sighand->action[sig-1];
-
        switch (regs->regs[0]) {
        case ERESTART_RESTARTBLOCK:
        case ERESTARTNOHAND:
@@ -676,8 +750,6 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
        else
                setup_frame(ka, regs, sig, oldset);
 
-       if (ka->sa.sa_flags & SA_ONESHOT)
-               ka->sa.sa_handler = SIG_DFL;
        if (!(ka->sa.sa_flags & SA_NODEFER)) {
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -689,6 +761,7 @@ static inline void handle_signal(unsigned long sig, siginfo_t *info,
 
 asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs)
 {
+       struct k_sigaction ka;
        siginfo_t info;
        int signr;
 
@@ -708,9 +781,9 @@ asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs)
        if (!oldset)
                oldset = &current->blocked;
 
-       signr = get_signal_to_deliver(&info, regs, NULL);
+       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
-               handle_signal(signr, &info, oldset, regs);
+               handle_signal(signr, &info, &ka, oldset, regs);
                return 1;
        }