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 do_exit(signr);
170 }
171 }
172
173
174
175 if ((int)regs->orig_gpr3 >= 0) {
176 if ((int)regs->result == -ERESTARTNOHAND ||
177 ((int)regs->result == -ERESTARTSYS && !(sa->sa_flags & SA_RESTART)))
178 (int)regs->result = -EINTR;
179 }
180 handler_signal |= 1 << (signr-1);
181 mask &= ~sa->sa_mask;
182 }
183 if (!handler_signal)
184 {
185 _enable_interrupts(s);
186 return 0;
187 }
188 nip = regs->nip;
189 frame = (unsigned long *) regs->gpr[1];
190
191 frame -= 2;
192 trampoline = frame;
193 trampoline[0] = 0x38007777;
194 trampoline[1] = 0x44000002;
195 frame -= sizeof(*regs) / sizeof(long);
196 regs_ptr = frame;
197 memcpy(regs_ptr, regs, sizeof(*regs));
198 signr = 1;
199 sa = current->sig->action;
200 for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
201 if (mask > handler_signal)
202 break;
203 if (!(mask & handler_signal))
204 continue;
205 frame -= sizeof(struct sigcontext_struct) / sizeof(long);
206 sc = (struct sigcontext_struct *)frame;
207 nip = (unsigned long) sa->sa_handler;
208 #if 0
209 nip = *(unsigned long *)nip;
210 #endif
211 if (sa->sa_flags & SA_ONESHOT)
212 sa->sa_handler = NULL;
213 sc->handler = nip;
214 sc->oldmask = current->blocked;
215 sc->regs = (unsigned long)regs_ptr;
216 sc->signal = signr;
217 current->blocked |= sa->sa_mask;
218 regs->gpr[3] = signr;
219 regs->gpr[4] = (unsigned long)regs_ptr;
220 }
221 regs->link = (unsigned long)trampoline;
222 regs->nip = nip;
223 regs->gpr[1] = (unsigned long)sc;
224
225
226
227
228
229
230
231 flush_instruction_cache();
232 _enable_interrupts(s);
233 return 1;
234 }