1 --- kernel-2.6.28.orig/arch/arm/include/asm/thread_info.h
2 +++ kernel-2.6.28/arch/arm/include/asm/thread_info.h
4 #define TIF_USING_IWMMXT 17
7 +#define TIF_RESTORE_SIGMASK 20
9 #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
10 #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
12 #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
13 #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
14 #define _TIF_FREEZE (1 << TIF_FREEZE)
15 +#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
18 * Change these and you break ASM code in entry-common.S
19 --- kernel-2.6.28.orig/arch/arm/include/asm/unistd.h
20 +++ kernel-2.6.28/arch/arm/include/asm/unistd.h
22 #define __NR_readlinkat (__NR_SYSCALL_BASE+332)
23 #define __NR_fchmodat (__NR_SYSCALL_BASE+333)
24 #define __NR_faccessat (__NR_SYSCALL_BASE+334)
25 - /* 335 for pselect6 */
27 +#define __NR_pselect6 (__NR_SYSCALL_BASE+335)
28 +#define __NR_ppoll (__NR_SYSCALL_BASE+336)
29 #define __NR_unshare (__NR_SYSCALL_BASE+337)
30 #define __NR_set_robust_list (__NR_SYSCALL_BASE+338)
31 #define __NR_get_robust_list (__NR_SYSCALL_BASE+339)
33 #define __NR_vmsplice (__NR_SYSCALL_BASE+343)
34 #define __NR_move_pages (__NR_SYSCALL_BASE+344)
35 #define __NR_getcpu (__NR_SYSCALL_BASE+345)
36 - /* 346 for epoll_pwait */
37 +#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346)
38 #define __NR_kexec_load (__NR_SYSCALL_BASE+347)
39 #define __NR_utimensat (__NR_SYSCALL_BASE+348)
40 #define __NR_signalfd (__NR_SYSCALL_BASE+349)
42 #define __ARCH_WANT_SYS_SIGPENDING
43 #define __ARCH_WANT_SYS_SIGPROCMASK
44 #define __ARCH_WANT_SYS_RT_SIGACTION
45 +#define __ARCH_WANT_SYS_RT_SIGSUSPEND
47 #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
48 #define __ARCH_WANT_SYS_TIME
49 --- kernel-2.6.28.orig/arch/arm/kernel/calls.S
50 +++ kernel-2.6.28/arch/arm/kernel/calls.S
52 CALL(sys_ni_syscall) /* was sys_ssetmask */
53 /* 70 */ CALL(sys_setreuid16)
55 - CALL(sys_sigsuspend_wrapper)
56 + CALL(sys_sigsuspend)
59 /* 75 */ CALL(sys_setrlimit)
61 CALL(sys_rt_sigpending)
62 CALL(sys_rt_sigtimedwait)
63 CALL(sys_rt_sigqueueinfo)
64 - CALL(sys_rt_sigsuspend_wrapper)
65 + CALL(sys_rt_sigsuspend)
66 /* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64))
67 CALL(ABI(sys_pwrite64, sys_oabi_pwrite64))
73 -/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */
74 - CALL(sys_ni_syscall) /* eventually ppoll */
75 +/* 335 */ CALL(sys_pselect6)
78 CALL(sys_set_robust_list)
79 CALL(sys_get_robust_list)
83 /* 345 */ CALL(sys_getcpu)
84 - CALL(sys_ni_syscall) /* eventually epoll_pwait */
85 + CALL(sys_epoll_pwait)
89 --- kernel-2.6.28.orig/arch/arm/kernel/entry-common.S
90 +++ kernel-2.6.28/arch/arm/kernel/entry-common.S
93 ENDPROC(sys_clone_wrapper)
95 -sys_sigsuspend_wrapper:
98 -ENDPROC(sys_sigsuspend_wrapper)
100 -sys_rt_sigsuspend_wrapper:
102 - b sys_rt_sigsuspend
103 -ENDPROC(sys_rt_sigsuspend_wrapper)
105 sys_sigreturn_wrapper:
108 --- kernel-2.6.28.orig/arch/arm/kernel/signal.c
109 +++ kernel-2.6.28/arch/arm/kernel/signal.c
111 MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
114 -static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
117 * atomically swap in the new signal mask, and wait for a signal.
119 -asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs)
120 +asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
125 spin_lock_irq(¤t->sighand->siglock);
126 - saveset = current->blocked;
127 + current->saved_sigmask = current->blocked;
128 siginitset(¤t->blocked, mask);
130 spin_unlock_irq(¤t->sighand->siglock);
131 - regs->ARM_r0 = -EINTR;
134 - current->state = TASK_INTERRUPTIBLE;
136 - if (do_signal(&saveset, regs, 0))
137 - return regs->ARM_r0;
142 -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
144 - sigset_t saveset, newset;
146 - /* XXX: Don't preclude handling different sized sigset_t's. */
147 - if (sigsetsize != sizeof(sigset_t))
150 - if (copy_from_user(&newset, unewset, sizeof(newset)))
152 - sigdelsetmask(&newset, ~_BLOCKABLE);
154 - spin_lock_irq(¤t->sighand->siglock);
155 - saveset = current->blocked;
156 - current->blocked = newset;
157 - recalc_sigpending();
158 - spin_unlock_irq(¤t->sighand->siglock);
159 - regs->ARM_r0 = -EINTR;
162 - current->state = TASK_INTERRUPTIBLE;
164 - if (do_signal(&saveset, regs, 0))
165 - return regs->ARM_r0;
167 + current->state = TASK_INTERRUPTIBLE;
169 + set_restore_sigmask();
170 + return -ERESTARTNOHAND;
176 * OK, we're invoking a handler
180 handle_signal(unsigned long sig, struct k_sigaction *ka,
181 siginfo_t *info, sigset_t *oldset,
182 struct pt_regs * regs, int syscall)
186 force_sigsegv(sig, tsk);
194 spin_unlock_irq(&tsk->sighand->siglock);
201 * the kernel can handle, and then we build all the user-level signal handling
202 * stack-frames in one go after that.
204 -static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
205 +static void do_signal(struct pt_regs *regs, int syscall)
207 struct k_sigaction ka;
212 if (!user_mode(regs))
220 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
222 - handle_signal(signr, &ka, &info, oldset, regs, syscall);
225 + if (test_thread_flag(TIF_RESTORE_SIGMASK))
226 + oldset = ¤t->saved_sigmask;
228 + oldset = ¤t->blocked;
229 + if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) {
231 + * A signal was successfully delivered; the saved
232 + * sigmask will have been stored in the signal frame,
233 + * and will be restored by sigreturn, so we can simply
234 + * clear the TIF_RESTORE_SIGMASK flag.
236 + if (test_thread_flag(TIF_RESTORE_SIGMASK))
237 + clear_thread_flag(TIF_RESTORE_SIGMASK);
239 single_step_set(current);
245 @@ -758,14 +739,21 @@
246 regs->ARM_r0 == -ERESTARTNOINTR) {
247 restart_syscall(regs);
250 + /* If there's no signal to deliver, we just put the saved sigmask
253 + if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
254 + clear_thread_flag(TIF_RESTORE_SIGMASK);
255 + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
258 single_step_set(current);
263 do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
265 if (thread_flags & _TIF_SIGPENDING)
266 - do_signal(¤t->blocked, regs, syscall);
267 + do_signal(regs, syscall);