+--- kernel-2.6.28.orig/arch/arm/include/asm/thread_info.h
++++ kernel-2.6.28/arch/arm/include/asm/thread_info.h
+@@ -138,6 +138,7 @@
+ #define TIF_USING_IWMMXT 17
+ #define TIF_MEMDIE 18
+ #define TIF_FREEZE 19
++#define TIF_RESTORE_SIGMASK 20
+
+ #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
+ #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
+@@ -145,6 +146,7 @@
+ #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
+ #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
+ #define _TIF_FREEZE (1 << TIF_FREEZE)
++#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
+
+ /*
+ * Change these and you break ASM code in entry-common.S
+--- kernel-2.6.28.orig/arch/arm/include/asm/unistd.h
++++ kernel-2.6.28/arch/arm/include/asm/unistd.h
+@@ -360,8 +360,8 @@
+ #define __NR_readlinkat (__NR_SYSCALL_BASE+332)
+ #define __NR_fchmodat (__NR_SYSCALL_BASE+333)
+ #define __NR_faccessat (__NR_SYSCALL_BASE+334)
+- /* 335 for pselect6 */
+- /* 336 for ppoll */
++#define __NR_pselect6 (__NR_SYSCALL_BASE+335)
++#define __NR_ppoll (__NR_SYSCALL_BASE+336)
+ #define __NR_unshare (__NR_SYSCALL_BASE+337)
+ #define __NR_set_robust_list (__NR_SYSCALL_BASE+338)
+ #define __NR_get_robust_list (__NR_SYSCALL_BASE+339)
+@@ -372,7 +372,7 @@
+ #define __NR_vmsplice (__NR_SYSCALL_BASE+343)
+ #define __NR_move_pages (__NR_SYSCALL_BASE+344)
+ #define __NR_getcpu (__NR_SYSCALL_BASE+345)
+- /* 346 for epoll_pwait */
++#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346)
+ #define __NR_kexec_load (__NR_SYSCALL_BASE+347)
+ #define __NR_utimensat (__NR_SYSCALL_BASE+348)
+ #define __NR_signalfd (__NR_SYSCALL_BASE+349)
+@@ -428,6 +428,7 @@
+ #define __ARCH_WANT_SYS_SIGPENDING
+ #define __ARCH_WANT_SYS_SIGPROCMASK
+ #define __ARCH_WANT_SYS_RT_SIGACTION
++#define __ARCH_WANT_SYS_RT_SIGSUSPEND
+
+ #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
+ #define __ARCH_WANT_SYS_TIME
+--- kernel-2.6.28.orig/arch/arm/kernel/calls.S
++++ kernel-2.6.28/arch/arm/kernel/calls.S
+@@ -81,7 +81,7 @@
+ CALL(sys_ni_syscall) /* was sys_ssetmask */
+ /* 70 */ CALL(sys_setreuid16)
+ CALL(sys_setregid16)
+- CALL(sys_sigsuspend_wrapper)
++ CALL(sys_sigsuspend)
+ CALL(sys_sigpending)
+ CALL(sys_sethostname)
+ /* 75 */ CALL(sys_setrlimit)
+@@ -188,7 +188,7 @@
+ CALL(sys_rt_sigpending)
+ CALL(sys_rt_sigtimedwait)
+ CALL(sys_rt_sigqueueinfo)
+- CALL(sys_rt_sigsuspend_wrapper)
++ CALL(sys_rt_sigsuspend)
+ /* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64))
+ CALL(ABI(sys_pwrite64, sys_oabi_pwrite64))
+ CALL(sys_chown16)
+@@ -344,8 +344,8 @@
+ CALL(sys_readlinkat)
+ CALL(sys_fchmodat)
+ CALL(sys_faccessat)
+-/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */
+- CALL(sys_ni_syscall) /* eventually ppoll */
++/* 335 */ CALL(sys_pselect6)
++ CALL(sys_ppoll)
+ CALL(sys_unshare)
+ CALL(sys_set_robust_list)
+ CALL(sys_get_robust_list)
+@@ -355,7 +355,7 @@
+ CALL(sys_vmsplice)
+ CALL(sys_move_pages)
+ /* 345 */ CALL(sys_getcpu)
+- CALL(sys_ni_syscall) /* eventually epoll_pwait */
++ CALL(sys_epoll_pwait)
+ CALL(sys_kexec_load)
+ CALL(sys_utimensat)
+ CALL(sys_signalfd)
+--- kernel-2.6.28.orig/arch/arm/kernel/entry-common.S
++++ kernel-2.6.28/arch/arm/kernel/entry-common.S
+@@ -362,16 +362,6 @@
+ b sys_clone
+ ENDPROC(sys_clone_wrapper)
+
+-sys_sigsuspend_wrapper:
+- add r3, sp, #S_OFF
+- b sys_sigsuspend
+-ENDPROC(sys_sigsuspend_wrapper)
+-
+-sys_rt_sigsuspend_wrapper:
+- add r2, sp, #S_OFF
+- b sys_rt_sigsuspend
+-ENDPROC(sys_rt_sigsuspend_wrapper)
+-
+ sys_sigreturn_wrapper:
+ add r0, sp, #S_OFF
+ b sys_sigreturn
+--- kernel-2.6.28.orig/arch/arm/kernel/signal.c
++++ kernel-2.6.28/arch/arm/kernel/signal.c
+@@ -47,57 +47,22 @@
+ MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
+ };
+
+-static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
+-
+ /*
+ * atomically swap in the new signal mask, and wait for a signal.
+ */
+-asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs)
++asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
+ {
+- sigset_t saveset;
+-
+ mask &= _BLOCKABLE;
+ spin_lock_irq(¤t->sighand->siglock);
+- saveset = current->blocked;
++ current->saved_sigmask = current->blocked;
+ siginitset(¤t->blocked, mask);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+- regs->ARM_r0 = -EINTR;
+-
+- while (1) {
+- current->state = TASK_INTERRUPTIBLE;
+- schedule();
+- if (do_signal(&saveset, regs, 0))
+- return regs->ARM_r0;
+- }
+-}
+-
+-asmlinkage int
+-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
+-{
+- sigset_t saveset, newset;
+-
+- /* 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->ARM_r0 = -EINTR;
+
+- while (1) {
+- current->state = TASK_INTERRUPTIBLE;
+- schedule();
+- if (do_signal(&saveset, regs, 0))
+- return regs->ARM_r0;
+- }
++ current->state = TASK_INTERRUPTIBLE;
++ schedule();
++ set_restore_sigmask();
++ return -ERESTARTNOHAND;
+ }
+
+ asmlinkage int
+@@ -606,7 +571,7 @@
+ /*
+ * OK, we're invoking a handler
+ */
+-static void
++static int
+ handle_signal(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset,
+ struct pt_regs * regs, int syscall)
+@@ -657,7 +622,7 @@
+
+ if (ret != 0) {
+ force_sigsegv(sig, tsk);
+- return;
++ return ret;
+ }
+
+ /*
+@@ -671,6 +636,7 @@
+ recalc_sigpending();
+ spin_unlock_irq(&tsk->sighand->siglock);
+
++ return 0;
+ }
+
+ /*
+@@ -682,7 +648,7 @@
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
+ */
+-static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
++static void do_signal(struct pt_regs *regs, int syscall)
+ {
+ struct k_sigaction ka;
+ siginfo_t info;
+@@ -695,7 +661,7 @@
+ * if so.
+ */
+ if (!user_mode(regs))
+- return 0;
++ return;
+
+ if (try_to_freeze())
+ goto no_signal;
+@@ -704,9 +670,24 @@
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ if (signr > 0) {
+- handle_signal(signr, &ka, &info, oldset, regs, syscall);
++ sigset_t *oldset;
++
++ if (test_thread_flag(TIF_RESTORE_SIGMASK))
++ oldset = ¤t->saved_sigmask;
++ else
++ oldset = ¤t->blocked;
++ if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) {
++ /*
++ * A signal was successfully delivered; the saved
++ * sigmask will have been stored in the signal frame,
++ * and will be restored by sigreturn, so we can simply
++ * clear the TIF_RESTORE_SIGMASK flag.
++ */
++ if (test_thread_flag(TIF_RESTORE_SIGMASK))
++ clear_thread_flag(TIF_RESTORE_SIGMASK);
++ }
+ single_step_set(current);
+- return 1;
++ return;
+ }
+
+ no_signal:
+@@ -758,14 +739,21 @@
+ regs->ARM_r0 == -ERESTARTNOINTR) {
+ restart_syscall(regs);
+ }
++
++ /* If there's no signal to deliver, we just put the saved sigmask
++ * back.
++ */
++ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
++ clear_thread_flag(TIF_RESTORE_SIGMASK);
++ sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
++ }
+ }
+ single_step_set(current);
+- return 0;
+ }
+
+ asmlinkage void
+ do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
+ {
+ if (thread_flags & _TIF_SIGPENDING)
+- do_signal(¤t->blocked, regs, syscall);
++ do_signal(regs, syscall);
+ }