• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef _SIGNAL_PORTABLE_H_
18 #define _SIGNAL_PORTABLE_H_
19 
20 #if (__mips__)
21 
22 #include <portability.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 
27 struct stack_t_portable {
28   void *ss_sp;
29   int ss_flags;
30   size_t ss_size;
31 };
32 
stack_t_pton(const struct stack_t_portable * ptr_p,stack_t * ptr_n)33 static inline void stack_t_pton(const struct stack_t_portable *ptr_p, stack_t *ptr_n) {
34   memset(ptr_n, '\0', sizeof(stack_t));
35   ptr_n->ss_sp    = ptr_p->ss_sp;
36   ptr_n->ss_flags = ptr_p->ss_flags;
37   ptr_n->ss_size  = ptr_p->ss_size;
38 }
39 
stack_t_ntop(const stack_t * ptr_n,struct stack_t_portable * ptr_p)40 static inline void stack_t_ntop(const stack_t *ptr_n, struct stack_t_portable *ptr_p) {
41   memset(ptr_p, '\0', sizeof(struct stack_t_portable));
42   ptr_p->ss_sp    = ptr_n->ss_sp;
43   ptr_p->ss_flags = ptr_n->ss_flags;
44   ptr_p->ss_size  = ptr_n->ss_size;
45 }
46 
WRAP(sigaltstack)47 int WRAP(sigaltstack)(const struct stack_t_portable *ss, struct stack_t_portable *oss) {
48   stack_t ss_n, oss_n;
49   if (ss != NULL) {
50     stack_t_pton(ss, &ss_n);
51     if (oss != NULL){
52       int ret = REAL(sigaltstack)(&ss_n, &oss_n);
53       stack_t_ntop(&oss_n, oss);
54       return ret;
55     }
56     else
57       return REAL(sigaltstack)(&ss_n, NULL);
58   }
59   else if (oss != NULL) {
60     int ret = REAL(sigaltstack)(NULL, &oss_n);
61     stack_t_ntop(&oss_n, oss);
62     return ret;
63   }
64   else
65     return REAL(sigaltstack)(NULL, NULL);
66 }
67 
68 #define SIGHUP_PORTABLE 1
69 #define SIGINT_PORTABLE 2
70 #define SIGQUIT_PORTABLE 3
71 #define SIGILL_PORTABLE 4
72 #define SIGTRAP_PORTABLE 5
73 #define SIGABRT_PORTABLE 6
74 #define SIGIOT_PORTABLE 6
75 #define SIGBUS_PORTABLE 7
76 #define SIGFPE_PORTABLE 8
77 #define SIGKILL_PORTABLE 9
78 #define SIGUSR1_PORTABLE 10
79 #define SIGSEGV_PORTABLE 11
80 #define SIGUSR2_PORTABLE 12
81 #define SIGPIPE_PORTABLE 13
82 #define SIGALRM_PORTABLE 14
83 #define SIGTERM_PORTABLE 15
84 // unsupported in MIPS
85 #define SIGSTKFLT_PORTABLE 16
86 //
87 #define SIGCHLD_PORTABLE 17
88 #define SIGCONT_PORTABLE 18
89 #define SIGSTOP_PORTABLE 19
90 #define SIGTSTP_PORTABLE 20
91 #define SIGTTIN_PORTABLE 21
92 #define SIGTTOU_PORTABLE 22
93 #define SIGURG_PORTABLE 23
94 #define SIGXCPU_PORTABLE 24
95 #define SIGXFSZ_PORTABLE 25
96 #define SIGVTALRM_PORTABLE 26
97 #define SIGPROF_PORTABLE 27
98 #define SIGWINCH_PORTABLE 28
99 #define SIGIO_PORTABLE 29
100 #define SIGPOLL_PORTABLE SIGIO_PORTABLE
101 #define SIGPWR_PORTABLE 30
102 #define SIGSYS_PORTABLE 31
103 #define SIGUNUSED_PORTABLE 31
104 // unsupported in MIPS
105 #define SIGSWI_PORTABLE 32
106 //
107 
signo_pton(int signum_p)108 static inline int signo_pton(int signum_p) {
109   switch(signum_p) {
110     case SIGHUP_PORTABLE: return SIGHUP;
111     case SIGINT_PORTABLE: return SIGINT;
112     case SIGQUIT_PORTABLE: return SIGQUIT;
113     case SIGILL_PORTABLE: return SIGILL;
114     case SIGTRAP_PORTABLE: return SIGTRAP;
115     case SIGABRT_PORTABLE: return SIGABRT;
116     case SIGBUS_PORTABLE: return SIGBUS;
117     case SIGFPE_PORTABLE: return SIGFPE;
118     case SIGKILL_PORTABLE: return SIGKILL;
119     case SIGUSR1_PORTABLE: return SIGUSR1;
120     case SIGSEGV_PORTABLE: return SIGSEGV;
121     case SIGUSR2_PORTABLE: return SIGUSR2;
122     case SIGPIPE_PORTABLE: return SIGPIPE;
123     case SIGALRM_PORTABLE: return SIGALRM;
124     case SIGTERM_PORTABLE: return SIGTERM;
125     case SIGCHLD_PORTABLE: return SIGCHLD;
126     case SIGCONT_PORTABLE: return SIGCONT;
127     case SIGSTOP_PORTABLE: return SIGSTOP;
128     case SIGTSTP_PORTABLE: return SIGTSTP;
129     case SIGTTIN_PORTABLE: return SIGTTIN;
130     case SIGTTOU_PORTABLE: return SIGTTOU;
131     case SIGURG_PORTABLE: return SIGURG;
132     case SIGXCPU_PORTABLE: return SIGXCPU;
133     case SIGXFSZ_PORTABLE: return SIGXFSZ;
134     case SIGVTALRM_PORTABLE: return SIGVTALRM;
135     case SIGPROF_PORTABLE: return SIGPROF;
136     case SIGWINCH_PORTABLE: return SIGWINCH;
137     case SIGIO_PORTABLE: return SIGIO;
138     case SIGPWR_PORTABLE: return SIGPWR;
139     case SIGSYS_PORTABLE: return SIGSYS;
140     default:
141       fprintf(stderr, "Unknown SIGNAL:%d\n", signum_p);
142       abort();
143   }
144 }
145 
signo_ntop(int signum_n)146 static inline int signo_ntop(int signum_n) {
147   switch(signum_n) {
148     case SIGHUP: return SIGHUP_PORTABLE;
149     case SIGINT: return SIGINT_PORTABLE;
150     case SIGQUIT: return SIGQUIT_PORTABLE;
151     case SIGILL: return SIGILL_PORTABLE;
152     case SIGTRAP: return SIGTRAP_PORTABLE;
153     case SIGABRT: return SIGABRT_PORTABLE;
154     case SIGBUS: return SIGBUS_PORTABLE;
155     case SIGFPE: return SIGFPE_PORTABLE;
156     case SIGKILL: return SIGKILL_PORTABLE;
157     case SIGUSR1: return SIGUSR1_PORTABLE;
158     case SIGSEGV: return SIGSEGV_PORTABLE;
159     case SIGUSR2: return SIGUSR2_PORTABLE;
160     case SIGPIPE: return SIGPIPE_PORTABLE;
161     case SIGALRM: return SIGALRM_PORTABLE;
162     case SIGTERM: return SIGTERM_PORTABLE;
163     case SIGCHLD: return SIGCHLD_PORTABLE;
164     case SIGCONT: return SIGCONT_PORTABLE;
165     case SIGSTOP: return SIGSTOP_PORTABLE;
166     case SIGTSTP: return SIGTSTP_PORTABLE;
167     case SIGTTIN: return SIGTTIN_PORTABLE;
168     case SIGTTOU: return SIGTTOU_PORTABLE;
169     case SIGURG: return SIGURG_PORTABLE;
170     case SIGXCPU: return SIGXCPU_PORTABLE;
171     case SIGXFSZ: return SIGXFSZ_PORTABLE;
172     case SIGVTALRM: return SIGVTALRM_PORTABLE;
173     case SIGPROF: return SIGPROF_PORTABLE;
174     case SIGWINCH: return SIGWINCH_PORTABLE;
175     case SIGIO: return SIGIO_PORTABLE;
176     case SIGPWR: return SIGPWR_PORTABLE;
177     case SIGSYS: return SIGSYS_PORTABLE;
178     default:
179       fprintf(stderr, "Unknown SIGNAL:%d\n", signum_n);
180       abort();
181   }
182 }
183 
184 #define SA_NOCLDSTOP_PORTABLE 0x00000001
185 #define SA_NOCLDWAIT_PORTABLE 0x00000002
186 #define SA_SIGINFO_PORTABLE 0x00000004
187 // unsupported in MIPS
188 #define SA_THIRTYTWO_PORTABLE 0x02000000
189 #define SA_RESTORER_PORTABLE 0x04000000
190 //
191 #define SA_ONSTACK_PORTABLE 0x08000000
192 #define SA_RESTART_PORTABLE 0x10000000
193 #define SA_NODEFER_PORTABLE 0x40000000
194 #define SA_RESETHAND_PORTABLE 0x80000000
195 #define SA_NOMASK_PORTABLE SA_NODEFER_PORTABLE
196 #define SA_ONESHOT_PORTABLE SA_RESETHAND_PORTABLE
197 
sa_flags_pton(int sa_flags_p)198 static inline int sa_flags_pton(int sa_flags_p) {
199   int sa_flags_n = 0;
200   sa_flags_n |= (sa_flags_p & SA_NOCLDSTOP_PORTABLE) ? SA_NOCLDSTOP : 0;
201   sa_flags_n |= (sa_flags_p & SA_NOCLDWAIT_PORTABLE) ? SA_NOCLDWAIT : 0;
202   sa_flags_n |= (sa_flags_p & SA_SIGINFO_PORTABLE) ? SA_SIGINFO : 0;
203   sa_flags_n |= (sa_flags_p & SA_ONSTACK_PORTABLE) ? SA_ONSTACK : 0;
204   sa_flags_n |= (sa_flags_p & SA_RESTART_PORTABLE) ? SA_RESTART : 0;
205   sa_flags_n |= (sa_flags_p & SA_NODEFER_PORTABLE) ? SA_NODEFER : 0;
206   sa_flags_n |= (sa_flags_p & SA_RESETHAND_PORTABLE) ? SA_RESETHAND : 0;
207   return sa_flags_n;
208 }
209 
sa_flags_ntop(int sa_flags_n)210 static inline int sa_flags_ntop(int sa_flags_n) {
211   int sa_flags_p = 0;
212   sa_flags_p |= (sa_flags_n & SA_NOCLDSTOP) ? SA_NOCLDSTOP_PORTABLE : 0;
213   sa_flags_p |= (sa_flags_n & SA_NOCLDWAIT) ? SA_NOCLDWAIT_PORTABLE : 0;
214   sa_flags_p |= (sa_flags_n & SA_SIGINFO) ? SA_SIGINFO_PORTABLE : 0;
215   sa_flags_p |= (sa_flags_n & SA_ONSTACK) ? SA_ONSTACK_PORTABLE : 0;
216   sa_flags_p |= (sa_flags_n & SA_RESTART) ? SA_RESTART_PORTABLE : 0;
217   sa_flags_p |= (sa_flags_n & SA_NODEFER) ? SA_NODEFER_PORTABLE : 0;
218   sa_flags_p |= (sa_flags_n & SA_RESETHAND) ? SA_RESETHAND_PORTABLE : 0;
219   return sa_flags_p;
220 }
221 
222 typedef unsigned long  sigset_t_portable;
223 struct sigaction_portable {
224   union {
225     __sighandler_t _sa_handler;
226     void (*_sa_sigaction)(int, struct siginfo *, void *);
227   } _u;
228   sigset_t_portable sa_mask;
229   unsigned long sa_flags;
230   void (*sa_restorer)(void); // obsolete
231 };
232 
sigset_t_pton(const sigset_t_portable * ptr_p,sigset_t * ptr_n)233 static inline void sigset_t_pton(const sigset_t_portable *ptr_p, sigset_t *ptr_n) {
234   memset(ptr_n, '\0', sizeof(sigset_t));
235   ptr_n->sig[0] = *ptr_p;
236 }
237 
sigset_t_ntop(const sigset_t * ptr_n,sigset_t_portable * ptr_p)238 static inline void sigset_t_ntop(const sigset_t *ptr_n, sigset_t_portable *ptr_p) {
239   memset(ptr_p, '\0', sizeof(sigset_t_portable));
240   *ptr_p = ptr_n->sig[0];
241 }
242 
sigaction_pton(const struct sigaction_portable * ptr_p,struct sigaction * ptr_n)243 static inline void sigaction_pton(const struct sigaction_portable *ptr_p, struct sigaction *ptr_n) {
244   memset(ptr_n, '\0', sizeof(struct sigaction));
245   ptr_n->sa_sigaction = ptr_p->_u._sa_sigaction;
246   sigset_t_pton(&ptr_p->sa_mask, &ptr_n->sa_mask);
247   ptr_n->sa_flags       = sa_flags_pton(ptr_p->sa_flags);
248 }
249 
sigaction_ntop(const struct sigaction * ptr_n,struct sigaction_portable * ptr_p)250 static inline void sigaction_ntop(const struct sigaction *ptr_n, struct sigaction_portable *ptr_p) {
251   memset(ptr_p, '\0', sizeof(struct sigaction_portable));
252   ptr_p->_u._sa_sigaction = ptr_n->sa_sigaction;
253   sigset_t_ntop(&ptr_n->sa_mask, &ptr_p->sa_mask);
254   ptr_p->sa_flags      = sa_flags_ntop(ptr_n->sa_flags);
255 }
256 
WRAP(sigaction)257 int WRAP(sigaction)(int signum, const struct sigaction_portable *act, struct sigaction_portable *oldact) {
258   struct sigaction act_n, oldact_n;
259   int signum_n = signo_pton(signum);
260 
261   if (act != NULL) {
262     sigaction_pton(act, &act_n);
263     if (oldact != NULL) {
264       int ret = REAL(sigaction)(signum_n, &act_n, &oldact_n);
265       sigaction_ntop(&oldact_n, oldact);
266       return ret;
267     }
268     else
269       return REAL(sigaction)(signum_n, &act_n, NULL);
270   }
271   else if (oldact != NULL) {
272     int ret = REAL(sigaction)(signum_n, NULL, &oldact_n);
273     sigaction_ntop(&oldact_n, oldact);
274     return ret;
275   }
276   else
277     return REAL(sigaction)(signum_n, NULL, NULL);
278 }
279 
WRAP(sigaddset)280 int WRAP(sigaddset)(sigset_t_portable *set, int signum) {
281   int signum_n = signo_pton(signum);
282   sigset_t set_n;
283   sigset_t_pton(set, &set_n);
284   int ret = REAL(sigaddset)(&set_n, signum_n);
285   sigset_t_ntop(&set_n, set);
286   return ret;
287 }
288 
WRAP(sigdelset)289 int WRAP(sigdelset)(sigset_t_portable *set, int signum) {
290   int signum_n = signo_pton(signum);
291   sigset_t set_n;
292   sigset_t_pton(set, &set_n);
293   int ret = REAL(sigdelset)(&set_n, signum_n);
294   sigset_t_ntop(&set_n, set);
295   return ret;
296 }
297 
WRAP(sigemptyset)298 int WRAP(sigemptyset)(sigset_t_portable *set){
299   sigset_t set_n;
300   sigset_t_pton(set, &set_n);
301   int ret = REAL(sigemptyset)(&set_n);
302   sigset_t_ntop(&set_n, set);
303   return ret;
304 }
305 
WRAP(sigfillset)306 int WRAP(sigfillset)(sigset_t_portable *set){
307   sigset_t set_n;
308   sigset_t_pton(set, &set_n);
309   int ret = REAL(sigfillset)(&set_n);
310   sigset_t_ntop(&set_n, set);
311   return ret;
312 }
313 
WRAP(sigismember)314 int WRAP(sigismember)(const sigset_t_portable *set, int signum) {
315   int signum_n = signo_pton(signum);
316   sigset_t set_n;
317   sigset_t_pton(set, &set_n);
318   return REAL(sigismember)(&set_n, signum_n);
319 }
320 
WRAP(sigpending)321 int WRAP(sigpending)(sigset_t_portable *set) {
322   sigset_t set_n;
323   sigset_t_pton(set, &set_n);
324   int ret = REAL(sigpending)(&set_n);
325   sigset_t_ntop(&set_n, set);
326   return ret;
327 }
328 
329 #define SIG_BLOCK_PORTABLE 0
330 #define SIG_UNBLOCK_PORTABLE 1
331 #define SIG_SETMASK_PORTABLE 2
332 
WRAP(sigprocmask)333 int WRAP(sigprocmask)(int how, const sigset_t_portable *set, sigset_t_portable *oldset) {
334   int how_n;
335   switch(how) {
336     case SIG_BLOCK_PORTABLE: how_n =  SIG_BLOCK; break;
337     case SIG_UNBLOCK_PORTABLE: how_n = SIG_UNBLOCK; break;
338     case SIG_SETMASK_PORTABLE: how_n = SIG_SETMASK; break;
339     default:
340       fprintf(stderr, "Unknown sigprocmask action:%d\n", how);
341       abort();
342   }
343   sigset_t set_n, oldset_n;
344   if (set != NULL) {
345     sigset_t_pton(set, &set_n);
346     if (oldset != NULL) {
347       int ret = REAL(sigprocmask)(how_n, &set_n, &oldset_n);
348       sigset_t_ntop(&oldset_n, oldset);
349       return ret;
350     }
351     else
352       return REAL(sigprocmask)(how_n, &set_n, NULL);
353   }
354   else if (oldset != NULL) {
355     int ret = REAL(sigprocmask)(how_n, NULL, &oldset_n);
356     sigset_t_ntop(&oldset_n, oldset);
357     return ret;
358   }
359   else
360     return REAL(sigprocmask)(how_n, NULL, NULL);
361 }
362 
WRAP(sigsuspend)363 int WRAP(sigsuspend)(const sigset_t_portable *mask) {
364   sigset_t mask_n;
365   sigset_t_pton(mask, &mask_n);
366   return REAL(sigsuspend)(&mask_n);
367 }
368 
WRAP(sigwait)369 int WRAP(sigwait)(const sigset_t_portable *set, int *sig) {
370   sigset_t set_n;
371   sigset_t_pton(set, &set_n);
372   int ret = REAL(sigwait)(&set_n, sig);
373   *sig = signo_ntop(*sig);
374   return ret;
375 }
376 
WRAP(kill)377 int WRAP(kill)(pid_t pid, int sig) {
378   int sig_n = signo_pton(sig);
379   return REAL(kill)(pid, sig_n);
380 }
381 
382 // sigset_t related function
383 #include <sys/select.h>
WRAP(pselect)384 int WRAP(pselect)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t_portable *sigmask) {
385   sigset_t sigmask_n;
386   sigset_t_pton(sigmask, &sigmask_n);
387   return  REAL(pselect)(nfds, readfds, writefds, exceptfds, timeout, sigmask_n);
388 }
389 
390 #include <sys/signalfd.h>
WRAP(signalfd)391 int WRAP(signalfd)(int fd, const sigset_t_portable* mask, int flags) {
392   sigset_t mask_n;
393   sigset_t_pton(mask, &mask_n);
394   return REAL(signalfd)(fd, mask_n, flags);
395 }
396 
397 #include <poll.h>
WRAP(ppoll)398 int WRAP(ppoll)(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts, const sigset_t_portable *sigmask) {
399   sigset_t sigmask_n;
400   sigset_t_pton(sigmask, &sigmask_n);
401   return REAL(ppoll)(fds, nfds, timeout_ts, sigmask_n);
402 }
403 
404 #include <pthread.h>
WRAP(pthread_sigmask)405 int WRAP(pthread_sigmask)(int how, const sigset_t_portable *set, sigset_t_portable *oldset) {
406   int how_n;
407   switch(how) {
408     case SIG_BLOCK_PORTABLE: how_n =  SIG_BLOCK; break;
409     case SIG_UNBLOCK_PORTABLE: how_n = SIG_UNBLOCK; break;
410     case SIG_SETMASK_PORTABLE: how_n = SIG_SETMASK; break;
411     default:
412       fprintf(stderr, "Unknown pthread_sigmask action:%d\n", how);
413       abort();
414   }
415   sigset_t set_n, oldset_n;
416   if (set != NULL) {
417     sigset_t_pton(set, &set_n);
418     if (oldset != NULL) {
419       int ret = REAL(pthread_sigmask)(how_n, &set_n, &oldset_n);
420       sigset_t_ntop(&oldset_n, oldset);
421       return ret;
422     }
423     else
424       return REAL(pthread_sigmask)(how_n, &set_n, NULL);
425   }
426   else if (oldset != NULL) {
427     int ret = REAL(pthread_sigmask)(how_n, NULL, &oldset_n);
428     sigset_t_ntop(&oldset_n, oldset);
429     return ret;
430   }
431   else
432     return REAL(pthread_sigmask)(how_n, NULL, NULL);
433 }
434 
435 #include <sys/epoll.h>
WRAP(epoll_pwait)436 int WRAP(epoll_pwait)(int fd, struct epoll_event* events, int max_events, int timeout, const sigset_t_portable* ss) {
437   sigset_t ss_n;
438   sigset_t_pton(ss, &ss_n);
439   return REAL(epoll_pwait)(fd, events, max_events, timeout, ss_n);
440 }
441 #endif /* __mips__ */
442 #endif /* _SIGNAL_PORTABLE_H */
443