1 From 8a7643b09856f4f661403dcedbe0455b3cbeeea9 Mon Sep 17 00:00:00 2001
2 From: Steven Newbury <s_j_newbury@yahoo.co.uk>
3 Date: Fri, 22 May 2009 14:25:40 +0200
4 Subject: [PATCH] implement TIF_RESTORE_SIGMASK support and enable the related
11 Based on http://www.spinics.net/lists/arm-kernel/msg38114.html
13 arch/arm/include/asm/thread_info.h | 2 +
14 arch/arm/include/asm/unistd.h | 7 ++-
15 arch/arm/kernel/calls.S | 6 +-
16 arch/arm/kernel/signal.c | 90 +++++++++++++++---------------------
17 4 files changed, 46 insertions(+), 59 deletions(-)
19 diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
20 index 4f88482..2cf0917 100644
21 --- a/arch/arm/include/asm/thread_info.h
22 +++ b/arch/arm/include/asm/thread_info.h
23 @@ -136,6 +136,7 @@ extern void vfp_sync_state(struct thread_info *thread);
24 #define TIF_SIGPENDING 0
25 #define TIF_NEED_RESCHED 1
26 #define TIF_SYSCALL_TRACE 8
27 +#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal */
28 #define TIF_POLLING_NRFLAG 16
29 #define TIF_USING_IWMMXT 17
31 @@ -144,6 +145,7 @@ extern void vfp_sync_state(struct thread_info *thread);
32 #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
33 #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
34 #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
35 +#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
36 #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
37 #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
38 #define _TIF_FREEZE (1 << TIF_FREEZE)
39 diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
40 index 94cc58e..cd1eaa0 100644
41 --- a/arch/arm/include/asm/unistd.h
42 +++ b/arch/arm/include/asm/unistd.h
44 #define __NR_readlinkat (__NR_SYSCALL_BASE+332)
45 #define __NR_fchmodat (__NR_SYSCALL_BASE+333)
46 #define __NR_faccessat (__NR_SYSCALL_BASE+334)
47 - /* 335 for pselect6 */
49 +#define __NR_pselect6 (__NR_SYSCALL_BASE+335)
50 +#define __NR_ppoll (__NR_SYSCALL_BASE+336)
51 #define __NR_unshare (__NR_SYSCALL_BASE+337)
52 #define __NR_set_robust_list (__NR_SYSCALL_BASE+338)
53 #define __NR_get_robust_list (__NR_SYSCALL_BASE+339)
55 #define __NR_vmsplice (__NR_SYSCALL_BASE+343)
56 #define __NR_move_pages (__NR_SYSCALL_BASE+344)
57 #define __NR_getcpu (__NR_SYSCALL_BASE+345)
58 - /* 346 for epoll_pwait */
59 +#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346)
60 #define __NR_kexec_load (__NR_SYSCALL_BASE+347)
61 #define __NR_utimensat (__NR_SYSCALL_BASE+348)
62 #define __NR_signalfd (__NR_SYSCALL_BASE+349)
64 #define __ARCH_WANT_SYS_SIGPENDING
65 #define __ARCH_WANT_SYS_SIGPROCMASK
66 #define __ARCH_WANT_SYS_RT_SIGACTION
67 +#define __ARCH_WANT_SYS_RT_SIGSUSPEND
69 #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
70 #define __ARCH_WANT_SYS_TIME
71 diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
72 index 1680e9e..534000d 100644
73 --- a/arch/arm/kernel/calls.S
74 +++ b/arch/arm/kernel/calls.S
79 -/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */
80 - CALL(sys_ni_syscall) /* eventually ppoll */
81 +/* 335 */ CALL(sys_pselect6)
84 CALL(sys_set_robust_list)
85 CALL(sys_get_robust_list)
89 /* 345 */ CALL(sys_getcpu)
90 - CALL(sys_ni_syscall) /* eventually epoll_pwait */
91 + CALL(sys_epoll_pwait)
95 diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
96 index 80b8b5c..7645048 100644
97 --- a/arch/arm/kernel/signal.c
98 +++ b/arch/arm/kernel/signal.c
99 @@ -47,57 +47,23 @@ const unsigned long sigreturn_codes[7] = {
100 MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
103 -static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
104 +static void do_signal(struct pt_regs * regs, int syscall);
107 * atomically swap in the new signal mask, and wait for a signal.
109 -asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs)
110 +asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
115 spin_lock_irq(¤t->sighand->siglock);
116 - saveset = current->blocked;
117 + current->saved_sigmask = current->blocked;
118 siginitset(¤t->blocked, mask);
120 spin_unlock_irq(¤t->sighand->siglock);
121 - regs->ARM_r0 = -EINTR;
124 - current->state = TASK_INTERRUPTIBLE;
126 - if (do_signal(&saveset, regs, 0))
127 - return regs->ARM_r0;
132 -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
134 - sigset_t saveset, newset;
136 - /* XXX: Don't preclude handling different sized sigset_t's. */
137 - if (sigsetsize != sizeof(sigset_t))
140 - if (copy_from_user(&newset, unewset, sizeof(newset)))
142 - sigdelsetmask(&newset, ~_BLOCKABLE);
144 - spin_lock_irq(¤t->sighand->siglock);
145 - saveset = current->blocked;
146 - current->blocked = newset;
147 - recalc_sigpending();
148 - spin_unlock_irq(¤t->sighand->siglock);
149 - regs->ARM_r0 = -EINTR;
152 - current->state = TASK_INTERRUPTIBLE;
154 - if (do_signal(&saveset, regs, 0))
155 - return regs->ARM_r0;
157 + current->state = TASK_INTERRUPTIBLE;
159 + set_thread_flag(TIF_RESTORE_SIGMASK);
160 + return -ERESTARTNOHAND;
164 @@ -290,7 +256,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
167 force_sig(SIGSEGV, current);
172 asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
173 @@ -325,7 +291,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
176 force_sig(SIGSEGV, current);
182 @@ -541,7 +507,7 @@ static inline void restart_syscall(struct pt_regs *regs)
184 * OK, we're invoking a handler
188 handle_signal(unsigned long sig, struct k_sigaction *ka,
189 siginfo_t *info, sigset_t *oldset,
190 struct pt_regs * regs, int syscall)
191 @@ -592,7 +558,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
194 force_sigsegv(sig, tsk);
200 @@ -606,6 +572,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
202 spin_unlock_irq(&tsk->sighand->siglock);
208 @@ -617,11 +584,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
209 * the kernel can handle, and then we build all the user-level signal handling
210 * stack-frames in one go after that.
212 -static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
213 +static void do_signal(struct pt_regs *regs, int syscall)
215 struct k_sigaction ka;
221 * We want the common case to go fast, which
222 @@ -630,18 +598,29 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
225 if (!user_mode(regs))
232 single_step_clear(current);
234 + if (test_thread_flag(TIF_RESTORE_SIGMASK))
235 + oldset = ¤t->saved_sigmask;
237 + oldset = ¤t->blocked;
239 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
241 - handle_signal(signr, &ka, &info, oldset, regs, syscall);
242 + if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) {
243 + /* a signal was successfully delivered; the saved
244 + * sigmask will have been stored in the signal frame,
245 + * and will be restored by sigreturn, so we can simply
246 + * clear the TIF_RESTORE_SIGMASK flag */
247 + clear_thread_flag(TIF_RESTORE_SIGMASK);
249 single_step_set(current);
255 @@ -665,7 +644,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
256 usp = (u32 __user *)regs->ARM_sp;
259 - * Either we supports OABI only, or we have
260 + * Either we support OABI only, or we have
261 * EABI with the OABI compat layer enabled.
262 * In the later case we don't know if user
263 * space is EABI or not, and if not we must
264 @@ -695,12 +674,17 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
267 single_step_set(current);
269 + /* if there's no signal to deliver, we just put the saved sigmask
271 + if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
272 + clear_thread_flag(TIF_RESTORE_SIGMASK);
273 + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
278 do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
280 - if (thread_flags & _TIF_SIGPENDING)
281 - do_signal(¤t->blocked, regs, syscall);
282 + if (thread_flags & (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK))
283 + do_signal(regs, syscall);