1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
|
All what you never wanted to know about sigaction(),
struct sigaction, and sigset_t.
Before vda started messing with sigset_t, struct sigaction
and sigaction() functions, things looked this way:
Structures
MIPS:
Ignoring bogus "#if defined(__mips__) ..." block in
libc/sysdeps/linux/common/bits/kernel_sigaction.h
and using
libc/sysdeps/linux/mips/bits/kernel_sigaction.h
as an authoritative source:
HAVE_SA_RESTORER is #defined
struct old_kernel_sigaction {
unsigned sa_flags;
sighandler_t k_sa_handler;
unsigned long sa_mask;
unsigned pad0[3]; /* reserved, keep size constant */
/* Abi says here follows reserved int[2] */
void (*sa_restorer)(void);
#if (_MIPS_SZPTR < 64)
/* For 32 bit code we have to pad struct sigaction to get
* constant size for the ABI */
int pad1[1]; /* reserved */
#endif
};
struct kernel_sigaction {
unsigned int sa_flags;
sighandler_t k_sa_handler;
kernel_sigset_t sa_mask;
void (*sa_restorer)(void);
int s_resv[1]; /* reserved */
};
struct sigaction {
unsigned sa_flags;
sighandler_t sa_handler;
sigset_t sa_mask;
/* The ABI says here are two unused ints following. */
/* Restore handler. */
void (*sa_restorer)(void);
#if _MIPS_SZPTR < 64
int sa_resv[1];
#endif
};
IA64:
Has no old_sigaction. What a relief.
struct kernel_sigaction {
sighandler_t k_sa_handler;
unsigned long sa_flags;
sigset_t sa_mask;
};
struct sigaction {
sighandler_t sa_handler;
unsigned long sa_flags;
sigset_t sa_mask;
};
Alpha:
struct old_kernel_sigaction {
sighandler_t k_sa_handler;
unsigned long sa_mask;
unsigned sa_flags;
};
struct kernel_sigaction {
sighandler_t k_sa_handler;
unsigned sa_flags;
sigset_t sa_mask;
};
struct sigaction {
sighandler_t sa_handler;
sigset_t sa_mask;
unsigned sa_flags;
};
HPPA:
struct kernel_sigaction {
sighandler_t k_sa_handler;
unsigned long sa_flags;
sigset_t sa_mask;
};
struct sigaction {
sighandler_t sa_handler;
unsigned long sa_flags;
sigset_t sa_mask;
};
The rest, kernel side:
HAVE_SA_RESTORER #defined
struct old_kernel_sigaction {
sighandler_t k_sa_handler;
unsigned long sa_mask;
unsigned long sa_flags;
void (*sa_restorer)(void);
};
struct kernel_sigaction {
sighandler_t k_sa_handler;
unsigned long sa_flags;
void (*sa_restorer)(void);
sigset_t sa_mask;
};
On userspace side, Sparc has special struct sigaction:
struct sigaction {
sighandler_t sa_handler;
sigset_t sa_mask;
unsigned long sa_flags;
void (*sa_restorer)(void); /* Not used by Linux/Sparc */
};
And finally the rest has:
struct sigaction {
sighandler_t sa_handler;
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
Userspace sigset_t was uniformly defined as vector of longs
big enough to hold 1024 (!) bits - carried over from glibc.
Since the only arch whose struct kernel_sigaction contains sa_mask
not as a last member is MIPS, MIPS has special kernel_sigset_t,
which is an array of longs long enough for 128 bits.
Other arches still used userspace sigset_t in struct kernel_sigaction,
but it did not really matter because overlong kernel_sigaction
does not hurt in sigaction() [explained below].
On kernel side, all arches define _NSIG to 65 (meaning
there are 64 signals, 1..64) except MIPS, which define it to 129.
Functions
sigaction() [libc function] usually has two kernel_sigaction's
on stack and copy (userspace) struct sigaction members into
first one, executes syscall, then pulls out the result from
second one. This accomodates differences in layouts of structs.
The only typically present quirk is what to do with sa_restorer.
libc/sysdeps/linux/arm/sigaction.c
if HAVE_SA_RESTORER and (sa_flags & SA_RESTORER) is not set,
sets sa_restorer to
(flags & SA_SIGINFO) ? __default_rt_sa_restorer : __default_sa_restorer,
and sets SA_RESTORER,
otherwise passes it as-is. Which is kinda strange, because AFAICS
HAVE_SA_RESTORER is *not* defined for ARM.
libc/sysdeps/linux/i386/sigaction.c
Forcibly sets SA_RESTORER and sa_restorer:
kact.sa_flags = act->sa_flags | SA_RESTORER;
kact.sa_restorer = ((act->sa_flags & SA_SIGINFO) ? &restore_rt : &restore);
libc/sysdeps/linux/x86_64/sigaction.c
Forcibly sets SA_RESTORER and sa_restorer:
kact.sa_flags = act->sa_flags | SA_RESTORER;
kact.sa_restorer = &restore_rt;
libc/sysdeps/linux/mips/sigaction.c
# ifdef HAVE_SA_RESTORER
# if _MIPS_SIM == _ABIO32
kact.sa_restorer = act->sa_restorer;
# else
kact.sa_restorer = &restore_rt;
# endif
# endif
No confusion here, HAVE_SA_RESTORER is #defined for MIPS
libc/sysdeps/linux/avr32/sigaction.c
if (kact.sa_flags & SA_RESTORER) {
kact.sa_restorer = act->sa_restorer;
} else {
kact.sa_restorer = __default_rt_sa_restorer;
kact.sa_flags |= SA_RESTORER;
}
Does not check HAVE_SA_RESTORER, but avr32 falls
in "completely ordinary" category on both kernel and
userspace sides, and those have it defined.
libc/sysdeps/linux/xtensa/sigaction.c
if (kact.sa_flags & SA_RESTORER) {
kact.sa_restorer = act->sa_restorer;
} else {
kact.sa_restorer = __default_sa_restorer;
kact.sa_flags |= SA_RESTORER;
}
Thus, similar to avr32.
libc/signal/sigaction.c (i.e. the all other arches)
# ifdef HAVE_SA_RESTORER
kact.sa_restorer = act->sa_restorer;
# endif
Plain translation, just sa_restorer copy is protected
by HAVE_SA_RESTORER #define check. Looks like here
HAVE_SA_RESTORER will be undef'ed only for IA64,
Alpha an HPPA.
Proposed overhaul past 0.9.30
Since we can define libc-side structures at will:
make sigset_t and struct sigaction identical on kernel side and libc side
within each arch. If arches do not need special handling of sa_restorer,
then sigaction() can directly use passed struct sigaction as-is.
Otherwise, a copy is still needed, although sigaction() might have
just one struct kernel_sigaction on stack and use it both for passing
data to kernel and for receiving it back. Might save a few bytes.
To this effect:
* Make sigset_t size match kernel side on all arches.
This is easy since all arches have 64 signals and only MIPS has 128.
* Modify libc/sysdeps/linux/$ARCH/bits/sigaction.h
so that its struct sigaction matches kernel's. If sa_restorer
field is present in libc but is missing in kernel_sigaction,
add it at the bottom in order to not mess up kernel_sigaction layout.
* Modify libc/sysdeps/linux/$ARCH/sigaction.c
to implement the logic above. In "common" pseudo-arch
(libc/signal/sigaction.c file),
we would not even need to do any copying, as described above.
* Document discovered arch quirks while debugging this mess.
* Deal with old_kernel_sigaction later.
|