This source file includes following definitions.
- sys_sigsuspend
- sys_sigreturn
- do_signal
1
2
3
4
5
6
7
8 #include <linux/sched.h>
9 #include <linux/mm.h>
10 #include <linux/kernel.h>
11 #include <linux/signal.h>
12 #include <linux/errno.h>
13 #include <linux/wait.h>
14 #include <linux/ptrace.h>
15 #include <linux/unistd.h>
16
17 #define _S(nr) (1<<((nr)-1))
18
19 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
20
21 asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
22
23
24
25
26 asmlinkage int sys_sigsuspend(unsigned long set, int p2, int p3, int p4, int p6, int p7, struct pt_regs *regs)
27 {
28 unsigned long mask;
29
30 mask = current->blocked;
31 current->blocked = set & _BLOCKABLE;
32 regs->gpr[3] = -EINTR;
33 #if 0
34 printk("Task: %x[%d] - SIGSUSPEND at %x, Mask: %x\n", current, current->pid, regs->nip, set);
35 #endif
36 while (1) {
37 current->state = TASK_INTERRUPTIBLE;
38 schedule();
39 if (do_signal(mask,regs))
40 return -EINTR;
41 }
42 }
43
44
45
46
47 asmlinkage int sys_sigreturn(struct pt_regs *regs)
48 {
49 struct sigcontext_struct *sc;
50 struct pt_regs *int_regs;
51 int signo;
52 sc = (struct sigcontext_struct *)regs->gpr[1];
53 current->blocked = sc->oldmask & _BLOCKABLE;
54 int_regs = sc->regs;
55 signo = sc->signal;
56 sc++;
57 if (sc == (struct sigcontext_struct *)(int_regs))
58 {
59 memcpy(regs, int_regs, sizeof(*regs));
60 if ((int)regs->orig_gpr3 >= 0 &&
61 ((int)regs->result == -ERESTARTNOHAND ||
62 (int)regs->result == -ERESTARTSYS ||
63 (int)regs->result == -ERESTARTNOINTR))
64 {
65 regs->gpr[3] = regs->orig_gpr3;
66 regs->nip -= 4;
67 regs->result = 0;
68 }
69 return (regs->result);
70 } else
71 {
72 regs->gpr[1] = (unsigned long)sc;
73 regs->gpr[3] = sc->signal;
74 regs->gpr[4] = sc->regs;
75 regs->link = (unsigned long)((sc->regs)+1);
76 regs->nip = sc->handler;
77 return (sc->signal);
78 }
79 }
80
81
82
83
84
85
86
87
88
89
90
91 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
92 {
93 unsigned long mask = ~current->blocked;
94 unsigned long handler_signal = 0;
95 unsigned long *frame = NULL;
96 unsigned long *trampoline;
97 unsigned long *regs_ptr;
98 unsigned long nip = 0;
99 unsigned long signr;
100 int bitno;
101 struct sigcontext_struct *sc;
102 struct sigaction * sa;
103 int s = _disable_interrupts();
104
105 while ((signr = current->signal & mask)) {
106 #if 0
107 signr = ffz(~signr);
108 #else
109 for (bitno = 0; bitno < 32; bitno++)
110 {
111 if (signr & (1<<bitno)) break;
112 }
113 signr = bitno;
114 #endif
115 current->signal &= ~(1<<signr);
116 sa = current->sig->action + signr;
117 signr++;
118 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
119 current->exit_code = signr;
120 current->state = TASK_STOPPED;
121 notify_parent(current);
122 schedule();
123 if (!(signr = current->exit_code))
124 continue;
125 current->exit_code = 0;
126 if (signr == SIGSTOP)
127 continue;
128 if (_S(signr) & current->blocked) {
129 current->signal |= _S(signr);
130 continue;
131 }
132 sa = current->sig->action + signr - 1;
133 }
134 if (sa->sa_handler == SIG_IGN) {
135 if (signr != SIGCHLD)
136 continue;
137
138 while (sys_waitpid(-1,NULL,WNOHANG) > 0)
139 ;
140 continue;
141 }
142 if (sa->sa_handler == SIG_DFL) {
143 if (current->pid == 1)
144 continue;
145 switch (signr) {
146 case SIGCONT: case SIGCHLD: case SIGWINCH:
147 continue;
148
149 case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
150 if (current->flags & PF_PTRACED)
151 continue;
152 current->state = TASK_STOPPED;
153 current->exit_code = signr;
154 if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
155 SA_NOCLDSTOP))
156 notify_parent(current);
157 schedule();
158 continue;
159
160 case SIGQUIT: case SIGILL: case SIGTRAP:
161 case SIGIOT: case SIGFPE: case SIGSEGV:
162 if (current->binfmt && current->binfmt->core_dump) {
163 if (current->binfmt->core_dump(signr, regs))
164 signr |= 0x80;
165 }
166
167 default:
168 current->signal |= _S(signr & 0x7f);
169 current->flags |= PF_SIGNALED;
170 do_exit(signr);
171 }
172 }
173
174
175
176 if ((int)regs->orig_gpr3 >= 0) {
177 if ((int)regs->result == -ERESTARTNOHAND ||
178 ((int)regs->result == -ERESTARTSYS && !(sa->sa_flags & SA_RESTART)))
179 (int)regs->result = -EINTR;
180 }
181 handler_signal |= 1 << (signr-1);
182 mask &= ~sa->sa_mask;
183 }
184 if (!handler_signal)
185 {
186 _enable_interrupts(s);
187 return 0;
188 }
189 nip = regs->nip;
190 frame = (unsigned long *) regs->gpr[1];
191
192 frame -= 2;
193 trampoline = frame;
194 trampoline[0] = 0x38007777;
195 trampoline[1] = 0x44000002;
196 frame -= sizeof(*regs) / sizeof(long);
197 regs_ptr = frame;
198 memcpy(regs_ptr, regs, sizeof(*regs));
199 signr = 1;
200 sa = current->sig->action;
201 for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
202 if (mask > handler_signal)
203 break;
204 if (!(mask & handler_signal))
205 continue;
206 frame -= sizeof(struct sigcontext_struct) / sizeof(long);
207 sc = (struct sigcontext_struct *)frame;
208 nip = (unsigned long) sa->sa_handler;
209 #if 0
210 nip = *(unsigned long *)nip;
211 #endif
212 if (sa->sa_flags & SA_ONESHOT)
213 sa->sa_handler = NULL;
214 sc->handler = nip;
215 sc->oldmask = current->blocked;
216 sc->regs = (unsigned long)regs_ptr;
217 sc->signal = signr;
218 current->blocked |= sa->sa_mask;
219 regs->gpr[3] = signr;
220 regs->gpr[4] = (unsigned long)regs_ptr;
221 }
222 regs->link = (unsigned long)trampoline;
223 regs->nip = nip;
224 regs->gpr[1] = (unsigned long)sc;
225
226
227
228
229
230
231
232 flush_instruction_cache();
233 _enable_interrupts(s);
234 return 1;
235 }