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

Linux Cross Reference
Linux/arch/um/kernel/signal_kern.c

Version: ~ [ 0.6-2.3.46 ] ~
Architecture: ~ [ um ] ~

** Warning: Cannot open xref database.

1 #include "linux/stddef.h" 2 #include "linux/sys.h" 3 #include "linux/sched.h" 4 #include "linux/wait.h" 5 #include "linux/kernel.h" 6 #include "linux/smp_lock.h" 7 #include "asm/signal.h" 8 #include "asm/uaccess.h" 9 #include "user_util.h" 10 #include "kern_util.h" 11 #include "kern.h" 12 13 #define _S(nr) (1<<((nr)-1)) 14 15 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) 16 17 void deliver_signals(void *t) 18 { 19 struct task_struct *task; 20 unsigned long handler; 21 int i, signal; 22 23 task = t; 24 if(task->thread.npending == 0) return; 25 for(i=task->thread.npending-1;i>=0;i--){ 26 signal = task->thread.signals[i].signal; 27 handler = task->thread.signals[i].handler; 28 task->thread.npending--; 29 signal_handler(task, handler, signal); 30 } 31 sigdelsetmask(&task->thread.saved_sigs, ~_BLOCKABLE); 32 spin_lock_irq(&task->sigmask_lock); 33 task->blocked = task->thread.saved_sigs; 34 recalc_sigpending(task); 35 spin_unlock_irq(&task->sigmask_lock); 36 } 37 38 /* 39 * OK, we're invoking a handler 40 */ 41 static int handle_signal(struct task_struct *task, unsigned long signr, 42 struct k_sigaction *ka, sigset_t *oldset, int *error) 43 { 44 __sighandler_t handler; 45 sigset_t save; 46 int ret = 0; 47 48 if((error != NULL) && (*error != 0)){ 49 switch (*error) { 50 case -ERESTARTNOHAND: 51 *error = -EINTR; 52 break; 53 54 case -ERESTARTSYS: 55 if (!(ka->sa.sa_flags & SA_RESTART)) { 56 *error = -EINTR; 57 break; 58 } 59 /* fallthrough */ 60 case -ERESTARTNOINTR: 61 ret = 1; 62 break; 63 } 64 } 65 handler = ka->sa.sa_handler; 66 67 save = *oldset; 68 69 if (ka->sa.sa_flags & SA_ONESHOT) 70 ka->sa.sa_handler = SIG_DFL; 71 72 if (!(ka->sa.sa_flags & SA_NODEFER)) { 73 spin_lock_irq(&task->sigmask_lock); 74 sigorsets(&task->blocked,&current->blocked,&ka->sa.sa_mask); 75 sigaddset(&task->blocked,signr); 76 recalc_sigpending(task); 77 spin_unlock_irq(&task->sigmask_lock); 78 } 79 80 if(task->thread.npending == 81 sizeof(task->thread.signals)/sizeof(task->thread.signals[0])) 82 panic("Too many queued signals"); 83 task->thread.signals[task->thread.npending].signal = signr; 84 task->thread.signals[task->thread.npending++].handler = 85 (unsigned long) handler; 86 task->thread.saved_sigs = save; 87 88 return(ret); 89 } 90 91 extern int sys_wait4(pid_t pid,unsigned int * stat_addr, int options, 92 struct rusage * ru); 93 94 /* 95 * Note that 'init' is a special process: it doesn't get signals it doesn't 96 * want to handle. Thus you cannot kill init even with a SIGKILL even by 97 * mistake. 98 * 99 * Note that we go through the signals twice: once to check the signals that 100 * the kernel can handle, and then we build all the user-level signal handling 101 * stack-frames in one go after that. 102 */ 103 int do_signal(void *t, int *error, int *signalled) 104 { 105 struct task_struct *task; 106 sigset_t *oldset; 107 siginfo_t info; 108 struct k_sigaction *ka; 109 int ret; 110 111 task = t; 112 if(task == NULL) task = current; 113 oldset = &task->blocked; 114 115 if(signalled != NULL) *signalled = 0; 116 for (;;) { 117 unsigned long signr; 118 119 spin_lock_irq(&task->sigmask_lock); 120 signr = dequeue_signal(&task->blocked, &info); 121 spin_unlock_irq(&task->sigmask_lock); 122 123 if (!signr) 124 break; 125 126 if(signalled != NULL) *signalled = 1; 127 128 if ((task->flags & PF_PTRACED) && signr != SIGKILL) { 129 /* Let the debugger run. */ 130 task->exit_code = signr; 131 task->state = TASK_STOPPED; 132 notify_parent(task, SIGCHLD); 133 schedule(); 134 135 /* We're back. Did the debugger cancel the sig? */ 136 if (!(signr = task->exit_code)) 137 continue; 138 task->exit_code = 0; 139 140 /* The debugger continued. Ignore SIGSTOP. */ 141 if (signr == SIGSTOP) 142 continue; 143 144 /* Update the siginfo structure. Is this good? */ 145 if (signr != info.si_signo) { 146 info.si_signo = signr; 147 info.si_errno = 0; 148 info.si_code = SI_USER; 149 info.si_pid = task->p_pptr->pid; 150 info.si_uid = task->p_pptr->uid; 151 } 152 153 /* If the (new) signal is now blocked, requeue it. */ 154 if (sigismember(&task->blocked, signr)) { 155 send_sig_info(signr, &info, task); 156 continue; 157 } 158 } 159 160 ka = &task->sig->action[signr-1]; 161 if (ka->sa.sa_handler == SIG_IGN) { 162 if (signr != SIGCHLD) 163 continue; 164 /* Check for SIGCHLD: it's special. */ 165 while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) 166 /* nothing */; 167 continue; 168 } 169 170 if (ka->sa.sa_handler == SIG_DFL) { 171 int exit_code = signr; 172 173 /* Init gets no signals it doesn't want. */ 174 if (task->pid == 1) 175 continue; 176 177 switch (signr) { 178 case SIGCONT: case SIGCHLD: case SIGWINCH: 179 continue; 180 181 case SIGTSTP: case SIGTTIN: case SIGTTOU: 182 if (is_orphaned_pgrp(task->pgrp)) 183 continue; 184 /* FALLTHRU */ 185 186 case SIGSTOP: 187 task->state = TASK_STOPPED; 188 task->exit_code = signr; 189 if (!(task->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) 190 notify_parent(task, SIGCHLD); 191 schedule(); 192 continue; 193 194 case SIGQUIT: case SIGILL: case SIGTRAP: 195 case SIGABRT: case SIGFPE: case SIGSEGV: 196 case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: 197 lock_kernel(); 198 if (task->binfmt 199 && task->binfmt->core_dump 200 && task->binfmt->core_dump(signr, NULL, 201 NULL)) 202 exit_code |= 0x80; 203 unlock_kernel(); 204 /* FALLTHRU */ 205 206 default: 207 lock_kernel(); 208 sigaddset(&task->signal, signr); 209 recalc_sigpending(task); 210 task->flags |= PF_SIGNALED; 211 do_exit(exit_code); 212 /* NOTREACHED */ 213 } 214 } 215 216 /* Whee! Actually deliver the signal. */ 217 ret = handle_signal(task, signr, ka, oldset, error); 218 if(ret != 0) return(ret); 219 } 220 return(0); 221 } 222 223 int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) 224 { 225 sigset_t saveset, newset; 226 227 /* XXX: Don't preclude handling different sized sigset_t's. */ 228 if (sigsetsize != sizeof(sigset_t)) 229 return -EINVAL; 230 231 if (copy_from_user(&newset, unewset, sizeof(newset))) 232 return -EFAULT; 233 sigdelsetmask(&newset, ~_BLOCKABLE); 234 235 spin_lock_irq(&current->sigmask_lock); 236 saveset = current->blocked; 237 current->blocked = newset; 238 recalc_sigpending(current); 239 spin_unlock_irq(&current->sigmask_lock); 240 return(0); 241 } 242

~ [ 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.