~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/arch/ppc/kernel/signal.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/arch/ppc/kernel/signal.c
  3  *
  4  *  PowerPC version 
  5  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  6  *
  7  *  Derived from "arch/i386/kernel/signal.c"
  8  *    Copyright (C) 1991, 1992 Linus Torvalds
  9  *    1997-11-28  Modified for POSIX.1b signals by Richard Henderson
 10  *
 11  *  This program is free software; you can redistribute it and/or
 12  *  modify it under the terms of the GNU General Public License
 13  *  as published by the Free Software Foundation; either version
 14  *  2 of the License, or (at your option) any later version.
 15  */
 16 
 17 #include <linux/sched.h>
 18 #include <linux/mm.h>
 19 #include <linux/smp.h>
 20 #include <linux/smp_lock.h>
 21 #include <linux/kernel.h>
 22 #include <linux/signal.h>
 23 #include <linux/errno.h>
 24 #include <linux/wait.h>
 25 #include <linux/ptrace.h>
 26 #include <linux/unistd.h>
 27 #include <linux/stddef.h>
 28 #include <linux/elf.h>
 29 #include <asm/ucontext.h>
 30 #include <asm/uaccess.h>
 31 #include <asm/pgtable.h>
 32 
 33 #define DEBUG_SIG 0
 34 
 35 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 36 
 37 #ifndef MIN
 38 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 39 #endif
 40 
 41 #define GP_REGS_SIZE    MIN(sizeof(elf_gregset_t), sizeof(struct pt_regs))
 42 
 43 /* 
 44  * These are the flags in the MSR that the user is allowed to change
 45  * by modifying the saved value of the MSR on the stack.  SE and BE
 46  * should not be in this list since gdb may want to change these.  I.e,
 47  * you should be able to step out of a signal handler to see what
 48  * instruction executes next after the signal handler completes.
 49  * Alternately, if you stepped into a signal handler, you should be
 50  * able to continue 'til the next breakpoint from within the signal
 51  * handler, even if the handler returns.
 52  */
 53 #define MSR_USERCHANGE  (MSR_FE0 | MSR_FE1)
 54 
 55 int do_signal(sigset_t *oldset, struct pt_regs *regs);
 56 
 57 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
 58 {
 59         if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
 60                 return -EFAULT;
 61         if (from->si_code < 0)
 62                 return __copy_to_user(to, from, sizeof(siginfo_t));
 63         else {
 64                 int err;
 65 
 66                 /* If you change siginfo_t structure, please be sure
 67                    this code is fixed accordingly.
 68                    It should never copy any pad contained in the structure
 69                    to avoid security leaks, but must copy the generic
 70                    3 ints plus the relevant union member.  */
 71                 err = __put_user(from->si_signo, &to->si_signo);
 72                 err |= __put_user(from->si_errno, &to->si_errno);
 73                 err |= __put_user((short)from->si_code, &to->si_code);
 74                 /* First 32bits of unions are always present.  */
 75                 err |= __put_user(from->si_pid, &to->si_pid);
 76                 switch (from->si_code >> 16) {
 77                 case __SI_FAULT >> 16:
 78                         break;
 79                 case __SI_CHLD >> 16:
 80                         err |= __put_user(from->si_utime, &to->si_utime);
 81                         err |= __put_user(from->si_stime, &to->si_stime);
 82                         err |= __put_user(from->si_status, &to->si_status);
 83                 default:
 84                         err |= __put_user(from->si_uid, &to->si_uid);
 85                         break;
 86                 /* case __SI_RT: This is not generated by the kernel as of now.  */
 87                 }
 88                 return err;
 89         }
 90 }
 91 
 92 /*
 93  * Atomically swap in the new signal mask, and wait for a signal.
 94  */
 95 int
 96 sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
 97                struct pt_regs *regs)
 98 {
 99         sigset_t saveset;
100 
101         mask &= _BLOCKABLE;
102         spin_lock_irq(&current->sigmask_lock);
103         saveset = current->blocked;
104         siginitset(&current->blocked, mask);
105         recalc_sigpending(current);
106         spin_unlock_irq(&current->sigmask_lock);
107 
108         regs->gpr[3] = -EINTR;
109         while (1) {
110                 current->state = TASK_INTERRUPTIBLE;
111                 schedule();
112                 if (do_signal(&saveset, regs))
113                         /*
114                          * If a signal handler needs to be called,
115                          * do_signal() has set R3 to the signal number (the
116                          * first argument of the signal handler), so don't
117                          * overwrite that with EINTR !
118                          * In the other cases, do_signal() doesn't touch 
119                          * R3, so it's still set to -EINTR (see above).
120                          */
121                         return regs->gpr[3];
122         }
123 }
124 
125 int
126 sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int p6,
127                   int p7, struct pt_regs *regs)
128 {
129         sigset_t saveset, newset;
130 
131         /* XXX: Don't preclude handling different sized sigset_t's.  */
132         if (sigsetsize != sizeof(sigset_t))
133                 return -EINVAL;
134 
135         if (copy_from_user(&newset, unewset, sizeof(newset)))
136                 return -EFAULT;
137         sigdelsetmask(&newset, ~_BLOCKABLE);
138 
139         spin_lock_irq(&current->sigmask_lock);
140         saveset = current->blocked;
141         current->blocked = newset;
142         recalc_sigpending(current);
143         spin_unlock_irq(&current->sigmask_lock);
144 
145         regs->gpr[3] = -EINTR;
146         while (1) {
147                 current->state = TASK_INTERRUPTIBLE;
148                 schedule();
149                 if (do_signal(&saveset, regs))
150                         return regs->gpr[3];
151         }
152 }
153 
154 
155 int
156 sys_sigaltstack(const stack_t *uss, stack_t *uoss)
157 {
158         struct pt_regs *regs = (struct pt_regs *) &uss;
159         return do_sigaltstack(uss, uoss, regs->gpr[1]);
160 }
161 
162 int 
163 sys_sigaction(int sig, const struct old_sigaction *act,
164               struct old_sigaction *oact)
165 {
166         struct k_sigaction new_ka, old_ka;
167         int ret;
168 
169         if (act) {
170                 old_sigset_t mask;
171                 if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
172                     __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
173                     __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
174                         return -EFAULT;
175                 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
176                 __get_user(mask, &act->sa_mask);
177                 siginitset(&new_ka.sa.sa_mask, mask);
178         }
179 
180         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
181 
182         if (!ret && oact) {
183                 if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
184                     __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
185                     __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
186                         return -EFAULT;
187                 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
188                 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
189         }
190 
191         return ret;
192 }
193 
194 /*
195  * When we have signals to deliver, we set up on the
196  * user stack, going down from the original stack pointer:
197  *      a sigregs struct
198  *      one or more sigcontext structs with
199  *      a gap of __SIGNAL_FRAMESIZE bytes
200  *
201  * Each of these things must be a multiple of 16 bytes in size.
202  *
203  */
204 struct sigregs {
205         elf_gregset_t   gp_regs;
206         double          fp_regs[ELF_NFPREG];
207         unsigned long   tramp[2];
208         /* Programs using the rs6000/xcoff abi can save up to 19 gp regs
209            and 18 fp regs below sp before decrementing it. */
210         int             abigap[56];
211 };
212 
213 struct rt_sigframe
214 {
215         unsigned long   _unused[2];
216         struct siginfo *pinfo;
217         void *puc;
218         struct siginfo info;
219         struct ucontext uc;
220 };
221 
222 
223 /*
224  *  When we have rt signals to deliver, we set up on the
225  *  user stack, going down from the original stack pointer:
226  *         a sigregs struct
227  *         one rt_sigframe struct (siginfo + ucontext)
228  *         a gap of __SIGNAL_FRAMESIZE bytes
229  *
230  *  Each of these things must be a multiple of 16 bytes in size.
231  *
232  */
233 int sys_rt_sigreturn(struct pt_regs *regs)
234 {
235         struct rt_sigframe *rt_sf;
236         struct sigcontext_struct sigctx;
237         struct sigregs *sr;
238         int ret;
239         elf_gregset_t saved_regs;  /* an array of ELF_NGREG unsigned longs */
240         sigset_t set;
241         stack_t st;
242         unsigned long prevsp;
243 
244         rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
245         if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx))
246             || copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set))
247             || copy_from_user(&st, &rt_sf->uc.uc_stack, sizeof(st)))
248                 goto badframe;
249         sigdelsetmask(&set, ~_BLOCKABLE);
250         spin_lock_irq(&current->sigmask_lock);
251         current->blocked = set;
252         recalc_sigpending(current);
253         spin_unlock_irq(&current->sigmask_lock);
254 
255         rt_sf++;                        /* Look at next rt_sigframe */
256         if (rt_sf == (struct rt_sigframe *)(sigctx.regs)) {
257                 /* Last stacked signal - restore registers -
258                  * sigctx is initialized to point to the 
259                  * preamble frame (where registers are stored) 
260                  * see handle_signal()
261                  */
262                 sr = (struct sigregs *) sigctx.regs;
263                 if (regs->msr & MSR_FP )
264                         giveup_fpu(current);
265                 if (copy_from_user(saved_regs, &sr->gp_regs,
266                                    sizeof(sr->gp_regs)))
267                         goto badframe;
268                 saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
269                         | (saved_regs[PT_MSR] & MSR_USERCHANGE);
270                 memcpy(regs, saved_regs, GP_REGS_SIZE);
271                 if (copy_from_user(current->thread.fpr, &sr->fp_regs,
272                                    sizeof(sr->fp_regs)))
273                         goto badframe;
274                 /* This function sets back the stack flags into
275                    the current task structure.  */
276                 sys_sigaltstack(&st, NULL);
277 
278                 ret = regs->result;
279         } else {
280                 /* More signals to go */
281                 /* Set up registers for next signal handler */
282                 regs->gpr[1] = (unsigned long)rt_sf - __SIGNAL_FRAMESIZE;
283                 if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)))
284                         goto badframe;
285                 sr = (struct sigregs *) sigctx.regs;
286                 regs->gpr[3] = ret = sigctx.signal;
287                 /* Get the siginfo   */
288                 get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo);
289                 /* Get the ucontext */
290                 get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc);
291                 regs->gpr[6] = (unsigned long) rt_sf;
292 
293                 regs->link = (unsigned long) &sr->tramp;
294                 regs->nip = sigctx.handler;
295                 if (get_user(prevsp, &sr->gp_regs[PT_R1])
296                     || put_user(prevsp, (unsigned long *) regs->gpr[1]))
297                         goto badframe;
298         }
299         return ret;
300 
301 badframe:
302         do_exit(SIGSEGV);
303 }
304 
305 static void
306 setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
307                signed long newsp)
308 {
309         struct rt_sigframe *rt_sf = (struct rt_sigframe *) newsp;
310 
311         /* Set up preamble frame */
312         if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
313                 goto badframe;
314         if (regs->msr & MSR_FP)
315                 giveup_fpu(current);
316         if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
317             || __copy_to_user(&frame->fp_regs, current->thread.fpr,
318                               ELF_NFPREG * sizeof(double))
319         /* Set up to return from user space.
320            It calls the sc exception at offset 0x9999 
321            for sys_rt_sigreturn().
322         */
323             || __put_user(0x38006666UL, &frame->tramp[0])       /* li r0,0x6666 */
324             || __put_user(0x44000002UL, &frame->tramp[1]))      /* sc */
325                 goto badframe;
326         flush_icache_range((unsigned long) &frame->tramp[0],
327                            (unsigned long) &frame->tramp[2]);
328 
329         /* Retrieve rt_sigframe from stack and
330            set up registers for signal handler
331         */
332         newsp -= __SIGNAL_FRAMESIZE;
333         if (put_user(regs->gpr[1], (unsigned long *)newsp)
334             || get_user(regs->nip, &rt_sf->uc.uc_mcontext.handler)
335             || get_user(regs->gpr[3], &rt_sf->uc.uc_mcontext.signal)
336             || get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo)
337             || get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc))
338                 goto badframe;
339 
340         regs->gpr[1] = newsp;
341         regs->gpr[6] = (unsigned long) rt_sf;
342         regs->link = (unsigned long) frame->tramp;
343 
344         return;
345 
346 badframe:
347 #if DEBUG_SIG
348         printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
349                regs, frame, newsp);
350 #endif
351         do_exit(SIGSEGV);
352 }
353 
354 /*
355  * Do a signal return; undo the signal stack.
356  */
357 int sys_sigreturn(struct pt_regs *regs)
358 {
359         struct sigcontext_struct *sc, sigctx;
360         struct sigregs *sr;
361         int ret;
362         elf_gregset_t saved_regs;  /* an array of ELF_NGREG unsigned longs */
363         sigset_t set;
364         unsigned long prevsp;
365 
366         sc = (struct sigcontext_struct *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
367         if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
368                 goto badframe;
369 
370         set.sig[0] = sigctx.oldmask;
371 #if _NSIG_WORDS > 1
372         set.sig[1] = sigctx._unused[3];
373 #endif
374         sigdelsetmask(&set, ~_BLOCKABLE);
375         spin_lock_irq(&current->sigmask_lock);
376         current->blocked = set;
377         recalc_sigpending(current);
378         spin_unlock_irq(&current->sigmask_lock);
379 
380         sc++;                   /* Look at next sigcontext */
381         if (sc == (struct sigcontext_struct *)(sigctx.regs)) {
382                 /* Last stacked signal - restore registers */
383                 sr = (struct sigregs *) sigctx.regs;
384                 if (regs->msr & MSR_FP )
385                         giveup_fpu(current);
386                 if (copy_from_user(saved_regs, &sr->gp_regs,
387                                    sizeof(sr->gp_regs)))
388                         goto badframe;
389                 saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
390                         | (saved_regs[PT_MSR] & MSR_USERCHANGE);
391                 memcpy(regs, saved_regs, GP_REGS_SIZE);
392 
393                 if (copy_from_user(current->thread.fpr, &sr->fp_regs,
394                                    sizeof(sr->fp_regs)))
395                         goto badframe;
396 
397                 ret = regs->result;
398 
399         } else {
400                 /* More signals to go */
401                 regs->gpr[1] = (unsigned long)sc - __SIGNAL_FRAMESIZE;
402                 if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
403                         goto badframe;
404                 sr = (struct sigregs *) sigctx.regs;
405                 regs->gpr[3] = ret = sigctx.signal;
406                 regs->gpr[4] = (unsigned long) sc;
407                 regs->link = (unsigned long) &sr->tramp;
408                 regs->nip = sigctx.handler;
409 
410                 if (get_user(prevsp, &sr->gp_regs[PT_R1])
411                     || put_user(prevsp, (unsigned long *) regs->gpr[1]))
412                         goto badframe;
413         }
414         return ret;
415 
416 badframe:
417         do_exit(SIGSEGV);
418 }       
419 
420 /*
421  * Set up a signal frame.
422  */
423 static void
424 setup_frame(struct pt_regs *regs, struct sigregs *frame,
425             unsigned long newsp)
426 {
427         struct sigcontext_struct *sc = (struct sigcontext_struct *) newsp;
428 
429         if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
430                 goto badframe;
431                 if (regs->msr & MSR_FP)
432                         giveup_fpu(current);
433         if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
434             || __copy_to_user(&frame->fp_regs, current->thread.fpr,
435                               ELF_NFPREG * sizeof(double))
436             || __put_user(0x38007777UL, &frame->tramp[0])    /* li r0,0x7777 */
437             || __put_user(0x44000002UL, &frame->tramp[1]))   /* sc */
438                 goto badframe;
439         flush_icache_range((unsigned long) &frame->tramp[0],
440                            (unsigned long) &frame->tramp[2]);
441 
442         newsp -= __SIGNAL_FRAMESIZE;
443         if (put_user(regs->gpr[1], (unsigned long *)newsp)
444             || get_user(regs->nip, &sc->handler)
445             || get_user(regs->gpr[3], &sc->signal))
446                 goto badframe;
447         regs->gpr[1] = newsp;
448         regs->gpr[4] = (unsigned long) sc;
449         regs->link = (unsigned long) frame->tramp;
450 
451         return;
452 
453 badframe:
454 #if DEBUG_SIG
455         printk("badframe in setup_frame, regs=%p frame=%p newsp=%lx\n",
456                regs, frame, newsp);
457 #endif
458         do_exit(SIGSEGV);
459 }
460 
461 /*
462  * OK, we're invoking a handler
463  */
464 static void
465 handle_signal(unsigned long sig, struct k_sigaction *ka,
466               siginfo_t *info, sigset_t *oldset, struct pt_regs * regs,
467               unsigned long *newspp, unsigned long frame)
468 {
469         struct sigcontext_struct *sc;
470         struct rt_sigframe *rt_sf;
471 
472         if (regs->trap == 0x0C00 /* System Call! */
473             && ((int)regs->result == -ERESTARTNOHAND ||
474                 ((int)regs->result == -ERESTARTSYS &&
475                  !(ka->sa.sa_flags & SA_RESTART))))
476                 regs->result = -EINTR;
477 
478         /* Set up Signal Frame */
479         if (ka->sa.sa_flags & SA_SIGINFO) {
480                 /* Put a Real Time Context onto stack */
481                 *newspp -= sizeof(*rt_sf);
482                 rt_sf = (struct rt_sigframe *) *newspp;
483                 if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf)))
484                         goto badframe;
485 
486                 if (__put_user((unsigned long) ka->sa.sa_handler, &rt_sf->uc.uc_mcontext.handler)
487                     || __put_user(&rt_sf->info, &rt_sf->pinfo)
488                     || __put_user(&rt_sf->uc, &rt_sf->puc)
489                     /* Put the siginfo */
490                     || __copy_to_user(&rt_sf->info, info, sizeof(*info))
491                     /* Create the ucontext */
492                     || __put_user(0, &rt_sf->uc.uc_flags)
493                     || __put_user(0, &rt_sf->uc.uc_link)
494                     || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp)
495                     || __put_user(sas_ss_flags(regs->gpr[1]), 
496                                   &rt_sf->uc.uc_stack.ss_flags)
497                     || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size)
498                     || __copy_to_user(&rt_sf->uc.uc_sigmask, oldset, sizeof(*oldset))
499                     /* mcontext.regs points to preamble register frame */
500                     || __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs)
501                     || __put_user(sig, &rt_sf->uc.uc_mcontext.signal))
502                         goto badframe;
503         } else {
504                 /* Put another sigcontext on the stack */
505                 *newspp -= sizeof(*sc);
506                 sc = (struct sigcontext_struct *) *newspp;
507                 if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
508                         goto badframe;
509                 
510                 if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
511                     || __put_user(oldset->sig[0], &sc->oldmask)
512 #if _NSIG_WORDS > 1
513                     || __put_user(oldset->sig[1], &sc->_unused[3])
514 #endif
515                     || __put_user((struct pt_regs *)frame, &sc->regs)
516                     || __put_user(sig, &sc->signal))
517                         goto badframe;
518         }
519 
520         if (ka->sa.sa_flags & SA_ONESHOT)
521                 ka->sa.sa_handler = SIG_DFL;
522 
523         if (!(ka->sa.sa_flags & SA_NODEFER)) {
524                 spin_lock_irq(&current->sigmask_lock);
525                 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
526                 sigaddset(&current->blocked,sig);
527                 recalc_sigpending(current);
528                 spin_unlock_irq(&current->sigmask_lock);
529         }
530         return;
531 
532 badframe:
533 #if DEBUG_SIG
534         printk("badframe in handle_signal, regs=%p frame=%lx newsp=%lx\n",
535                regs, frame, *newspp);
536         printk("sc=%p sig=%d ka=%p info=%p oldset=%p\n", sc, sig, ka, info, oldset);
537 #endif
538         do_exit(SIGSEGV);
539 }
540 
541 /*
542  * Note that 'init' is a special process: it doesn't get signals it doesn't
543  * want to handle. Thus you cannot kill init even with a SIGKILL even by
544  * mistake.
545  */
546 int do_signal(sigset_t *oldset, struct pt_regs *regs)
547 {
548         siginfo_t info;
549         struct k_sigaction *ka;
550         unsigned long frame, newsp;
551 
552         if (!oldset)
553                 oldset = &current->blocked;
554 
555         newsp = frame = 0;
556 
557         for (;;) {
558                 unsigned long signr;
559 
560                 spin_lock_irq(&current->sigmask_lock);
561                 signr = dequeue_signal(&current->blocked, &info);
562                 spin_unlock_irq(&current->sigmask_lock);
563 
564                 if (!signr)
565                         break;
566 
567                 if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
568                         /* Let the debugger run.  */
569                         current->exit_code = signr;
570                         current->state = TASK_STOPPED;
571                         notify_parent(current, SIGCHLD);
572                         schedule();
573 
574                         /* We're back.  Did the debugger cancel the sig?  */
575                         if (!(signr = current->exit_code))
576                                 continue;
577                         current->exit_code = 0;
578 
579                         /* The debugger continued.  Ignore SIGSTOP.  */
580                         if (signr == SIGSTOP)
581                                 continue;
582 
583                         /* Update the siginfo structure.  Is this good?  */
584                         if (signr != info.si_signo) {
585                                 info.si_signo = signr;
586                                 info.si_errno = 0;
587                                 info.si_code = SI_USER;
588                                 info.si_pid = current->p_pptr->pid;
589                                 info.si_uid = current->p_pptr->uid;
590                         }
591 
592                         /* If the (new) signal is now blocked, requeue it.  */
593                         if (sigismember(&current->blocked, signr)) {
594                                 send_sig_info(signr, &info, current);
595                                 continue;
596                         }
597                 }
598 
599                 ka = &current->sig->action[signr-1];
600                 if (ka->sa.sa_handler == SIG_IGN) {
601                         if (signr != SIGCHLD)
602                                 continue;
603                         /* Check for SIGCHLD: it's special.  */
604                         while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
605                                 /* nothing */;
606                         continue;
607                 }
608 
609                 if (ka->sa.sa_handler == SIG_DFL) {
610                         int exit_code = signr;
611 
612                         /* Init gets no signals it doesn't want.  */
613                         if (current->pid == 1)
614                                 continue;
615 
616                         switch (signr) {
617                         case SIGCONT: case SIGCHLD: case SIGWINCH:
618                                 continue;
619 
620                         case SIGTSTP: case SIGTTIN: case SIGTTOU:
621                                 if (is_orphaned_pgrp(current->pgrp))
622                                         continue;
623                                 /* FALLTHRU */
624 
625                         case SIGSTOP:
626                                 current->state = TASK_STOPPED;
627                                 current->exit_code = signr;
628                                 if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
629                                         notify_parent(current, SIGCHLD);
630                                 schedule();
631                                 continue;
632 
633                         case SIGQUIT: case SIGILL: case SIGTRAP:
634                         case SIGABRT: case SIGFPE: case SIGSEGV:
635                         case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
636                                 if (do_coredump(signr, regs))
637                                         exit_code |= 0x80;
638                                 /* FALLTHRU */
639 
640                         default:
641                                 sigaddset(&current->pending.signal, signr);
642                                 recalc_sigpending(current);
643                                 current->flags |= PF_SIGNALED;
644                                 do_exit(exit_code);
645                                 /* NOTREACHED */
646                         }
647                 }
648 
649                 if ( (ka->sa.sa_flags & SA_ONSTACK)
650                      && (! on_sig_stack(regs->gpr[1])))
651                         newsp = (current->sas_ss_sp + current->sas_ss_size);
652                 else
653                         newsp = regs->gpr[1];
654                 newsp = frame = newsp - sizeof(struct sigregs);
655 
656                 /* Whee!  Actually deliver the signal.  */
657                 handle_signal(signr, ka, &info, oldset, regs, &newsp, frame);
658                 break;
659         }
660 
661         if (regs->trap == 0x0C00 /* System Call! */ &&
662             ((int)regs->result == -ERESTARTNOHAND ||
663              (int)regs->result == -ERESTARTSYS ||
664              (int)regs->result == -ERESTARTNOINTR)) {
665                 regs->gpr[3] = regs->orig_gpr3;
666                 regs->nip -= 4;         /* Back up & retry system call */
667                 regs->result = 0;
668         }
669 
670         if (newsp == frame)
671                 return 0;               /* no signals delivered */
672 
673         if (ka->sa.sa_flags & SA_SIGINFO)
674                 setup_rt_frame(regs, (struct sigregs *) frame, newsp);
675         else
676                 setup_frame(regs, (struct sigregs *) frame, newsp);
677         return 1;
678 }
679 
680 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.