Date:2010-08-19 14:49:33 (2 years 9 months ago)
Author:nbd
Commit:715bc925855760ced69162f6242fc0704b42e939
Message:kernel: backport ppoll to 2.6.31 to fix udev build

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@22719 3c298f89-4303-0410-b956-a3cf2f4a3e73
Files: target/linux/generic/patches-2.6.31/965-arm_restore_sigmask_v2.patch (1 diff)

Change Details

target/linux/generic/patches-2.6.31/965-arm_restore_sigmask_v2.patch
1From: Mikael Pettersson <mikpe@it.uu.se>
2Date: Sat, 15 Aug 2009 11:58:11 +0000 (+0100)
3Subject: ARM: 5677/1: ARM support for TIF_RESTORE_SIGMASK/pselect6/ppoll/epoll_pwait
4X-Git-Tag: next-20090817~86^2~1^6
5X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=369842658a36bcea28ecb643ba4bdb53919330dd
6
7ARM: 5677/1: ARM support for TIF_RESTORE_SIGMASK/pselect6/ppoll/epoll_pwait
8
9This patch adds support for TIF_RESTORE_SIGMASK to ARM's
10signal handling, which allows to hook up the pselect6, ppoll,
11and epoll_pwait syscalls on ARM.
12
13Tested here with eabi userspace and a test program with a
14deliberate race between a child's exit and the parent's
15sigprocmask/select sequence. Using sys_pselect6() instead
16of sigprocmask/select reliably prevents the race.
17
18The other arch's support for TIF_RESTORE_SIGMASK has evolved
19over time:
20
21In 2.6.16:
22- add TIF_RESTORE_SIGMASK which parallels TIF_SIGPENDING
23- test both when checking for pending signal [changed later]
24- reimplement sys_sigsuspend() to use current->saved_sigmask,
25  TIF_RESTORE_SIGMASK [changed later], and -ERESTARTNOHAND;
26  ditto for sys_rt_sigsuspend(), but drop private code and
27  use common code via __ARCH_WANT_SYS_RT_SIGSUSPEND;
28- there are now no "extra" calls to do_signal() so its oldset
29  parameter is always &current->blocked so need not be passed,
30  also its return value is changed to void
31- change handle_signal() to return 0/-errno
32- change do_signal() to honor TIF_RESTORE_SIGMASK:
33  + get oldset from current->saved_sigmask if TIF_RESTORE_SIGMASK
34    is set
35  + if handle_signal() was successful then clear TIF_RESTORE_SIGMASK
36  + if no signal was delivered and TIF_RESTORE_SIGMASK is set then
37    clear it and restore the sigmask
38- hook up sys_pselect6() and sys_ppoll()
39
40In 2.6.19:
41- hook up sys_epoll_pwait()
42
43In 2.6.26:
44- allow archs to override how TIF_RESTORE_SIGMASK is implemented;
45  default set_restore_sigmask() sets both TIF_RESTORE_SIGMASK and
46  TIF_SIGPENDING; archs need now just test TIF_SIGPENDING again
47  when checking for pending signal work; some archs now implement
48  TIF_RESTORE_SIGMASK as a secondary/non-atomic thread flag bit
49- call set_restore_sigmask() in sys_sigsuspend() instead of setting
50  TIF_RESTORE_SIGMASK
51
52In 2.6.29-rc:
53- kill sys_pselect7() which no arch wanted
54
55So for 2.6.31-rc6/ARM this patch does the following:
56- Add TIF_RESTORE_SIGMASK. Use the generic set_restore_sigmask()
57  which sets both TIF_SIGPENDING and TIF_RESTORE_SIGMASK, so
58  TIF_RESTORE_SIGMASK need not claim one of the scarce low thread
59  flags, and existing TIF_SIGPENDING and _TIF_WORK_MASK tests need
60  not be extended for TIF_RESTORE_SIGMASK.
61- sys_sigsuspend() is reimplemented to use current->saved_sigmask
62  and set_restore_sigmask(), making it identical to most other archs
63- The private code for sys_rt_sigsuspend() is removed, instead
64  generic code supplies it via __ARCH_WANT_SYS_RT_SIGSUSPEND.
65- sys_sigsuspend() and sys_rt_sigsuspend() no longer need a pt_regs
66  parameter, so their assembly code wrappers are removed.
67- handle_signal() is changed to return 0 on success or -errno.
68- The oldset parameter to do_signal() is now redundant and removed,
69  and the return value is now also redundant and changed to void.
70- do_signal() is changed to honor TIF_RESTORE_SIGMASK:
71  + get oldset from current->saved_sigmask if TIF_RESTORE_SIGMASK
72    is set
73  + if handle_signal() was successful then clear TIF_RESTORE_SIGMASK
74  + if no signal was delivered and TIF_RESTORE_SIGMASK is set then
75    clear it and restore the sigmask
76- Hook up sys_pselect6, sys_ppoll, and sys_epoll_pwait.
77
78Signed-off-by: Mikael Pettersson <mikpe@it.uu.se>
79Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
80---
81
82--- a/arch/arm/include/asm/thread_info.h
83@@ -141,6 +141,7 @@
84 #define TIF_USING_IWMMXT 17
85 #define TIF_MEMDIE 18
86 #define TIF_FREEZE 19
87+#define TIF_RESTORE_SIGMASK 20
88
89 #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
90 #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
91@@ -148,6 +149,7 @@
92 #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
93 #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
94 #define _TIF_FREEZE (1 << TIF_FREEZE)
95+#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
96
97 /*
98  * Change these and you break ASM code in entry-common.S
99--- a/arch/arm/include/asm/unistd.h
100@@ -360,8 +360,8 @@
101 #define __NR_readlinkat (__NR_SYSCALL_BASE+332)
102 #define __NR_fchmodat (__NR_SYSCALL_BASE+333)
103 #define __NR_faccessat (__NR_SYSCALL_BASE+334)
104- /* 335 for pselect6 */
105- /* 336 for ppoll */
106+#define __NR_pselect6 (__NR_SYSCALL_BASE+335)
107+#define __NR_ppoll (__NR_SYSCALL_BASE+336)
108 #define __NR_unshare (__NR_SYSCALL_BASE+337)
109 #define __NR_set_robust_list (__NR_SYSCALL_BASE+338)
110 #define __NR_get_robust_list (__NR_SYSCALL_BASE+339)
111@@ -372,7 +372,7 @@
112 #define __NR_vmsplice (__NR_SYSCALL_BASE+343)
113 #define __NR_move_pages (__NR_SYSCALL_BASE+344)
114 #define __NR_getcpu (__NR_SYSCALL_BASE+345)
115- /* 346 for epoll_pwait */
116+#define __NR_epoll_pwait (__NR_SYSCALL_BASE+346)
117 #define __NR_kexec_load (__NR_SYSCALL_BASE+347)
118 #define __NR_utimensat (__NR_SYSCALL_BASE+348)
119 #define __NR_signalfd (__NR_SYSCALL_BASE+349)
120@@ -432,6 +432,7 @@
121 #define __ARCH_WANT_SYS_SIGPENDING
122 #define __ARCH_WANT_SYS_SIGPROCMASK
123 #define __ARCH_WANT_SYS_RT_SIGACTION
124+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
125
126 #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
127 #define __ARCH_WANT_SYS_TIME
128--- a/arch/arm/kernel/calls.S
129@@ -81,7 +81,7 @@
130         CALL(sys_ni_syscall) /* was sys_ssetmask */
131 /* 70 */ CALL(sys_setreuid16)
132         CALL(sys_setregid16)
133- CALL(sys_sigsuspend_wrapper)
134+ CALL(sys_sigsuspend)
135         CALL(sys_sigpending)
136         CALL(sys_sethostname)
137 /* 75 */ CALL(sys_setrlimit)
138@@ -188,7 +188,7 @@
139         CALL(sys_rt_sigpending)
140         CALL(sys_rt_sigtimedwait)
141         CALL(sys_rt_sigqueueinfo)
142- CALL(sys_rt_sigsuspend_wrapper)
143+ CALL(sys_rt_sigsuspend)
144 /* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64))
145         CALL(ABI(sys_pwrite64, sys_oabi_pwrite64))
146         CALL(sys_chown16)
147@@ -344,8 +344,8 @@
148         CALL(sys_readlinkat)
149         CALL(sys_fchmodat)
150         CALL(sys_faccessat)
151-/* 335 */ CALL(sys_ni_syscall) /* eventually pselect6 */
152- CALL(sys_ni_syscall) /* eventually ppoll */
153+/* 335 */ CALL(sys_pselect6)
154+ CALL(sys_ppoll)
155         CALL(sys_unshare)
156         CALL(sys_set_robust_list)
157         CALL(sys_get_robust_list)
158@@ -355,7 +355,7 @@
159         CALL(sys_vmsplice)
160         CALL(sys_move_pages)
161 /* 345 */ CALL(sys_getcpu)
162- CALL(sys_ni_syscall) /* eventually epoll_pwait */
163+ CALL(sys_epoll_pwait)
164         CALL(sys_kexec_load)
165         CALL(sys_utimensat)
166         CALL(sys_signalfd)
167--- a/arch/arm/kernel/entry-common.S
168@@ -373,16 +373,6 @@
169         b sys_clone
170 ENDPROC(sys_clone_wrapper)
171
172-sys_sigsuspend_wrapper:
173- add r3, sp, #S_OFF
174- b sys_sigsuspend
175-ENDPROC(sys_sigsuspend_wrapper)
176-
177-sys_rt_sigsuspend_wrapper:
178- add r2, sp, #S_OFF
179- b sys_rt_sigsuspend
180-ENDPROC(sys_rt_sigsuspend_wrapper)
181-
182 sys_sigreturn_wrapper:
183         add r0, sp, #S_OFF
184         b sys_sigreturn
185--- a/arch/arm/kernel/signal.c
186@@ -47,57 +47,22 @@
187     MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
188 };
189
190-static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
191-
192 /*
193  * atomically swap in the new signal mask, and wait for a signal.
194  */
195-asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs)
196+asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
197 {
198- sigset_t saveset;
199-
200     mask &= _BLOCKABLE;
201     spin_lock_irq(&current->sighand->siglock);
202- saveset = current->blocked;
203+ current->saved_sigmask = current->blocked;
204     siginitset(&current->blocked, mask);
205     recalc_sigpending();
206     spin_unlock_irq(&current->sighand->siglock);
207- regs->ARM_r0 = -EINTR;
208-
209- while (1) {
210- current->state = TASK_INTERRUPTIBLE;
211- schedule();
212- if (do_signal(&saveset, regs, 0))
213- return regs->ARM_r0;
214- }
215-}
216-
217-asmlinkage int
218-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
219-{
220- sigset_t saveset, newset;
221-
222- /* XXX: Don't preclude handling different sized sigset_t's. */
223- if (sigsetsize != sizeof(sigset_t))
224- return -EINVAL;
225-
226- if (copy_from_user(&newset, unewset, sizeof(newset)))
227- return -EFAULT;
228- sigdelsetmask(&newset, ~_BLOCKABLE);
229-
230- spin_lock_irq(&current->sighand->siglock);
231- saveset = current->blocked;
232- current->blocked = newset;
233- recalc_sigpending();
234- spin_unlock_irq(&current->sighand->siglock);
235- regs->ARM_r0 = -EINTR;
236
237- while (1) {
238- current->state = TASK_INTERRUPTIBLE;
239- schedule();
240- if (do_signal(&saveset, regs, 0))
241- return regs->ARM_r0;
242- }
243+ current->state = TASK_INTERRUPTIBLE;
244+ schedule();
245+ set_restore_sigmask();
246+ return -ERESTARTNOHAND;
247 }
248
249 asmlinkage int
250@@ -545,7 +510,7 @@
251 /*
252  * OK, we're invoking a handler
253  */
254-static void
255+static int
256 handle_signal(unsigned long sig, struct k_sigaction *ka,
257           siginfo_t *info, sigset_t *oldset,
258           struct pt_regs * regs, int syscall)
259@@ -596,7 +561,7 @@
260
261     if (ret != 0) {
262         force_sigsegv(sig, tsk);
263- return;
264+ return ret;
265     }
266
267     /*
268@@ -610,6 +575,7 @@
269     recalc_sigpending();
270     spin_unlock_irq(&tsk->sighand->siglock);
271
272+ return 0;
273 }
274
275 /*
276@@ -621,11 +587,12 @@
277  * the kernel can handle, and then we build all the user-level signal handling
278  * stack-frames in one go after that.
279  */
280-static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
281+static void do_signal(struct pt_regs *regs, int syscall)
282 {
283     struct k_sigaction ka;
284     siginfo_t info;
285     int signr;
286+ sigset_t *oldset;
287
288     /*
289      * We want the common case to go fast, which
290@@ -634,18 +601,32 @@
291      * if so.
292      */
293     if (!user_mode(regs))
294- return 0;
295+ return;
296
297     if (try_to_freeze())
298         goto no_signal;
299
300     single_step_clear(current);
301
302+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
303+ oldset = &current->saved_sigmask;
304+ else
305+ oldset = &current->blocked;
306+
307     signr = get_signal_to_deliver(&info, &ka, regs, NULL);
308     if (signr > 0) {
309- handle_signal(signr, &ka, &info, oldset, regs, syscall);
310+ if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) {
311+ /*
312+ * A signal was successfully delivered; the saved
313+ * sigmask will have been stored in the signal frame,
314+ * and will be restored by sigreturn, so we can simply
315+ * clear the TIF_RESTORE_SIGMASK flag.
316+ */
317+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
318+ clear_thread_flag(TIF_RESTORE_SIGMASK);
319+ }
320         single_step_set(current);
321- return 1;
322+ return;
323     }
324
325  no_signal:
326@@ -697,14 +678,21 @@
327             regs->ARM_r0 == -ERESTARTNOINTR) {
328             setup_syscall_restart(regs);
329         }
330+
331+ /* If there's no signal to deliver, we just put the saved sigmask
332+ * back.
333+ */
334+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
335+ clear_thread_flag(TIF_RESTORE_SIGMASK);
336+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
337+ }
338     }
339     single_step_set(current);
340- return 0;
341 }
342
343 asmlinkage void
344 do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
345 {
346     if (thread_flags & _TIF_SIGPENDING)
347- do_signal(&current->blocked, regs, syscall);
348+ do_signal(regs, syscall);
349 }

Archive Download the corresponding diff file



interactive