This source file includes following definitions.
- osf_sigprocmask
- do_sigsuspend
- do_sigreturn
- setup_frame
- do_signal
1
2
3
4
5
6
7 #include <linux/sched.h>
8 #include <linux/kernel.h>
9 #include <linux/signal.h>
10 #include <linux/errno.h>
11 #include <linux/wait.h>
12 #include <linux/ptrace.h>
13 #include <linux/unistd.h>
14 #include <linux/mm.h>
15
16 #include <asm/bitops.h>
17 #include <asm/segment.h>
18
19 #define _S(nr) (1<<((nr)-1))
20 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
21
22 asmlinkage int sys_wait4(int, int *, int, struct rusage *);
23 asmlinkage void ret_from_sys_call(void);
24 asmlinkage int do_signal(unsigned long, struct pt_regs *, struct switch_stack *,
25 unsigned long, unsigned long);
26
27 extern int ptrace_set_bpt (struct task_struct *child);
28 extern int ptrace_cancel_bpt (struct task_struct *child);
29
30
31
32
33
34 asmlinkage unsigned long osf_sigprocmask(int how, unsigned long newmask)
35 {
36 unsigned long oldmask = current->blocked;
37
38 newmask &= _BLOCKABLE;
39 switch (how) {
40 case SIG_BLOCK:
41 current->blocked |= newmask;
42 return oldmask;
43 case SIG_UNBLOCK:
44 current->blocked &= ~newmask;
45 return oldmask;
46 case SIG_SETMASK:
47 current->blocked = newmask;
48 return oldmask;
49 }
50 return -EINVAL;
51 }
52
53
54
55
56 asmlinkage int do_sigsuspend(unsigned long mask, struct pt_regs * regs, struct switch_stack * sw)
57 {
58 unsigned long oldmask = current->blocked;
59 current->blocked = mask & _BLOCKABLE;
60 while (1) {
61 current->state = TASK_INTERRUPTIBLE;
62 schedule();
63 if (do_signal(oldmask,regs, sw, 0, 0))
64 return -EINTR;
65 }
66 }
67
68
69
70
71 asmlinkage void do_sigreturn(struct sigcontext_struct * sc,
72 struct pt_regs * regs, struct switch_stack * sw)
73 {
74 unsigned long mask;
75 int i;
76
77
78 if (verify_area(VERIFY_READ, sc, sizeof(*sc)))
79 do_exit(SIGSEGV);
80 if (get_fs_quad(&sc->sc_ps) != 8)
81 do_exit(SIGSEGV);
82 mask = get_fs_quad(&sc->sc_mask);
83 if (mask & ~_BLOCKABLE)
84 do_exit(SIGSEGV);
85
86
87 wrusp(get_fs_quad(sc->sc_regs+30));
88 regs->pc = get_fs_quad(&sc->sc_pc);
89 sw->r26 = (unsigned long) ret_from_sys_call;
90 current->blocked = mask;
91
92 regs->r0 = get_fs_quad(sc->sc_regs+0);
93 regs->r1 = get_fs_quad(sc->sc_regs+1);
94 regs->r2 = get_fs_quad(sc->sc_regs+2);
95 regs->r3 = get_fs_quad(sc->sc_regs+3);
96 regs->r4 = get_fs_quad(sc->sc_regs+4);
97 regs->r5 = get_fs_quad(sc->sc_regs+5);
98 regs->r6 = get_fs_quad(sc->sc_regs+6);
99 regs->r7 = get_fs_quad(sc->sc_regs+7);
100 regs->r8 = get_fs_quad(sc->sc_regs+8);
101 sw->r9 = get_fs_quad(sc->sc_regs+9);
102 sw->r10 = get_fs_quad(sc->sc_regs+10);
103 sw->r11 = get_fs_quad(sc->sc_regs+11);
104 sw->r12 = get_fs_quad(sc->sc_regs+12);
105 sw->r13 = get_fs_quad(sc->sc_regs+13);
106 sw->r14 = get_fs_quad(sc->sc_regs+14);
107 sw->r15 = get_fs_quad(sc->sc_regs+15);
108 regs->r16 = get_fs_quad(sc->sc_regs+16);
109 regs->r17 = get_fs_quad(sc->sc_regs+17);
110 regs->r18 = get_fs_quad(sc->sc_regs+18);
111 regs->r19 = get_fs_quad(sc->sc_regs+19);
112 regs->r20 = get_fs_quad(sc->sc_regs+20);
113 regs->r21 = get_fs_quad(sc->sc_regs+21);
114 regs->r22 = get_fs_quad(sc->sc_regs+22);
115 regs->r23 = get_fs_quad(sc->sc_regs+23);
116 regs->r24 = get_fs_quad(sc->sc_regs+24);
117 regs->r25 = get_fs_quad(sc->sc_regs+25);
118 regs->r26 = get_fs_quad(sc->sc_regs+26);
119 regs->r27 = get_fs_quad(sc->sc_regs+27);
120 regs->r28 = get_fs_quad(sc->sc_regs+28);
121 regs->gp = get_fs_quad(sc->sc_regs+29);
122 for (i = 0; i < 31; i++)
123 sw->fp[i] = get_fs_quad(sc->sc_fpregs+i);
124
125
126 if (ptrace_cancel_bpt (current))
127 send_sig(SIGTRAP, current, 1);
128 }
129
130
131
132
133 static void setup_frame(struct sigaction * sa, struct sigcontext_struct ** fp,
134 unsigned long pc, struct pt_regs * regs,
135 struct switch_stack * sw, int signr,
136 unsigned long oldmask)
137 {
138 int i;
139 struct sigcontext_struct * sc;
140
141 sc = *fp;
142
143 sc--;
144 if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
145 do_exit(SIGSEGV);
146
147 put_fs_quad(oldmask, &sc->sc_mask);
148 put_fs_quad(8, &sc->sc_ps);
149 put_fs_quad(pc, &sc->sc_pc);
150 put_fs_quad((unsigned long)*fp, sc->sc_regs+30);
151
152 put_fs_quad(regs->r0 , sc->sc_regs+0);
153 put_fs_quad(regs->r1 , sc->sc_regs+1);
154 put_fs_quad(regs->r2 , sc->sc_regs+2);
155 put_fs_quad(regs->r3 , sc->sc_regs+3);
156 put_fs_quad(regs->r4 , sc->sc_regs+4);
157 put_fs_quad(regs->r5 , sc->sc_regs+5);
158 put_fs_quad(regs->r6 , sc->sc_regs+6);
159 put_fs_quad(regs->r7 , sc->sc_regs+7);
160 put_fs_quad(regs->r8 , sc->sc_regs+8);
161 put_fs_quad(sw->r9 , sc->sc_regs+9);
162 put_fs_quad(sw->r10 , sc->sc_regs+10);
163 put_fs_quad(sw->r11 , sc->sc_regs+11);
164 put_fs_quad(sw->r12 , sc->sc_regs+12);
165 put_fs_quad(sw->r13 , sc->sc_regs+13);
166 put_fs_quad(sw->r14 , sc->sc_regs+14);
167 put_fs_quad(sw->r15 , sc->sc_regs+15);
168 put_fs_quad(regs->r16, sc->sc_regs+16);
169 put_fs_quad(regs->r17, sc->sc_regs+17);
170 put_fs_quad(regs->r18, sc->sc_regs+18);
171 put_fs_quad(regs->r19, sc->sc_regs+19);
172 put_fs_quad(regs->r20, sc->sc_regs+20);
173 put_fs_quad(regs->r21, sc->sc_regs+21);
174 put_fs_quad(regs->r22, sc->sc_regs+22);
175 put_fs_quad(regs->r23, sc->sc_regs+23);
176 put_fs_quad(regs->r24, sc->sc_regs+24);
177 put_fs_quad(regs->r25, sc->sc_regs+25);
178 put_fs_quad(regs->r26, sc->sc_regs+26);
179 put_fs_quad(regs->r27, sc->sc_regs+27);
180 put_fs_quad(regs->r28, sc->sc_regs+28);
181 put_fs_quad(regs->gp , sc->sc_regs+29);
182 for (i = 0; i < 31; i++)
183 put_fs_quad(sw->fp[i], sc->sc_fpregs+i);
184
185
186
187
188
189
190
191
192
193
194 put_fs_quad(0x43ecf40047de0410, sc->sc_retcode+0);
195 put_fs_quad(0x0000000000000083, sc->sc_retcode+1);
196 regs->r26 = (unsigned long) sc->sc_retcode;
197 regs->r16 = signr;
198 regs->r17 = 0;
199 regs->r18 = (unsigned long) sc;
200 *fp = sc;
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216 asmlinkage int do_signal(unsigned long oldmask,
217 struct pt_regs * regs,
218 struct switch_stack * sw,
219 unsigned long r0, unsigned long r19)
220 {
221 unsigned long mask = ~current->blocked;
222 unsigned long handler_signal = 0;
223 struct sigcontext_struct *frame = NULL;
224 unsigned long pc = 0;
225 unsigned long signr, single_stepping;
226 struct sigaction * sa;
227
228 single_stepping = ptrace_cancel_bpt(current);
229
230 while ((signr = current->signal & mask) != 0) {
231 signr = ffz(~signr);
232 clear_bit(signr, ¤t->signal);
233 sa = current->sig->action + signr;
234 signr++;
235 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
236 current->exit_code = signr;
237 current->state = TASK_STOPPED;
238 notify_parent(current);
239 schedule();
240 single_stepping |= ptrace_cancel_bpt(current);
241 if (!(signr = current->exit_code))
242 continue;
243 current->exit_code = 0;
244 if (signr == SIGSTOP)
245 continue;
246 if (_S(signr) & current->blocked) {
247 current->signal |= _S(signr);
248 continue;
249 }
250 sa = current->sig->action + signr - 1;
251 }
252 if (sa->sa_handler == SIG_IGN) {
253 if (signr != SIGCHLD)
254 continue;
255
256 while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
257 ;
258 continue;
259 }
260 if (sa->sa_handler == SIG_DFL) {
261 if (current->pid == 1)
262 continue;
263 switch (signr) {
264 case SIGCONT: case SIGCHLD: case SIGWINCH:
265 continue;
266
267 case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
268 if (current->flags & PF_PTRACED)
269 continue;
270 current->state = TASK_STOPPED;
271 current->exit_code = signr;
272 if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
273 SA_NOCLDSTOP))
274 notify_parent(current);
275 schedule();
276 single_stepping |= ptrace_cancel_bpt(current);
277 continue;
278
279 case SIGQUIT: case SIGILL: case SIGTRAP:
280 case SIGABRT: case SIGFPE: case SIGSEGV:
281 if (current->binfmt && current->binfmt->core_dump) {
282 if (current->binfmt->core_dump(signr, regs))
283 signr |= 0x80;
284 }
285
286 default:
287 current->signal |= _S(signr & 0x7f);
288 current->flags |= PF_SIGNALED;
289 do_exit(signr);
290 }
291 }
292
293
294
295 if (r0) {
296 if (regs->r0 == ERESTARTNOHAND ||
297 (regs->r0 == ERESTARTSYS && !(sa->sa_flags & SA_RESTART)))
298 regs->r0 = EINTR;
299 }
300 handler_signal |= 1 << (signr-1);
301 mask &= ~sa->sa_mask;
302 }
303 if (r0 &&
304 (regs->r0 == ERESTARTNOHAND ||
305 regs->r0 == ERESTARTSYS ||
306 regs->r0 == ERESTARTNOINTR)) {
307 regs->r0 = r0;
308 regs->r19 = r19;
309 regs->pc -= 4;
310 }
311 if (!handler_signal) {
312 if (single_stepping) {
313 ptrace_set_bpt(current);
314 }
315 return 0;
316 }
317 pc = regs->pc;
318 frame = (struct sigcontext_struct *) rdusp();
319 signr = 1;
320 sa = current->sig->action;
321 for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
322 if (mask > handler_signal)
323 break;
324 if (!(mask & handler_signal))
325 continue;
326 setup_frame(sa,&frame,pc,regs,sw,signr,oldmask);
327 pc = (unsigned long) sa->sa_handler;
328 regs->r27 = pc;
329 if (sa->sa_flags & SA_ONESHOT)
330 sa->sa_handler = NULL;
331 current->blocked |= sa->sa_mask;
332 oldmask |= sa->sa_mask;
333 }
334 imb();
335 wrusp((unsigned long) frame);
336 regs->pc = pc;
337 if (single_stepping) {
338 ptrace_set_bpt(current);
339 }
340 return 1;
341 }