1 Path: news.gmane.org!not-for-mail
2 From: Mikael Pettersson <mikpe@it.uu.se>
3 Newsgroups: gmane.linux.ports.arm.kernel
4 Subject: [PATCH][v3] ARM support for
5 TIF_RESTORE_SIGMASK/pselect6/ppoll/epoll_pwait
6 Date: Sat, 15 Aug 2009 13:09:28 +0200 (MEST)
8 Approved: news@gmane.org
9 Message-ID: <200908151109.n7FB9Sbs000150@pilspetsen.it.uu.se>
10 NNTP-Posting-Host: lo.gmane.org
12 Content-Type: text/plain; charset="us-ascii"
13 Content-Transfer-Encoding: 7bit
14 X-Trace: ger.gmane.org 1250334940 22899 80.91.229.12 (15 Aug 2009 11:15:40 GMT)
15 X-Complaints-To: usenet@ger.gmane.org
16 NNTP-Posting-Date: Sat, 15 Aug 2009 11:15:40 +0000 (UTC)
17 To: linux-arm-kernel@lists.arm.linux.org.uk
18 Original-X-From: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.arm.linux.org.uk Sat Aug 15 13:15:33 2009
19 Return-path: <linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.arm.linux.org.uk>
20 Envelope-to: linux-arm-kernel@m.gmane.org
21 Original-Received: from zeniv.linux.org.uk ([195.92.253.2])
22 by lo.gmane.org with esmtp (Exim 4.50)
24 for linux-arm-kernel@m.gmane.org; Sat, 15 Aug 2009 13:15:31 +0200
25 Original-Received: from [2002:4e20:1eda:1:201:3dff:fe00:156] (helo=lists.arm.linux.org.uk)
26 by ZenIV.linux.org.uk with esmtpsa (Exim 4.69 #1 (Red Hat Linux))
27 id 1McH9u-0005LV-3W; Sat, 15 Aug 2009 11:10:57 +0000
28 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
29 d=arm.linux.org.uk; s=lists; h=Date:Message-Id:From:To:Subject:
30 List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:
31 List-Subscribe:MIME-Version:Content-Type:
32 Content-Transfer-Encoding; bh=RVq9hPAexlUcptd3h6j5nomOyoEIjcDWAP
33 VeJtlhsa4=; b=HAoqRMC9svNzKlR0f938E0cRlLoJZvG2aSun171woWZAClu/Ud
34 IYN0iD2vm4eF+kYQkTYD6PGFCMbNnugmZe6gCpS0QhijoKyOzRBdykQHJuOLQtLE
35 q9KJzp24cQ/vwsV2+O1OqcmIFboIg2L5JQaUuv0djS7OkdspH0ysmi1lg=
36 Original-Received: from [::1] (helo=lists.arm.linux.org.uk)
37 by lists.arm.linux.org.uk with esmtp (Exim 4.69)
38 (envelope-from <linux-arm-kernel-bounces@lists.arm.linux.org.uk>)
39 id 1McH9o-0002us-34; Sat, 15 Aug 2009 12:10:44 +0100
40 Original-Received: from aun.it.uu.se ([130.238.12.36] ident=root)
41 by lists.arm.linux.org.uk with esmtps (TLSv1:AES256-SHA:256)
42 (Exim 4.69) (envelope-from <mikpe@user.it.uu.se>) id 1McH8h-0002uj-Ck
43 for linux-arm-kernel@lists.arm.linux.org.uk;
44 Sat, 15 Aug 2009 12:09:35 +0100
45 Original-Received: from pilspetsen.it.uu.se (daemon@pilspetsen.it.uu.se [130.238.18.39])
46 by aun.it.uu.se (8.13.6/8.13.6) with ESMTP id n7FB9S04005839
47 for <linux-arm-kernel@lists.arm.linux.org.uk>;
48 Sat, 15 Aug 2009 13:09:28 +0200 (MEST)
49 Original-Received: (from mikpe@localhost)
50 by pilspetsen.it.uu.se (8.13.8+Sun/8.13.7) id n7FB9Sbs000150
51 for linux-arm-kernel@lists.arm.linux.org.uk;
52 Sat, 15 Aug 2009 13:09:28 +0200 (MEST)
53 X-BeenThere: linux-arm-kernel@lists.arm.linux.org.uk
54 X-Mailman-Version: 2.1.9
56 List-Id: ARM Linux kernel discussions <linux-arm-kernel.lists.arm.linux.org.uk>
57 List-Unsubscribe: <http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel>,
58 <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=unsubscribe>
59 List-Archive: <http://lists.arm.linux.org.uk/lurker/list/linux-arm-kernel.html>
60 List-Post: <mailto:linux-arm-kernel@lists.arm.linux.org.uk>
61 List-Help: <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=help>
62 List-Subscribe: <http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel>,
63 <mailto:linux-arm-kernel-request@lists.arm.linux.org.uk?subject=subscribe>
64 Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.arm.linux.org.uk
65 Xref: news.gmane.org gmane.linux.ports.arm.kernel:64340
66 Archived-At: <http://permalink.gmane.org/gmane.linux.ports.arm.kernel/64340>
68 This patch adds support for TIF_RESTORE_SIGMASK to ARM's signal handling,
69 which allows to hook up the pselect6, ppoll, and epoll_pwait syscalls on ARM.
71 Tested here with eabi userspace and a test program with a deliberate race
72 between a child's exit and the parent's sigprocmask/select sequence.
73 Using sys_pselect6() instead of sigprocmask/select reliably prevents the race.
75 The other arch's support for TIF_RESTORE_SIGMASK has evolved over time:
78 - add TIF_RESTORE_SIGMASK which parallels TIF_SIGPENDING
79 - test both when checking for pending signal [bad, changed later]
80 - reimplement sys_sigsuspend() to use current->saved_sigmask,
81 TIF_RESTORE_SIGMASK [changed later], and -ERESTARTNOHAND;
82 ditto for sys_rt_sigsuspend(), but drop private code and
83 use common code via __ARCH_WANT_SYS_RT_SIGSUSPEND;
84 - there are now no "extra" calls to do_signal() so its oldset
85 parameter is always ¤t->blocked so need not be passed,
86 also its return value is changed to void
87 - change handle_signal() to return 0/-errno
88 - change do_signal() to honor TIF_RESTORE_SIGMASK:
89 + get oldset from current->saved_sigmask if TIF_RESTORE_SIGMASK is set
90 + if handle_signal() was successful then clear TIF_RESTORE_SIGMASK
91 + if no signal was delivered and TIF_RESTORE_SIGMASK is set then
92 clear it and restore the sigmask
93 - hook up sys_pselect6() and sys_ppoll()
96 - hook up sys_epoll_pwait()
99 - allow archs to override how TIF_RESTORE_SIGMASK is implemented;
100 default set_restore_sigmask() sets both TIF_RESTORE_SIGMASK and
101 TIF_SIGPENDING; archs need now just test TIF_SIGPENDING again
102 when checking for pending signal work; some archs now implement
103 TIF_RESTORE_SIGMASK as a secondary/non-atomic thread flag bit
104 - call set_restore_sigmask() in sys_sigsuspend() instead of setting
108 - kill sys_pselect7() which no arch wanted
110 So for 2.6.31-rc6/ARM this patch does the following:
111 - Add TIF_RESTORE_SIGMASK. Use the generic set_restore_sigmask()
112 which sets both TIF_SIGPENDING and TIF_RESTORE_SIGMASK, so
113 TIF_RESTORE_SIGMASK need not claim one of the scarce low thread
114 flags, and existing TIF_SIGPENDING and _TIF_WORK_MASK tests need
115 not be extended for TIF_RESTORE_SIGMASK.
116 - sys_sigsuspend() is reimplemented to use current->saved_sigmask and
117 set_restore_sigmask(), making it identical to most other archs.
118 - The private code for sys_rt_sigsuspend() is removed, instead generic
119 code supplies it via __ARCH_WANT_SYS_RT_SIGSUSPEND.
120 - sys_sigsuspend() and sys_rt_sigsuspend() no longer need a pt_regs
121 parameter, so their assembly code wrappers are removed.
122 - handle_signal() is changed to return 0 on success or -errno.
123 - The oldset parameter to do_signal() is now redundant and removed,
124 and the return value is now also redundant so it's changed to void.
125 - do_signal() is changed to honor TIF_RESTORE_SIGMASK:
126 + get oldset from current->saved_sigmask if TIF_RESTORE_SIGMASK is set
127 + if handle_signal() was successful then clear TIF_RESTORE_SIGMASK
128 + if no signal was delivered and TIF_RESTORE_SIGMASK is set then
129 clear it and restore the sigmask
130 - Hook up sys_pselect6, sys_ppoll, and sys_epoll_pwait.
132 Signed-off-by: Mikael Pettersson
134 Changes from previous versions:
136 v2 (only posted as incremental diff against v1):
137 - moved sigmask restoration in no-signal-delivered case into
138 "if (syscall)" block for extra protection against exception
139 path also invoking do_signal()
141 - moved oldset initialisation into "if (signr > 0)" block,
142 as requested by Russell
144 arch/arm/include/asm/thread_info.h | 2
145 arch/arm/include/asm/unistd.h | 7 +--
146 arch/arm/kernel/calls.S | 10 ++--
147 arch/arm/kernel/entry-common.S | 10 ----
148 arch/arm/kernel/signal.c | 86 +++++++++++++++----------------------
149 5 files changed, 48 insertions(+), 67 deletions(-)
151 diff -rupN linux-2.6.31-rc6/arch/arm/include/asm/thread_info.h linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/include/asm/thread_info.h
152 --- linux-2.6.31-rc6/arch/arm/include/asm/thread_info.h 2009-08-14 11:11:10.000000000 +0200
153 +++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/include/asm/thread_info.h 2009-08-14 11:26:44.000000000 +0200
154 @@ -140,6 +140,7 @@ extern void vfp_sync_state(struct thread
155 #define TIF_USING_IWMMXT 17
156 #define TIF_MEMDIE 18
157 #define TIF_FREEZE 19
158 +#define TIF_RESTORE_SIGMASK 20
160 #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
161 #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
162 @@ -147,6 +148,7 @@ extern void vfp_sync_state(struct thread
163 #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
164 #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
165 #define _TIF_FREEZE (1 << TIF_FREEZE)
166 +#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
169 * Change these and you break ASM code in entry-common.S
170 diff -rupN linux-2.6.31-rc6/arch/arm/include/asm/unistd.h linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/include/asm/unistd.h
171 --- linux-2.6.31-rc6/arch/arm/include/asm/unistd.h 2009-08-14 11:11:10.000000000 +0200
172 +++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/include/asm/unistd.h 2009-08-14 11:26:44.000000000 +0200
174 #define __NR_readlinkat (__NR_SYSCALL_BASE+332)
175 #define __NR_fchmodat (__NR_SYSCALL_BASE+333)
176 #define __NR_faccessat (__NR_SYSCALL_BASE+334)
177 - /* 335 for pselect6 */
178 - /* 336 for ppoll */
179 +#define __NR_pselect6 (__NR_SYSCALL_BASE+335)
180 +#define __NR_ppoll (__NR_SYSCALL_BASE+336)
181 #define __NR_unshare (__NR_SYSCALL_BASE+337)
182 #define __NR_set_robust_list (__NR_SYSCALL_BASE+338)
183 #define __NR_get_robust_list (__NR_SYSCALL_BASE+339)
185 #define __NR_vmsplice (__NR_SYSCALL_BASE+343)
186 #define __NR_move_pages (__NR_SYSCALL_BASE+344)
187 #define __NR_getcpu (__NR_SYSCALL_BASE+345)
188 - /* 346 for epoll_pwait */
189 +#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346)
190 #define __NR_kexec_load (__NR_SYSCALL_BASE+347)
191 #define __NR_utimensat (__NR_SYSCALL_BASE+348)
192 #define __NR_signalfd (__NR_SYSCALL_BASE+349)
194 #define __ARCH_WANT_SYS_SIGPENDING
195 #define __ARCH_WANT_SYS_SIGPROCMASK
196 #define __ARCH_WANT_SYS_RT_SIGACTION
197 +#define __ARCH_WANT_SYS_RT_SIGSUSPEND
199 #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
200 #define __ARCH_WANT_SYS_TIME
201 diff -rupN linux-2.6.31-rc6/arch/arm/kernel/calls.S linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/calls.S
202 --- linux-2.6.31-rc6/arch/arm/kernel/calls.S 2009-08-14 11:11:10.000000000 +0200
203 +++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/calls.S 2009-08-14 11:26:44.000000000 +0200
205 CALL(sys_ni_syscall) /* was sys_ssetmask */
206 /* 70 */ CALL(sys_setreuid16)
208 - CALL(sys_sigsuspend_wrapper)
209 + CALL(sys_sigsuspend)
211 CALL(sys_sethostname)
212 /* 75 */ CALL(sys_setrlimit)
214 CALL(sys_rt_sigpending)
215 CALL(sys_rt_sigtimedwait)
216 CALL(sys_rt_sigqueueinfo)
217 - CALL(sys_rt_sigsuspend_wrapper)
218 + CALL(sys_rt_sigsuspend)
219 /* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64))
220 CALL(ABI(sys_pwrite64, sys_oabi_pwrite64))
226 -/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */
227 - CALL(sys_ni_syscall) /* eventually ppoll */
228 +/* 335 */ CALL(sys_pselect6)
231 CALL(sys_set_robust_list)
232 CALL(sys_get_robust_list)
236 /* 345 */ CALL(sys_getcpu)
237 - CALL(sys_ni_syscall) /* eventually epoll_pwait */
238 + CALL(sys_epoll_pwait)
242 diff -rupN linux-2.6.31-rc6/arch/arm/kernel/entry-common.S linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/entry-common.S
243 --- linux-2.6.31-rc6/arch/arm/kernel/entry-common.S 2009-08-14 11:11:10.000000000 +0200
244 +++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/entry-common.S 2009-08-14 11:26:44.000000000 +0200
245 @@ -373,16 +373,6 @@ sys_clone_wrapper:
247 ENDPROC(sys_clone_wrapper)
249 -sys_sigsuspend_wrapper:
252 -ENDPROC(sys_sigsuspend_wrapper)
254 -sys_rt_sigsuspend_wrapper:
256 - b sys_rt_sigsuspend
257 -ENDPROC(sys_rt_sigsuspend_wrapper)
259 sys_sigreturn_wrapper:
262 diff -rupN linux-2.6.31-rc6/arch/arm/kernel/signal.c linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/signal.c
263 --- linux-2.6.31-rc6/arch/arm/kernel/signal.c 2009-08-14 11:11:10.000000000 +0200
264 +++ linux-2.6.31-rc6.arm-restore-sigmask-v3/arch/arm/kernel/signal.c 2009-08-14 11:26:44.000000000 +0200
265 @@ -47,57 +47,22 @@ const unsigned long sigreturn_codes[7] =
266 MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
269 -static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
272 * atomically swap in the new signal mask, and wait for a signal.
274 -asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs)
275 +asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
280 spin_lock_irq(¤t->sighand->siglock);
281 - saveset = current->blocked;
282 + current->saved_sigmask = current->blocked;
283 siginitset(¤t->blocked, mask);
285 spin_unlock_irq(¤t->sighand->siglock);
286 - regs->ARM_r0 = -EINTR;
289 - current->state = TASK_INTERRUPTIBLE;
291 - if (do_signal(&saveset, regs, 0))
292 - return regs->ARM_r0;
297 -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
299 - sigset_t saveset, newset;
301 - /* XXX: Don't preclude handling different sized sigset_t's. */
302 - if (sigsetsize != sizeof(sigset_t))
305 - if (copy_from_user(&newset, unewset, sizeof(newset)))
307 - sigdelsetmask(&newset, ~_BLOCKABLE);
309 - spin_lock_irq(¤t->sighand->siglock);
310 - saveset = current->blocked;
311 - current->blocked = newset;
312 - recalc_sigpending();
313 - spin_unlock_irq(¤t->sighand->siglock);
314 - regs->ARM_r0 = -EINTR;
317 - current->state = TASK_INTERRUPTIBLE;
319 - if (do_signal(&saveset, regs, 0))
320 - return regs->ARM_r0;
322 + current->state = TASK_INTERRUPTIBLE;
324 + set_restore_sigmask();
325 + return -ERESTARTNOHAND;
329 @@ -545,7 +510,7 @@ static inline void setup_syscall_restart
331 * OK, we're invoking a handler
335 handle_signal(unsigned long sig, struct k_sigaction *ka,
336 siginfo_t *info, sigset_t *oldset,
337 struct pt_regs * regs, int syscall)
338 @@ -596,7 +561,7 @@ handle_signal(unsigned long sig, struct
341 force_sigsegv(sig, tsk);
347 @@ -610,6 +575,7 @@ handle_signal(unsigned long sig, struct
349 spin_unlock_irq(&tsk->sighand->siglock);
355 @@ -621,7 +587,7 @@ handle_signal(unsigned long sig, struct
356 * the kernel can handle, and then we build all the user-level signal handling
357 * stack-frames in one go after that.
359 -static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
360 +static void do_signal(struct pt_regs *regs, int syscall)
362 struct k_sigaction ka;
364 @@ -634,7 +600,7 @@ static int do_signal(sigset_t *oldset, s
367 if (!user_mode(regs))
373 @@ -643,9 +609,24 @@ static int do_signal(sigset_t *oldset, s
375 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
377 - handle_signal(signr, &ka, &info, oldset, regs, syscall);
380 + if (test_thread_flag(TIF_RESTORE_SIGMASK))
381 + oldset = ¤t->saved_sigmask;
383 + oldset = ¤t->blocked;
384 + if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) {
386 + * A signal was successfully delivered; the saved
387 + * sigmask will have been stored in the signal frame,
388 + * and will be restored by sigreturn, so we can simply
389 + * clear the TIF_RESTORE_SIGMASK flag.
391 + if (test_thread_flag(TIF_RESTORE_SIGMASK))
392 + clear_thread_flag(TIF_RESTORE_SIGMASK);
394 single_step_set(current);
400 @@ -697,14 +678,21 @@ static int do_signal(sigset_t *oldset, s
401 regs->ARM_r0 == -ERESTARTNOINTR) {
402 setup_syscall_restart(regs);
405 + /* If there's no signal to deliver, we just put the saved sigmask
408 + if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
409 + clear_thread_flag(TIF_RESTORE_SIGMASK);
410 + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
413 single_step_set(current);
418 do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
420 if (thread_flags & _TIF_SIGPENDING)
421 - do_signal(¤t->blocked, regs, syscall);
422 + do_signal(regs, syscall);
425 -------------------------------------------------------------------
426 List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
427 FAQ: http://www.arm.linux.org.uk/mailinglists/faq.php
428 Etiquette: http://www.arm.linux.org.uk/mailinglists/etiquette.php