This source file includes following definitions.
- sys_sigsuspend
 
- sys_sigreturn
 
- setup_frame
 
- do_signal
 
   1 
   2 
   3 
   4 
   5 
   6 #include <linux/sched.h>
   7 #include <linux/mm.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 
  15 #include <asm/bitops.h>
  16 #include <asm/segment.h>
  17 #include <asm/cachectl.h>
  18 
  19 #define _S(nr) (1<<((nr)-1))
  20 
  21 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
  22 
  23 asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
  24 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
  25 
  26 
  27 
  28 
  29 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
     
  30 {
  31         unsigned long mask;
  32         struct pt_regs * regs = (struct pt_regs *) &restart;
  33 
  34         mask = current->blocked;
  35         current->blocked = set & _BLOCKABLE;
  36         regs->reg2 = -EINTR;
  37         while (1) {
  38                 current->state = TASK_INTERRUPTIBLE;
  39                 schedule();
  40                 if (do_signal(mask,regs))
  41                         return -EINTR;
  42         }
  43 }
  44 
  45 
  46 
  47 
  48 asmlinkage int sys_sigreturn(struct pt_regs *regs)
     
  49 {
  50         struct sigcontext_struct *context;
  51 
  52         
  53 
  54 
  55 
  56 
  57         context = (struct sigcontext_struct *) regs->reg29;
  58         if (verify_area(VERIFY_READ, context, sizeof(struct sigcontext_struct)) ||
  59             (regs->reg29 & 3))
  60                 goto badframe;
  61 
  62         current->blocked = context->sc_oldmask & _BLOCKABLE;
  63         regs->reg1  = context->sc_at;
  64         regs->reg2  = context->sc_v0;
  65         regs->reg3  = context->sc_v1;
  66         regs->reg4  = context->sc_a0;
  67         regs->reg5  = context->sc_a1;
  68         regs->reg6  = context->sc_a2;
  69         regs->reg7  = context->sc_a3;
  70         regs->reg8  = context->sc_t0;
  71         regs->reg9  = context->sc_t1;
  72         regs->reg10 = context->sc_t2;
  73         regs->reg11 = context->sc_t3;
  74         regs->reg12 = context->sc_t4;
  75         regs->reg13 = context->sc_t5;
  76         regs->reg14 = context->sc_t6;
  77         regs->reg15 = context->sc_t7;
  78         regs->reg16 = context->sc_s0;
  79         regs->reg17 = context->sc_s1;
  80         regs->reg18 = context->sc_s2;
  81         regs->reg19 = context->sc_s3;
  82         regs->reg20 = context->sc_s4;
  83         regs->reg21 = context->sc_s5;
  84         regs->reg22 = context->sc_s6;
  85         regs->reg23 = context->sc_s7;
  86         regs->reg24 = context->sc_t8;
  87         regs->reg25 = context->sc_t9;
  88         
  89 
  90 
  91         regs->reg28 = context->sc_gp;
  92         regs->reg29 = context->sc_sp;
  93         regs->reg30 = context->sc_fp;
  94         regs->reg31 = context->sc_ra;
  95         regs->cp0_epc = context->sc_epc;
  96         regs->cp0_cause = context->sc_cause;
  97 
  98         
  99 
 100 
 101         regs->orig_reg2 = -1;
 102         return context->sc_v0;
 103 
 104 badframe:
 105         do_exit(SIGSEGV);
 106 }
 107 
 108 
 109 
 110 
 111 
 112 
 113 
 114 
 115 
 116 
 117 
 118 
 119 
 120 
 121 
 122 
 123 
 124 
 125 
 126 
 127 
 128 
 129 
 130 
 131 
 132 
 133 
 134 
 135 
 136 
 137 
 138 
 139 struct sc {
 140         unsigned long   ass[4];
 141         unsigned int    code[4];
 142         struct sigcontext_struct scc;
 143 };
 144 #define scc_offset ((size_t)&((struct sc *)0)->scc)
 145 
 146 static void setup_frame(struct sigaction * sa, struct sc **fp,
     
 147                         unsigned long pc, struct pt_regs *regs,
 148                         int signr, unsigned long oldmask)
 149 {
 150         struct sc *frame;
 151 
 152         frame = *fp;
 153         frame--;
 154 
 155         
 156 
 157 
 158 
 159 
 160         if (verify_area(VERIFY_WRITE, frame, sizeof (struct sc)) ||
 161             ((unsigned long)frame & 3))
 162                 do_exit(SIGSEGV);
 163 
 164         
 165 
 166 
 167 
 168 
 169 
 170 
 171 
 172 
 173         frame->code[0] = 0x27bd0000 + scc_offset;
 174         frame->code[1] = 0x24020000 + __NR_sigreturn;
 175         frame->code[2] = 0x0000000c;
 176 
 177         
 178 
 179 
 180         sys_cacheflush (frame->code, sizeof (frame->code), ICACHE);
 181 
 182         
 183 
 184 
 185         frame->scc.sc_at = regs->reg1;          
 186         frame->scc.sc_v0 = regs->reg2;          
 187         frame->scc.sc_v1 = regs->reg3;
 188         frame->scc.sc_a0 = regs->reg4;          
 189         frame->scc.sc_a1 = regs->reg5;
 190         frame->scc.sc_a2 = regs->reg6;
 191         frame->scc.sc_a3 = regs->reg7;
 192 
 193         frame->scc.sc_t0 = regs->reg8;          
 194         frame->scc.sc_t1 = regs->reg9;
 195         frame->scc.sc_t2 = regs->reg10;
 196         frame->scc.sc_t3 = regs->reg11;
 197         frame->scc.sc_t4 = regs->reg12;
 198         frame->scc.sc_t5 = regs->reg13;
 199         frame->scc.sc_t6 = regs->reg14;
 200         frame->scc.sc_t7 = regs->reg15;
 201 
 202         frame->scc.sc_s0 = regs->reg16;         
 203         frame->scc.sc_s1 = regs->reg17;
 204         frame->scc.sc_s2 = regs->reg18;
 205         frame->scc.sc_s3 = regs->reg19;
 206         frame->scc.sc_s4 = regs->reg20;
 207         frame->scc.sc_s5 = regs->reg21;
 208         frame->scc.sc_s6 = regs->reg22;
 209         frame->scc.sc_s7 = regs->reg23;
 210 
 211         frame->scc.sc_t8 = regs->reg24;         
 212         frame->scc.sc_t9 = regs->reg25;
 213 
 214         
 215 
 216 
 217         frame->scc.sc_gp = regs->reg28;         
 218         frame->scc.sc_sp = regs->reg29;         
 219         frame->scc.sc_fp = regs->reg30;         
 220         frame->scc.sc_ra = regs->reg31;         
 221 
 222         frame->scc.sc_epc = regs->cp0_epc;      
 223         frame->scc.sc_cause = regs->cp0_cause;  
 224 
 225         frame->scc.sc_oldmask = oldmask;
 226         *fp = frame;
 227 
 228         regs->reg4 = signr;             
 229 }
 230 
 231 
 232 
 233 
 234 
 235 
 236 
 237 
 238 
 239 
 240 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
     
 241 {
 242         unsigned long mask = ~current->blocked;
 243         unsigned long handler_signal = 0;
 244         struct sc *frame = NULL;
 245         unsigned long pc = 0;
 246         unsigned long signr;
 247         struct sigaction * sa;
 248 
 249         while ((signr = current->signal & mask)) {
 250                 signr = ffz(~signr);
 251                 clear_bit(signr, ¤t->signal);
 252                 sa = current->sig->action + signr;
 253                 signr++;
 254                 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
 255                         current->exit_code = signr;
 256                         current->state = TASK_STOPPED;
 257                         notify_parent(current);
 258                         schedule();
 259                         if (!(signr = current->exit_code))
 260                                 continue;
 261                         current->exit_code = 0;
 262                         if (signr == SIGSTOP)
 263                                 continue;
 264                         if (_S(signr) & current->blocked) {
 265                                 current->signal |= _S(signr);
 266                                 continue;
 267                         }
 268                         sa = current->sig->action + signr - 1;
 269                 }
 270                 if (sa->sa_handler == SIG_IGN) {
 271                         if (signr != SIGCHLD)
 272                                 continue;
 273                         
 274                         while (sys_waitpid(-1,NULL,WNOHANG) > 0)
 275                                 ;
 276                         continue;
 277                 }
 278                 if (sa->sa_handler == SIG_DFL) {
 279                         if (current->pid == 1)
 280                                 continue;
 281                         switch (signr) {
 282                         case SIGCONT: case SIGCHLD: case SIGWINCH:
 283                                 continue;
 284 
 285                         case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
 286                                 if (current->flags & PF_PTRACED)
 287                                         continue;
 288                                 current->state = TASK_STOPPED;
 289                                 current->exit_code = signr;
 290                                 if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & 
 291                                                 SA_NOCLDSTOP))
 292                                         notify_parent(current);
 293                                 schedule();
 294                                 continue;
 295 
 296                         case SIGQUIT: case SIGILL: case SIGTRAP:
 297                         case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS:
 298                                 if (current->binfmt && current->binfmt->core_dump) {
 299                                         if (current->binfmt->core_dump(signr, regs))
 300                                                 signr |= 0x80;
 301                                 }
 302                                 
 303                         default:
 304                                 current->signal |= _S(signr & 0x7f);
 305                                 do_exit(signr);
 306                         }
 307                 }
 308                 
 309 
 310 
 311                 if (regs->orig_reg2 >= 0) {
 312                         if (regs->reg2 == -ERESTARTNOHAND ||
 313                            (regs->reg2 == -ERESTARTSYS &&
 314                             !(sa->sa_flags & SA_RESTART)))
 315                                 regs->reg2 = -EINTR;
 316                 }
 317                 handler_signal |= 1 << (signr-1);
 318                 mask &= ~sa->sa_mask;
 319         }
 320         
 321 
 322 
 323 
 324 
 325         if (regs->orig_reg2 >= 0 &&
 326             (regs->reg2 == -ERESTARTNOHAND ||
 327              regs->reg2 == -ERESTARTSYS ||
 328              regs->reg2 == -ERESTARTNOINTR))
 329         {
 330                 regs->reg2 = regs->orig_reg2;
 331                 regs->cp0_epc -= 8;
 332         }
 333         if (!handler_signal)            
 334                 return 0;
 335         pc = regs->cp0_epc;
 336         frame = (struct sc *) regs->reg29;
 337         signr = 1;
 338         sa = current->sig->action;
 339         for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
 340                 if (mask > handler_signal)
 341                         break;
 342                 if (!(mask & handler_signal))
 343                         continue;
 344                 setup_frame(sa, &frame, pc, regs, signr, oldmask);
 345                 pc = (unsigned long) sa->sa_handler;
 346                 if (sa->sa_flags & SA_ONESHOT)
 347                         sa->sa_handler = NULL;
 348                 current->blocked |= sa->sa_mask;
 349                 oldmask |= sa->sa_mask;
 350         }
 351         regs->reg29 = (unsigned long) frame;            
 352         regs->reg31 = (unsigned long) frame->code;      
 353         regs->cp0_epc = pc;             
 354 
 355         return 1;
 356 }