LDREG   TI_FLAGS(%r1),%r19      /* sched.h: TIF_NEED_RESCHED */
        bb,<,n  %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
 
+       .import do_notify_resume,code
 intr_check_sig:
        /* As above */
        mfctl   %cr30,%r1
-       LDREG   TI_FLAGS(%r1),%r19      /* sched.h: TIF_SIGPENDING */
-       bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */
+       LDREG   TI_FLAGS(%r1),%r19
+       load32  (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r20
+       and,COND(<>)    %r19, %r20, %r0
+       b,n     intr_restore    /* skip past if we've nothing to do */
+
+       /* This check is critical to having LWS
+        * working. The IASQ is zero on the gateway
+        * page and we cannot deliver any signals until
+        * we get off the gateway page.
+        *
+        * Only do signals if we are returning to user space
+        */
+       LDREG   PT_IASQ0(%r16), %r20
+       CMPIB= 0,%r20,intr_restore /* backward */
+       nop
+       LDREG   PT_IASQ1(%r16), %r20
+       CMPIB= 0,%r20,intr_restore /* backward */
+       nop
+
+       copy    %r0, %r25                       /* long in_syscall = 0 */
+#ifdef CONFIG_64BIT
+       ldo     -16(%r30),%r29                  /* Reference param save area */
+#endif
+
+       BL      do_notify_resume,%r2
+       copy    %r16, %r26                      /* struct pt_regs *regs */
+
+       b       intr_check_sig
+       nop
 
 intr_restore:
        copy            %r16,%r29
        b,n     intr_restore            /* ssm PSW_SM_I done by intr_restore */
 #endif /* CONFIG_PREEMPT */
 
-       .import do_signal,code
-intr_do_signal:
-       /* 
-               This check is critical to having LWS
-               working. The IASQ is zero on the gateway
-               page and we cannot deliver any signals until
-               we get off the gateway page.
-
-               Only do signals if we are returning to user space 
-       */
-       LDREG   PT_IASQ0(%r16), %r20
-       CMPIB= 0,%r20,intr_restore /* backward */
-       nop
-       LDREG   PT_IASQ1(%r16), %r20
-       CMPIB= 0,%r20,intr_restore /* backward */
-       nop
-
-       copy    %r0, %r24                       /* unsigned long in_syscall */
-       copy    %r16, %r25                      /* struct pt_regs *regs */
-#ifdef CONFIG_64BIT
-       ldo     -16(%r30),%r29                  /* Reference param save area */
-#endif
-
-       BL      do_signal,%r2
-       copy    %r0, %r26                       /* sigset_t *oldset = NULL */
-
-       b       intr_check_sig
-       nop
-
        /*
         * External interrupts.
         */
        nop
 #endif
 
-       .export sys_rt_sigsuspend_wrapper
-sys_rt_sigsuspend_wrapper:
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
-       ldo     TASK_REGS(%r1),%r24
-       reg_save %r24
-
-       STREG   %r2, -RP_OFFSET(%r30)
-#ifdef CONFIG_64BIT
-       ldo     FRAME_SIZE(%r30), %r30
-       BL      sys_rt_sigsuspend,%r2
-       ldo     -16(%r30),%r29          /* Reference param save area */
-#else
-       BL      sys_rt_sigsuspend,%r2
-       ldo     FRAME_SIZE(%r30), %r30
-#endif
-
-       ldo     -FRAME_SIZE(%r30), %r30
-       LDREG   -RP_OFFSET(%r30), %r2
-
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
-       ldo     TASK_REGS(%r1),%r1
-       reg_restore %r1
-
-       bv      %r0(%r2)
-       nop
-
        .export syscall_exit
 syscall_exit:
 
        LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19   /* long */
        bb,<,n  %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */
 
+       .import do_signal,code
 syscall_check_sig:
-       LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19    /* get ti flags */
-       bb,<,n  %r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */
+       LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19
+       load32  (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r26
+       and,COND(<>)    %r19, %r26, %r0
+       b,n     syscall_restore /* skip past if we've nothing to do */
+
+syscall_do_signal:
+       /* Save callee-save registers (for sigcontext).
+        * FIXME: After this point the process structure should be
+        * consistent with all the relevant state of the process
+        * before the syscall.  We need to verify this.
+        */
+       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+       ldo     TASK_REGS(%r1), %r26            /* struct pt_regs *regs */
+       reg_save %r26
+
+#ifdef CONFIG_64BIT
+       ldo     -16(%r30),%r29                  /* Reference param save area */
+#endif
+
+       BL      do_notify_resume,%r2
+       ldi     1, %r25                         /* long in_syscall = 1 */
+
+       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+       ldo     TASK_REGS(%r1), %r20            /* reload pt_regs */
+       reg_restore %r20
+
+       b,n     syscall_check_sig
 
 syscall_restore:
        /* Are we being ptraced? */
        b       syscall_check_bh  /* if resched, we start over again */
        nop
 
-       .import do_signal,code
-syscall_do_signal:
-       /* Save callee-save registers (for sigcontext).
-          FIXME: After this point the process structure should be
-          consistent with all the relevant state of the process
-          before the syscall.  We need to verify this. */
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 
-       ldo     TASK_REGS(%r1), %r25            /* struct pt_regs *regs */
-       reg_save %r25
-
-       ldi     1, %r24                         /* unsigned long in_syscall */
-
-#ifdef CONFIG_64BIT
-       ldo     -16(%r30),%r29                  /* Reference param save area */
-#endif
-       BL      do_signal,%r2
-       copy    %r0, %r26                       /* sigset_t *oldset = NULL */
-
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
-       ldo     TASK_REGS(%r1), %r20            /* reload pt_regs */
-       reg_restore %r20
-
-       b,n     syscall_check_sig
-
        /*
         * get_register is used by the non access tlb miss handlers to
         * copy the value of the general register specified in r8 into
 
  * this. */
 #define A(__x) ((unsigned long)(__x))
 
-int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 #include "sys32.h"
 #endif
 
-asmlinkage int
-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
-{
-       sigset_t saveset, newset;
-#ifdef __LP64__
-       compat_sigset_t newset32;
-
-       if (is_compat_task()) {
-               /* XXX: Don't preclude handling different sized sigset_t's.  */
-               if (sigsetsize != sizeof(compat_sigset_t))
-                       return -EINVAL;
-               if (copy_from_user(&newset32, (compat_sigset_t __user *)unewset, sizeof(newset32)))
-                       return -EFAULT;
-               sigset_32to64(&newset,&newset32);
-               
-       } else 
-#endif
-       {
-               /* XXX: Don't preclude handling different sized sigset_t's.  */
-               if (sigsetsize != sizeof(sigset_t))
-                       return -EINVAL;
-       
-               if (copy_from_user(&newset, unewset, sizeof(newset)))
-                       return -EFAULT;
-       }
-
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-
-       spin_lock_irq(¤t->sighand->siglock);
-       saveset = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(¤t->sighand->siglock);
-
-       regs->gr[28] = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(&saveset, regs, 1))
-                       return -EINTR;
-       }
-}
-
 /*
  * Do a signal return - restore sigcontext.
  */
  * us due to the magic of delayed branching.
  */
 
-asmlinkage int
-do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
+asmlinkage void
+do_signal(struct pt_regs *regs, long in_syscall)
 {
        siginfo_t info;
        struct k_sigaction ka;
        int signr;
+       sigset_t *oldset;
 
        DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
               oldset, regs, regs->sr[7], in_syscall);
           we would be called in that case, but for some reason we
           are. */
 
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = ¤t->saved_sigmask;
+       else
                oldset = ¤t->blocked;
 
        DBG(1,"do_signal: oldset %08lx / %08lx\n", 
                if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) {
                        DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
                                regs->gr[28]);
-                       return 1;
+                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+                       return;
                }
        }
        /* end of while(1) looping forever if we can't force a signal */
        DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", 
                regs->gr[28]);
 
-       return 0;
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
+       }
+
+       return;
+}
+
+void do_notify_resume(struct pt_regs *regs, long in_syscall)
+{
+       if (test_thread_flag(TIF_SIGPENDING) ||
+           test_thread_flag(TIF_RESTORE_SIGMASK))
+               do_signal(regs, in_syscall);
 }