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_waitpid(pid_t pid,unsigned long * stat_addr, int options);
  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         *fp = sc;
 199 }
 200 
 201 
 202 
 203 
 204 
 205 
 206 
 207 
 208 
 209 
 210 
 211 
 212 
 213 
 214 asmlinkage int do_signal(unsigned long oldmask,
     
 215         struct pt_regs * regs,
 216         struct switch_stack * sw,
 217         unsigned long r0, unsigned long r19)
 218 {
 219         unsigned long mask = ~current->blocked;
 220         unsigned long handler_signal = 0;
 221         struct sigcontext_struct *frame = NULL;
 222         unsigned long pc = 0;
 223         unsigned long signr, single_stepping;
 224         struct sigaction * sa;
 225 
 226         single_stepping = ptrace_cancel_bpt(current);
 227 
 228         while ((signr = current->signal & mask) != 0) {
 229                 signr = ffz(~signr);
 230                 clear_bit(signr, ¤t->signal);
 231                 sa = current->sig->action + signr;
 232                 signr++;
 233                 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
 234                         current->exit_code = signr;
 235                         current->state = TASK_STOPPED;
 236                         notify_parent(current);
 237                         schedule();
 238                         single_stepping |= ptrace_cancel_bpt(current);
 239                         if (!(signr = current->exit_code))
 240                                 continue;
 241                         current->exit_code = 0;
 242                         if (signr == SIGSTOP)
 243                                 continue;
 244                         if (_S(signr) & current->blocked) {
 245                                 current->signal |= _S(signr);
 246                                 continue;
 247                         }
 248                         sa = current->sig->action + signr - 1;
 249                 }
 250                 if (sa->sa_handler == SIG_IGN) {
 251                         if (signr != SIGCHLD)
 252                                 continue;
 253                         
 254                         while (sys_waitpid(-1,NULL,WNOHANG) > 0)
 255                                 ;
 256                         continue;
 257                 }
 258                 if (sa->sa_handler == SIG_DFL) {
 259                         if (current->pid == 1)
 260                                 continue;
 261                         switch (signr) {
 262                         case SIGCONT: case SIGCHLD: case SIGWINCH:
 263                                 continue;
 264 
 265                         case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
 266                                 if (current->flags & PF_PTRACED)
 267                                         continue;
 268                                 current->state = TASK_STOPPED;
 269                                 current->exit_code = signr;
 270                                 if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & 
 271                                                 SA_NOCLDSTOP))
 272                                         notify_parent(current);
 273                                 schedule();
 274                                 single_stepping |= ptrace_cancel_bpt(current);
 275                                 continue;
 276 
 277                         case SIGQUIT: case SIGILL: case SIGTRAP:
 278                         case SIGABRT: case SIGFPE: case SIGSEGV:
 279                                 if (current->binfmt && current->binfmt->core_dump) {
 280                                         if (current->binfmt->core_dump(signr, regs))
 281                                                 signr |= 0x80;
 282                                 }
 283                                 
 284                         default:
 285                                 current->signal |= _S(signr & 0x7f);
 286                                 do_exit(signr);
 287                         }
 288                 }
 289                 
 290 
 291 
 292                 if (r0) {
 293                         if (regs->r0 == ERESTARTNOHAND ||
 294                            (regs->r0 == ERESTARTSYS && !(sa->sa_flags & SA_RESTART)))
 295                                 regs->r0 = EINTR;
 296                 }
 297                 handler_signal |= 1 << (signr-1);
 298                 mask &= ~sa->sa_mask;
 299         }
 300         if (r0 &&
 301             (regs->r0 == ERESTARTNOHAND ||
 302              regs->r0 == ERESTARTSYS ||
 303              regs->r0 == ERESTARTNOINTR)) {
 304                 regs->r0 = r0;  
 305                 regs->r19 = r19;
 306                 regs->pc -= 4;
 307         }
 308         if (!handler_signal) {  
 309                 if (single_stepping) {
 310                         ptrace_set_bpt(current);        
 311                 }
 312                 return 0;
 313         }
 314         pc = regs->pc;
 315         frame = (struct sigcontext_struct *) rdusp();
 316         signr = 1;
 317         sa = current->sig->action;
 318         for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
 319                 if (mask > handler_signal)
 320                         break;
 321                 if (!(mask & handler_signal))
 322                         continue;
 323                 setup_frame(sa,&frame,pc,regs,sw,signr,oldmask);
 324                 pc = (unsigned long) sa->sa_handler;
 325                 regs->r27 = pc;
 326                 if (sa->sa_flags & SA_ONESHOT)
 327                         sa->sa_handler = NULL;
 328                 current->blocked |= sa->sa_mask;
 329                 oldmask |= sa->sa_mask;
 330         }
 331         imb();
 332         wrusp((unsigned long) frame);
 333         regs->pc = pc;                  
 334         if (single_stepping) {
 335                 ptrace_set_bpt(current);        
 336         }
 337         return 1;
 338 }