1 From 000afb0c667a638d5dd2eede868ec2e7e852f0bb Mon Sep 17 00:00:00 2001
\r
2 From: Steven Newbury <s_j_newbury@yahoo.co.uk>
\r
3 Date: Fri, 22 May 2009 14:25:40 +0200
\r
4 Subject: [PATCH] implement TIF_RESTORE_SIGMASK support and enable the related
\r
11 Based on http://www.spinics.net/lists/arm-kernel/msg38114.html
\r
13 arch/arm/include/asm/unistd.h | 7 ++-
\r
14 arch/arm/kernel/calls.S | 6 +-
\r
15 arch/arm/kernel/signal.c | 90 +++++++++++++++++------------------------
\r
16 3 files changed, 44 insertions(+), 59 deletions(-)
\r
18 diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
\r
19 index 94cc58e..cd1eaa0 100644
\r
20 --- a/arch/arm/include/asm/unistd.h
\r
21 +++ b/arch/arm/include/asm/unistd.h
\r
23 #define __NR_readlinkat (__NR_SYSCALL_BASE+332)
\r
24 #define __NR_fchmodat (__NR_SYSCALL_BASE+333)
\r
25 #define __NR_faccessat (__NR_SYSCALL_BASE+334)
\r
26 - /* 335 for pselect6 */
\r
27 - /* 336 for ppoll */
\r
28 +#define __NR_pselect6 (__NR_SYSCALL_BASE+335)
\r
29 +#define __NR_ppoll (__NR_SYSCALL_BASE+336)
\r
30 #define __NR_unshare (__NR_SYSCALL_BASE+337)
\r
31 #define __NR_set_robust_list (__NR_SYSCALL_BASE+338)
\r
32 #define __NR_get_robust_list (__NR_SYSCALL_BASE+339)
\r
34 #define __NR_vmsplice (__NR_SYSCALL_BASE+343)
\r
35 #define __NR_move_pages (__NR_SYSCALL_BASE+344)
\r
36 #define __NR_getcpu (__NR_SYSCALL_BASE+345)
\r
37 - /* 346 for epoll_pwait */
\r
38 +#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346)
\r
39 #define __NR_kexec_load (__NR_SYSCALL_BASE+347)
\r
40 #define __NR_utimensat (__NR_SYSCALL_BASE+348)
\r
41 #define __NR_signalfd (__NR_SYSCALL_BASE+349)
\r
43 #define __ARCH_WANT_SYS_SIGPENDING
\r
44 #define __ARCH_WANT_SYS_SIGPROCMASK
\r
45 #define __ARCH_WANT_SYS_RT_SIGACTION
\r
46 +#define __ARCH_WANT_SYS_RT_SIGSUSPEND
\r
48 #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
\r
49 #define __ARCH_WANT_SYS_TIME
\r
50 diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
\r
51 index 1680e9e..d9edf33 100644
\r
52 --- a/arch/arm/kernel/calls.S
\r
53 +++ b/arch/arm/kernel/calls.S
\r
55 CALL(sys_readlinkat)
\r
58 -/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */
\r
59 - CALL(sys_ni_syscall) /* eventually ppoll */
\r
60 +/* 335 */ CALL(sys_pselect6)
\r
63 CALL(sys_set_robust_list)
\r
64 CALL(sys_get_robust_list)
\r
67 CALL(sys_move_pages)
\r
68 /* 345 */ CALL(sys_getcpu)
\r
69 - CALL(sys_ni_syscall) /* eventually epoll_pwait */
\r
70 + CALL(sys_epoll_pwait)
\r
71 CALL(sys_kexec_load)
\r
74 diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
\r
75 index 80b8b5c..014703d 100644
\r
76 --- a/arch/arm/kernel/signal.c
\r
77 +++ b/arch/arm/kernel/signal.c
\r
78 @@ -47,57 +47,23 @@ const unsigned long sigreturn_codes[7] = {
\r
79 MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
\r
82 -static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
\r
83 +static void fastcall do_signal(struct pt_regs * regs, int syscall);
\r
86 * atomically swap in the new signal mask, and wait for a signal.
\r
88 -asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs)
\r
89 +asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
\r
94 spin_lock_irq(¤t->sighand->siglock);
\r
95 - saveset = current->blocked;
\r
96 + current->saved_sigmask = current->blocked;
\r
97 siginitset(¤t->blocked, mask);
\r
98 recalc_sigpending();
\r
99 spin_unlock_irq(¤t->sighand->siglock);
\r
100 - regs->ARM_r0 = -EINTR;
\r
103 - current->state = TASK_INTERRUPTIBLE;
\r
105 - if (do_signal(&saveset, regs, 0))
\r
106 - return regs->ARM_r0;
\r
111 -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
\r
113 - sigset_t saveset, newset;
\r
115 - /* XXX: Don't preclude handling different sized sigset_t's. */
\r
116 - if (sigsetsize != sizeof(sigset_t))
\r
119 - if (copy_from_user(&newset, unewset, sizeof(newset)))
\r
121 - sigdelsetmask(&newset, ~_BLOCKABLE);
\r
123 - spin_lock_irq(¤t->sighand->siglock);
\r
124 - saveset = current->blocked;
\r
125 - current->blocked = newset;
\r
126 - recalc_sigpending();
\r
127 - spin_unlock_irq(¤t->sighand->siglock);
\r
128 - regs->ARM_r0 = -EINTR;
\r
131 - current->state = TASK_INTERRUPTIBLE;
\r
133 - if (do_signal(&saveset, regs, 0))
\r
134 - return regs->ARM_r0;
\r
136 + current->state = TASK_INTERRUPTIBLE;
\r
138 + set_thread_flag(TIF_RESTORE_SIGMASK);
\r
139 + return -ERESTARTNOHAND;
\r
143 @@ -290,7 +256,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
\r
146 force_sig(SIGSEGV, current);
\r
151 asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
\r
152 @@ -325,7 +291,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
\r
155 force_sig(SIGSEGV, current);
\r
161 @@ -541,7 +507,7 @@ static inline void restart_syscall(struct pt_regs *regs)
\r
163 * OK, we're invoking a handler
\r
167 handle_signal(unsigned long sig, struct k_sigaction *ka,
\r
168 siginfo_t *info, sigset_t *oldset,
\r
169 struct pt_regs * regs, int syscall)
\r
170 @@ -592,7 +558,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
\r
173 force_sigsegv(sig, tsk);
\r
179 @@ -606,6 +572,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
\r
180 recalc_sigpending();
\r
181 spin_unlock_irq(&tsk->sighand->siglock);
\r
187 @@ -617,11 +584,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
\r
188 * the kernel can handle, and then we build all the user-level signal handling
\r
189 * stack-frames in one go after that.
\r
191 -static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
\r
192 +static void fastcall do_signal(struct pt_regs *regs, int syscall)
\r
194 struct k_sigaction ka;
\r
197 + sigset_t *oldset;
\r
200 * We want the common case to go fast, which
\r
201 @@ -630,18 +598,29 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
\r
204 if (!user_mode(regs))
\r
208 if (try_to_freeze())
\r
211 single_step_clear(current);
\r
213 + if (test_thread_flag(TIF_RESTORE_SIGMASK))
\r
214 + oldset = ¤t->saved_sigmask;
\r
216 + oldset = ¤t->blocked;
\r
218 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
\r
220 - handle_signal(signr, &ka, &info, oldset, regs, syscall);
\r
221 + if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) {
\r
222 + /* a signal was successfully delivered; the saved
\r
223 + * sigmask will have been stored in the signal frame,
\r
224 + * and will be restored by sigreturn, so we can simply
\r
225 + * clear the TIF_RESTORE_SIGMASK flag */
\r
226 + clear_thread_flag(TIF_RESTORE_SIGMASK);
\r
228 single_step_set(current);
\r
234 @@ -665,7 +644,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
\r
235 usp = (u32 __user *)regs->ARM_sp;
\r
238 - * Either we supports OABI only, or we have
\r
239 + * Either we support OABI only, or we have
\r
240 * EABI with the OABI compat layer enabled.
\r
241 * In the later case we don't know if user
\r
242 * space is EABI or not, and if not we must
\r
243 @@ -695,12 +674,17 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
\r
246 single_step_set(current);
\r
248 + /* if there's no signal to deliver, we just put the saved sigmask
\r
250 + if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
\r
251 + clear_thread_flag(TIF_RESTORE_SIGMASK);
\r
252 + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
\r
257 do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
\r
259 - if (thread_flags & _TIF_SIGPENDING)
\r
260 - do_signal(¤t->blocked, regs, syscall);
\r
261 + if (thread_flags & (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK))
\r
262 + do_signal(regs, syscall);
\r