]>
Commit | Line | Data |
---|---|---|
fd26970f | 1 | /* POSIX.1 sigaction call for Linux/SPARC. |
0ecb606c | 2 | Copyright (C) 1997-2000,2002,2003,2005 Free Software Foundation, Inc. |
fd26970f UD |
3 | This file is part of the GNU C Library. |
4 | Contributed by Miguel de Icaza (miguel@nuclecu.unam.mx), 1997. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
7 | modify it under the terms of the GNU Lesser General Public |
8 | License as published by the Free Software Foundation; either | |
9 | version 2.1 of the License, or (at your option) any later version. | |
fd26970f UD |
10 | |
11 | The GNU C Library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 14 | Lesser General Public License for more details. |
fd26970f | 15 | |
41bdb6e2 AJ |
16 | You should have received a copy of the GNU Lesser General Public |
17 | License along with the GNU C Library; if not, write to the Free | |
18 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
19 | 02111-1307 USA. */ | |
fd26970f | 20 | |
99e46354 | 21 | #include <string.h> |
fd26970f UD |
22 | #include <syscall.h> |
23 | #include <sys/signal.h> | |
24 | #include <errno.h> | |
4194bc66 | 25 | #include <kernel_sigaction.h> |
b5bc52ef | 26 | #include <sysdep.h> |
9c4c0024 UD |
27 | |
28 | static void __rt_sigreturn_stub (void); | |
29 | static void __sigreturn_stub (void); | |
30 | ||
4775243a UD |
31 | /* The variable is shared between all wrappers around signal handling |
32 | functions which have RT equivalents. */ | |
2d4a30ce | 33 | int __libc_missing_rt_sigs; |
4775243a | 34 | |
fd26970f | 35 | int |
c0f53cdd UD |
36 | __libc_sigaction (int sig, __const struct sigaction *act, |
37 | struct sigaction *oact) | |
fd26970f | 38 | { |
9c4c0024 | 39 | struct old_kernel_sigaction k_sigact, k_osigact; |
fd26970f | 40 | int ret; |
9c4c0024 | 41 | |
655b26bb | 42 | #ifdef __NR_rt_sigaction |
9c4c0024 UD |
43 | /* First try the RT signals. */ |
44 | if (!__libc_missing_rt_sigs) | |
45 | { | |
46 | struct kernel_sigaction kact, koact; | |
47 | unsigned long stub = 0; | |
48 | int saved_errno = errno; | |
49 | ||
50 | if (act) | |
51 | { | |
52 | kact.k_sa_handler = act->sa_handler; | |
53 | memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t)); | |
54 | if (((kact.sa_flags = act->sa_flags) & SA_SIGINFO) != 0) | |
55 | stub = (unsigned long) &__rt_sigreturn_stub; | |
56 | else | |
57 | stub = (unsigned long) &__sigreturn_stub; | |
58 | stub -= 8; | |
59 | kact.sa_restorer = NULL; | |
60 | } | |
61 | ||
62 | /* XXX The size argument hopefully will have to be changed to the | |
63 | real size of the user-level sigset_t. */ | |
b5bc52ef UD |
64 | ret = INLINE_SYSCALL (rt_sigaction, 5, sig, act ? &kact : 0, |
65 | oact ? &koact : 0, stub, _NSIG / 8); | |
9c4c0024 UD |
66 | |
67 | if (ret >= 0 || errno != ENOSYS) | |
68 | { | |
69 | if (oact && ret >= 0) | |
70 | { | |
71 | oact->sa_handler = koact.k_sa_handler; | |
72 | memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t)); | |
73 | oact->sa_flags = koact.sa_flags; | |
74 | oact->sa_restorer = koact.sa_restorer; | |
75 | } | |
76 | return ret; | |
77 | } | |
78 | ||
79 | __set_errno (saved_errno); | |
80 | __libc_missing_rt_sigs = 1; | |
81 | } | |
655b26bb | 82 | #endif |
fd26970f | 83 | |
4194bc66 | 84 | /* Magic to tell the kernel we are using "new-style" signals, in that |
bf47fa23 | 85 | the signal table is not kept in userspace. Not the same as the |
4194bc66 RH |
86 | really-new-style rt signals. */ |
87 | sig = -sig; | |
88 | ||
89 | if (act) | |
fd26970f | 90 | { |
bf47fa23 | 91 | k_sigact.k_sa_handler = act->sa_handler; |
9c4c0024 | 92 | k_sigact.sa_mask = act->sa_mask.__val[0]; |
4194bc66 | 93 | k_sigact.sa_flags = act->sa_flags; |
9c4c0024 | 94 | k_sigact.sa_restorer = NULL; |
fd26970f | 95 | } |
4194bc66 RH |
96 | |
97 | { | |
98 | register int r_syscallnr __asm__("%g1") = __NR_sigaction; | |
99 | register int r_sig __asm__("%o0") = sig; | |
9c4c0024 UD |
100 | register struct old_kernel_sigaction *r_act __asm__("%o1"); |
101 | register struct old_kernel_sigaction *r_oact __asm__("%o2"); | |
4194bc66 RH |
102 | |
103 | r_act = act ? &k_sigact : NULL; | |
104 | r_oact = oact ? &k_osigact : NULL; | |
105 | ||
106 | __asm__ __volatile__("t 0x10\n\t" | |
107 | "bcc 1f\n\t" | |
108 | " nop\n\t" | |
9c4c0024 | 109 | "sub %%g0,%%o0,%%o0\n" |
4194bc66 RH |
110 | "1:" |
111 | : "=r"(r_sig) | |
112 | : "r"(r_syscallnr), "r"(r_act), "r"(r_oact), | |
113 | "0"(r_sig)); | |
114 | ||
115 | ret = r_sig; | |
116 | } | |
fd26970f | 117 | |
39abffb3 | 118 | if (ret >= 0) |
fd26970f | 119 | { |
39abffb3 UD |
120 | if (oact) |
121 | { | |
122 | oact->sa_handler = k_osigact.k_sa_handler; | |
123 | oact->sa_mask.__val[0] = k_osigact.sa_mask; | |
124 | oact->sa_flags = k_osigact.sa_flags; | |
125 | oact->sa_restorer = NULL; | |
126 | } | |
9c4c0024 | 127 | return ret; |
fd26970f | 128 | } |
fd26970f | 129 | |
fd26970f UD |
130 | __set_errno (-ret); |
131 | return -1; | |
132 | } | |
5ec5c857 | 133 | libc_hidden_def (__libc_sigaction) |
bf293afe | 134 | |
0ecb606c JJ |
135 | #ifdef WRAPPER_INCLUDE |
136 | # include WRAPPER_INCLUDE | |
137 | #endif | |
138 | ||
bf293afe | 139 | #ifndef LIBC_SIGACTION |
ab18b1e1 | 140 | weak_alias (__libc_sigaction, __sigaction); |
37ba7d66 | 141 | libc_hidden_weak (__sigaction) |
c0f53cdd | 142 | weak_alias (__libc_sigaction, sigaction); |
bf293afe | 143 | #endif |
9c4c0024 UD |
144 | |
145 | static void | |
146 | __rt_sigreturn_stub (void) | |
147 | { | |
148 | __asm__ ("mov %0, %%g1\n\t" | |
149 | "ta 0x10\n\t" | |
150 | : /* no outputs */ | |
151 | : "i" (__NR_rt_sigreturn)); | |
152 | } | |
153 | ||
154 | static void | |
155 | __sigreturn_stub (void) | |
156 | { | |
157 | __asm__ ("mov %0, %%g1\n\t" | |
158 | "ta 0x10\n\t" | |
159 | : /* no outputs */ | |
160 | : "i" (__NR_sigreturn)); | |
161 | } |