omap3-pandora-kernel: Bump kernel GIT to a version that has 2.6.27.46 merged in.
[openpandora.oe.git] / recipes / linux / omap3-pandora-kernel / 0001-implement-TIF_RESTORE_SIGMASK-support-and-enable-the.patch
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
5  syscalls:\r
6 \r
7 pselect6\r
8 ppoll\r
9 epoll_pwait\r
10 \r
11 Based on http://www.spinics.net/lists/arm-kernel/msg38114.html\r
12 ---\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
17 \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
22 @@ -360,8 +360,8 @@\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
33 @@ -372,7 +372,7 @@\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
42 @@ -430,6 +430,7 @@\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
47  \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
54 @@ -344,8 +344,8 @@\r
55                 CALL(sys_readlinkat)\r
56                 CALL(sys_fchmodat)\r
57                 CALL(sys_faccessat)\r
58 -/* 335 */      CALL(sys_ni_syscall)            /* eventually pselect6 */\r
59 -               CALL(sys_ni_syscall)            /* eventually ppoll */\r
60 +/* 335 */      CALL(sys_pselect6)\r
61 +               CALL(ys_ppoll)\r
62                 CALL(sys_unshare)\r
63                 CALL(sys_set_robust_list)\r
64                 CALL(sys_get_robust_list)\r
65 @@ -355,7 +355,7 @@\r
66                 CALL(sys_vmsplice)\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
72                 CALL(sys_utimensat)\r
73                 CALL(sys_signalfd)\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
80  };\r
81  \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
84  \r
85  /*\r
86   * atomically swap in the new signal mask, and wait for a signal.\r
87   */\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
90  {\r
91 -       sigset_t saveset;\r
92 -\r
93         mask &= _BLOCKABLE;\r
94         spin_lock_irq(&current->sighand->siglock);\r
95 -       saveset = current->blocked;\r
96 +       current->saved_sigmask = current->blocked;\r
97         siginitset(&current->blocked, mask);\r
98         recalc_sigpending();\r
99         spin_unlock_irq(&current->sighand->siglock);\r
100 -       regs->ARM_r0 = -EINTR;\r
101 -\r
102 -       while (1) {\r
103 -               current->state = TASK_INTERRUPTIBLE;\r
104 -               schedule();\r
105 -               if (do_signal(&saveset, regs, 0))\r
106 -                       return regs->ARM_r0;\r
107 -       }\r
108 -}\r
109 -\r
110 -asmlinkage int\r
111 -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)\r
112 -{\r
113 -       sigset_t saveset, newset;\r
114 -\r
115 -       /* XXX: Don't preclude handling different sized sigset_t's. */\r
116 -       if (sigsetsize != sizeof(sigset_t))\r
117 -               return -EINVAL;\r
118 -\r
119 -       if (copy_from_user(&newset, unewset, sizeof(newset)))\r
120 -               return -EFAULT;\r
121 -       sigdelsetmask(&newset, ~_BLOCKABLE);\r
122 -\r
123 -       spin_lock_irq(&current->sighand->siglock);\r
124 -       saveset = current->blocked;\r
125 -       current->blocked = newset;\r
126 -       recalc_sigpending();\r
127 -       spin_unlock_irq(&current->sighand->siglock);\r
128 -       regs->ARM_r0 = -EINTR;\r
129 -\r
130 -       while (1) {\r
131 -               current->state = TASK_INTERRUPTIBLE;\r
132 -               schedule();\r
133 -               if (do_signal(&saveset, regs, 0))\r
134 -                       return regs->ARM_r0;\r
135 -       }\r
136 +       current->state = TASK_INTERRUPTIBLE;\r
137 +       schedule();\r
138 +       set_thread_flag(TIF_RESTORE_SIGMASK);\r
139 +       return -ERESTARTNOHAND;\r
140  }\r
141  \r
142  asmlinkage int \r
143 @@ -290,7 +256,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)\r
144  \r
145  badframe:\r
146         force_sig(SIGSEGV, current);\r
147 -       return 0;\r
148 +       return -EFAULT;\r
149  }\r
150  \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
153  \r
154  badframe:\r
155         force_sig(SIGSEGV, current);\r
156 -       return 0;\r
157 +       return -EFAULT;\r
158  }\r
159  \r
160  static int\r
161 @@ -541,7 +507,7 @@ static inline void restart_syscall(struct pt_regs *regs)\r
162  /*\r
163   * OK, we're invoking a handler\r
164   */    \r
165 -static void\r
166 +static int\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
171  \r
172         if (ret != 0) {\r
173                 force_sigsegv(sig, tsk);\r
174 -               return;\r
175 +               return ret;\r
176         }\r
177  \r
178         /*\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
182  \r
183 +       return ret;\r
184  }\r
185  \r
186  /*\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
190   */\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
193  {\r
194         struct k_sigaction ka;\r
195         siginfo_t info;\r
196         int signr;\r
197 +       sigset_t *oldset;\r
198  \r
199         /*\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
202          * if so.\r
203          */\r
204         if (!user_mode(regs))\r
205 -               return 0;\r
206 +               return;\r
207  \r
208         if (try_to_freeze())\r
209                 goto no_signal;\r
210  \r
211         single_step_clear(current);\r
212  \r
213 +       if (test_thread_flag(TIF_RESTORE_SIGMASK))\r
214 +               oldset = &current->saved_sigmask;\r
215 +       else\r
216 +               oldset = &current->blocked;\r
217 +\r
218         signr = get_signal_to_deliver(&info, &ka, regs, NULL);\r
219         if (signr > 0) {\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
227 +               }\r
228                 single_step_set(current);\r
229 -               return 1;\r
230 +               return;\r
231         }\r
232  \r
233   no_signal:\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
236  \r
237                                 /*\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
244                 }\r
245         }\r
246         single_step_set(current);\r
247 -       return 0;\r
248 +        /* if there's no signal to deliver, we just put the saved sigmask\r
249 +           back. */\r
250 +               if (test_thread_flag(TIF_RESTORE_SIGMASK)) {\r
251 +                       clear_thread_flag(TIF_RESTORE_SIGMASK);\r
252 +                       sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);\r
253 +               }\r
254  }\r
255  \r
256  asmlinkage void\r
257  do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)\r
258  {\r
259 -       if (thread_flags & _TIF_SIGPENDING)\r
260 -               do_signal(&current->blocked, regs, syscall);\r
261 +       if (thread_flags & (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK))\r
262 +               do_signal(regs, syscall);\r
263  }\r
264 -- \r
265 1.6.2.4\r
266 \r