(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / sysdep-cancel.h
blob8142455781089fe9c52f45b3a057f22e113447fa
1 /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 #include <sysdep.h>
21 #include <tls.h>
22 #ifndef __ASSEMBLER__
23 # include <nptl/pthreadP.h>
24 #endif
26 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
28 # undef PSEUDO
29 # define PSEUDO(name, syscall_name, args) \
30 .text; \
31 ENTRY (name) \
32 L(name##START): \
33 cmpl $0, %gs:MULTIPLE_THREADS_OFFSET; \
34 jne L(pseudo_cancel); \
35 .type __##syscall_name##_nocancel,@function; \
36 .globl __##syscall_name##_nocancel; \
37 __##syscall_name##_nocancel: \
38 DO_CALL (syscall_name, args); \
39 cmpl $-4095, %eax; \
40 jae SYSCALL_ERROR_LABEL; \
41 ret; \
42 .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
43 L(pseudo_cancel): \
44 CENABLE \
45 SAVE_OLDTYPE_##args \
46 PUSHCARGS_##args \
47 DOCARGS_##args \
48 movl $SYS_ify (syscall_name), %eax; \
49 ENTER_KERNEL; \
50 POPCARGS_##args; \
51 POPSTATE_##args \
52 cmpl $-4095, %eax; \
53 jae SYSCALL_ERROR_LABEL; \
54 L(pseudo_end): \
56 /* Create unwinding information for the syscall wrapper. */ \
57 .section .eh_frame,"a",@progbits; \
58 L(STARTFRAME): \
59 /* Length of the CIE. */ \
60 .long L(ENDCIE)-L(STARTCIE); \
61 L(STARTCIE): \
62 /* CIE ID. */ \
63 .long 0; \
64 /* Version number. */ \
65 .byte 1; \
66 /* NUL-terminated augmentation string. */ \
67 AUGMENTATION_STRING; \
68 /* Code alignment factor. */ \
69 .uleb128 1; \
70 /* Data alignment factor. */ \
71 .sleb128 -4; \
72 /* Return address register column. */ \
73 .byte 8; \
74 /* Optional augmentation parameter. */ \
75 AUGMENTATION_PARAM \
76 /* Start of the table initialization. */ \
77 .byte 0xc; /* DW_CFA_def_cfa */ \
78 .uleb128 4; \
79 .uleb128 4; \
80 .byte 0x88; /* DW_CFA_offset, column 0x8 */ \
81 .uleb128 1; \
82 .align 4; \
83 L(ENDCIE): \
84 /* Length of the FDE. */ \
85 .long L(ENDFDE)-L(STARTFDE); \
86 L(STARTFDE): \
87 /* CIE pointer. */ \
88 .long L(STARTFDE)-L(STARTFRAME); \
89 /* Start address of the code. */ \
90 START_SYMBOL_REF (name); \
91 /* Length of the code. */ \
92 .long L(name##END)-L(name##START); \
93 /* Augmentation data. */ \
94 AUGMENTATION_PARAM_FDE \
95 /* The rest of the code depends on the number of parameters the syscall \
96 takes. */ \
97 EH_FRAME_##args(name); \
98 .align 4; \
99 L(ENDFDE): \
100 .previous
102 # ifdef SHARED
103 /* NUL-terminated augmentation string. Note "z" means there is an
104 augmentation value later on. */
105 # define AUGMENTATION_STRING .string "zR"
106 # define AUGMENTATION_PARAM \
107 /* Augmentation value length. */ \
108 .uleb128 1; \
109 /* Encoding: DW_EH_PE_pcrel + DW_EH_PE_sdata4. */ \
110 .byte 0x1b;
111 # define AUGMENTATION_PARAM_FDE \
112 /* No augmentation data. */ \
113 .uleb128 0;
114 # define START_SYMBOL_REF(name) \
115 /* PC-relative start address of the code. */ \
116 .long L(name##START)-.
117 # else
118 /* No augmentation. */
119 # define AUGMENTATION_STRING .ascii "\0"
120 # define AUGMENTATION_PARAM /* nothing */
121 # define AUGMENTATION_PARAM_FDE /* nothing */
122 # define START_SYMBOL_REF(name) \
123 /* Absolute start address of the code. */ \
124 .long L(name##START)
125 # endif
127 /* Callframe description for syscalls without parameters. This is very
128 simple. The only place the stack pointer is changed is when the old
129 cancellation state value is saved. */
130 # define EH_FRAME_0(name) \
131 .byte 0x40+L(PUSHSTATE)-L(name##START); /* DW_CFA_advance_loc+N */ \
132 .byte 14; /* DW_CFA_def_cfa_offset */ \
133 .uleb128 8; \
134 .byte 0x40+L(POPSTATE)-L(PUSHSTATE); /* DW_CFA_advance_loc+N */ \
135 .byte 14; /* DW_CFA_def_cfa_offset */ \
136 .uleb128 4
138 /* For syscalls with one and two parameters the code is the same as for
139 those which take no parameter. */
140 # define EH_FRAME_1(name) \
141 .byte 0x40+L(SAVEBX1)-L(name##START); /* DW_CFA_advance_loc+N */ \
142 .byte 9; /* DW_CFA_register */ \
143 .uleb128 3; /* %ebx */ \
144 .uleb128 2; /* %edx */ \
145 .byte 0x40+L(RESTBX1)-L(SAVEBX1); /* DW_CFA_advance_loc+N */ \
146 .byte 0xc3; /* DW_CFA_restore %ebx */ \
147 .byte 0x40+L(PUSHSTATE)-L(RESTBX1); /* DW_CFA_advance_loc+N */ \
148 .byte 14; /* DW_CFA_def_cfa_offset */ \
149 .uleb128 8; \
150 .byte 0x40+L(SAVEBX2)-L(PUSHSTATE); /* DW_CFA_advance_loc+N */ \
151 .byte 9; /* DW_CFA_register */ \
152 .uleb128 3; /* %ebx */ \
153 .uleb128 2; /* %edx */ \
154 .byte 0x40+L(RESTBX2)-L(SAVEBX2); /* DW_CFA_advance_loc+N */ \
155 .byte 0xc3; /* DW_CFA_restore %ebx */ \
156 .byte 0x40+L(POPSTATE)-L(RESTBX2); /* DW_CFA_advance_loc+N */ \
157 .byte 14; /* DW_CFA_def_cfa_offset */ \
158 .uleb128 4
160 # define EH_FRAME_2(name) EH_FRAME_1 (name)
162 /* For syscalls with three parameters the stack pointer is changed
163 also to save the content of the %ebx register. */
164 # define EH_FRAME_3(name) \
165 .byte 0x40+L(PUSHBX1)-L(name##START); /* DW_CFA_advance_loc+N */ \
166 .byte 14; /* DW_CFA_def_cfa_offset */ \
167 .uleb128 8; \
168 .byte 0x83; /* DW_CFA_offset %ebx */ \
169 .uleb128 2; \
170 .byte 0x40+L(POPBX1)-L(PUSHBX1); /* DW_CFA_advance_loc+N */ \
171 .byte 14; /* DW_CFA_def_cfa_offset */ \
172 .uleb128 4; \
173 .byte 0xc3; /* DW_CFA_restore %ebx */ \
174 .byte 0x40+L(PUSHSTATE)-L(POPBX1); /* DW_CFA_advance_loc+N */ \
175 .byte 14; /* DW_CFA_def_cfa_offset */ \
176 .uleb128 8; \
177 .byte 0x40+L(PUSHBX2)-L(PUSHSTATE); /* DW_CFA_advance_loc+N */ \
178 .byte 14; /* DW_CFA_def_cfa_offset */ \
179 .uleb128 12; \
180 .byte 0x83; /* DW_CFA_offset %ebx */ \
181 .uleb128 3; \
182 .byte 0x40+L(POPBX2)-L(PUSHBX2); /* DW_CFA_advance_loc+N */ \
183 .byte 14; /* DW_CFA_def_cfa_offset */ \
184 .uleb128 8; \
185 .byte 0xc3; /* DW_CFA_restore %ebx */ \
186 .byte 0x40+L(POPSTATE)-L(POPBX2); /* DW_CFA_advance_loc+N */ \
187 .byte 14; /* DW_CFA_def_cfa_offset */ \
188 .uleb128 4
190 /* With four parameters the syscall wrappers have to save %ebx and %esi. */
191 # define EH_FRAME_4(name) \
192 .byte 0x40+L(PUSHSI1)-L(name##START); /* DW_CFA_advance_loc+N */ \
193 .byte 14; /* DW_CFA_def_cfa_offset */ \
194 .uleb128 8; \
195 .byte 0x86; /* DW_CFA_offset %esi */ \
196 .uleb128 2; \
197 .byte 0x40+L(PUSHBX1)-L(PUSHSI1); /* DW_CFA_advance_loc+N */ \
198 .byte 14; /* DW_CFA_def_cfa_offset */ \
199 .uleb128 12; \
200 .byte 0x83; /* DW_CFA_offset %ebx */ \
201 .uleb128 3; \
202 .byte 0x40+L(POPBX1)-L(PUSHBX1); /* DW_CFA_advance_loc+N */ \
203 .byte 14; /* DW_CFA_def_cfa_offset */ \
204 .uleb128 8; \
205 .byte 0xc3; /* DW_CFA_restore %ebx */ \
206 .byte 0x40+L(POPSI1)-L(POPBX1); /* DW_CFA_advance_loc+N */ \
207 .byte 14; /* DW_CFA_def_cfa_offset */ \
208 .uleb128 4; \
209 .byte 0xc6; /* DW_CFA_restore %esi */ \
210 .byte 0x40+L(PUSHSTATE)-L(POPSI1); /* DW_CFA_advance_loc+N */ \
211 .byte 14; /* DW_CFA_def_cfa_offset */ \
212 .uleb128 8; \
213 .byte 0x40+L(PUSHSI2)-L(PUSHSTATE); /* DW_CFA_advance_loc+N */ \
214 .byte 14; /* DW_CFA_def_cfa_offset */ \
215 .uleb128 12; \
216 .byte 0x86; /* DW_CFA_offset %esi */ \
217 .uleb128 3; \
218 .byte 0x40+L(PUSHBX2)-L(PUSHSI2); /* DW_CFA_advance_loc+N */ \
219 .byte 14; /* DW_CFA_def_cfa_offset */ \
220 .uleb128 16; \
221 .byte 0x83; /* DW_CFA_offset %ebx */ \
222 .uleb128 4; \
223 .byte 0x40+L(POPBX2)-L(PUSHBX2); /* DW_CFA_advance_loc+N */ \
224 .byte 14; /* DW_CFA_def_cfa_offset */ \
225 .uleb128 12; \
226 .byte 0xc3; /* DW_CFA_restore %ebx */ \
227 .byte 0x40+L(POPSI2)-L(POPBX2); /* DW_CFA_advance_loc+N */ \
228 .byte 14; /* DW_CFA_def_cfa_offset */ \
229 .uleb128 8; \
230 .byte 0xc6; /* DW_CFA_restore %esi */ \
231 .byte 0x40+L(POPSTATE)-L(POPSI2); /* DW_CFA_advance_loc+N */ \
232 .byte 14; /* DW_CFA_def_cfa_offset */ \
233 .uleb128 4
235 /* With five parameters the syscall wrappers have to save %ebx, %esi,
236 and %edi. */
237 # define EH_FRAME_5(name) \
238 .byte 0x40+L(PUSHDI1)-L(name##START); /* DW_CFA_advance_loc+N */ \
239 .byte 14; /* DW_CFA_def_cfa_offset */ \
240 .uleb128 8; \
241 .byte 0x87; /* DW_CFA_offset %edi */ \
242 .uleb128 2; \
243 .byte 0x40+L(PUSHSI1)-L(PUSHDI1); /* DW_CFA_advance_loc+N */ \
244 .byte 14; /* DW_CFA_def_cfa_offset */ \
245 .uleb128 12; \
246 .byte 0x86; /* DW_CFA_offset %esi */ \
247 .uleb128 3; \
248 .byte 0x40+L(PUSHBX1)-L(PUSHSI1); /* DW_CFA_advance_loc+N */ \
249 .byte 14; /* DW_CFA_def_cfa_offset */ \
250 .uleb128 16; \
251 .byte 0x83; /* DW_CFA_offset %ebx */ \
252 .uleb128 4; \
253 .byte 0x40+L(POPBX1)-L(PUSHBX1); /* DW_CFA_advance_loc+N */ \
254 .byte 14; /* DW_CFA_def_cfa_offset */ \
255 .uleb128 12; \
256 .byte 0xc3; /* DW_CFA_restore %ebx */ \
257 .byte 0x40+L(POPSI1)-L(POPBX1); /* DW_CFA_advance_loc+N */ \
258 .byte 14; /* DW_CFA_def_cfa_offset */ \
259 .uleb128 8; \
260 .byte 0xc6; /* DW_CFA_restore %esi */ \
261 .byte 0x40+L(POPDI1)-L(POPSI1); /* DW_CFA_advance_loc+N */ \
262 .byte 14; /* DW_CFA_def_cfa_offset */ \
263 .uleb128 4; \
264 .byte 0xc7; /* DW_CFA_restore %edi */ \
265 .byte 0x40+L(PUSHSTATE)-L(POPDI1); /* DW_CFA_advance_loc+N */ \
266 .byte 14; /* DW_CFA_def_cfa_offset */ \
267 .uleb128 8; \
268 .byte 0x40+L(PUSHDI2)-L(PUSHSTATE); /* DW_CFA_advance_loc+N */ \
269 .byte 14; /* DW_CFA_def_cfa_offset */ \
270 .uleb128 12; \
271 .byte 0x87; /* DW_CFA_offset %edi */ \
272 .uleb128 3; \
273 .byte 0x40+L(PUSHSI2)-L(PUSHDI2); /* DW_CFA_advance_loc+N */ \
274 .byte 14; /* DW_CFA_def_cfa_offset */ \
275 .uleb128 16; \
276 .byte 0x86; /* DW_CFA_offset %esi */ \
277 .uleb128 4; \
278 .byte 0x40+L(PUSHBX2)-L(PUSHSI2); /* DW_CFA_advance_loc+N */ \
279 .byte 14; /* DW_CFA_def_cfa_offset */ \
280 .uleb128 20; \
281 .byte 0x83; /* DW_CFA_offset %ebx */ \
282 .uleb128 5; \
283 .byte 0x40+L(POPBX2)-L(PUSHBX2); /* DW_CFA_advance_loc+N */ \
284 .byte 14; /* DW_CFA_def_cfa_offset */ \
285 .uleb128 16; \
286 .byte 0xc3; /* DW_CFA_restore %ebx */ \
287 .byte 0x40+L(POPSI2)-L(POPBX2); /* DW_CFA_advance_loc+N */ \
288 .byte 14; /* DW_CFA_def_cfa_offset */ \
289 .uleb128 12; \
290 .byte 0xc6; /* DW_CFA_restore %esi */ \
291 .byte 0x40+L(POPDI2)-L(POPSI2); /* DW_CFA_advance_loc+N */ \
292 .byte 14; /* DW_CFA_def_cfa_offset */ \
293 .uleb128 8; \
294 .byte 0xc7; /* DW_CFA_restore %edi */ \
295 .byte 0x40+L(POPSTATE)-L(POPDI2); /* DW_CFA_advance_loc+N */ \
296 .byte 14; /* DW_CFA_def_cfa_offset */ \
297 .uleb128 4
300 # undef ASM_SIZE_DIRECTIVE
301 # define ASM_SIZE_DIRECTIVE(name) L(name##END): .size name,.-name;
303 # define SAVE_OLDTYPE_0 movl %eax, %ecx;
304 # define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0
305 # define SAVE_OLDTYPE_2 pushl %eax; L(PUSHSTATE):
306 # define SAVE_OLDTYPE_3 SAVE_OLDTYPE_2
307 # define SAVE_OLDTYPE_4 SAVE_OLDTYPE_2
308 # define SAVE_OLDTYPE_5 SAVE_OLDTYPE_2
310 # define PUSHCARGS_0 /* No arguments to push. */
311 # define DOCARGS_0 /* No arguments to frob. */
312 # define POPCARGS_0 /* No arguments to pop. */
313 # define _PUSHCARGS_0 /* No arguments to push. */
314 # define _POPCARGS_0 /* No arguments to pop. */
316 # define PUSHCARGS_1 movl %ebx, %edx; L(SAVEBX2): PUSHCARGS_0
317 # define DOCARGS_1 _DOARGS_1 (4)
318 # define POPCARGS_1 POPCARGS_0; movl %edx, %ebx; L(RESTBX2):
319 # define _PUSHCARGS_1 pushl %ebx; L(PUSHBX2): _PUSHCARGS_0
320 # define _POPCARGS_1 _POPCARGS_0; popl %ebx; L(POPBX2):
322 # define PUSHCARGS_2 PUSHCARGS_1
323 # define DOCARGS_2 _DOARGS_2 (12)
324 # define POPCARGS_2 POPCARGS_1
325 # define _PUSHCARGS_2 _PUSHCARGS_1
326 # define _POPCARGS_2 _POPCARGS_1
328 # define PUSHCARGS_3 _PUSHCARGS_2
329 # define DOCARGS_3 _DOARGS_3 (20)
330 # define POPCARGS_3 _POPCARGS_3
331 # define _PUSHCARGS_3 _PUSHCARGS_2
332 # define _POPCARGS_3 _POPCARGS_2
334 # define PUSHCARGS_4 _PUSHCARGS_4
335 # define DOCARGS_4 _DOARGS_4 (28)
336 # define POPCARGS_4 _POPCARGS_4
337 # define _PUSHCARGS_4 pushl %esi; L(PUSHSI2): _PUSHCARGS_3
338 # define _POPCARGS_4 _POPCARGS_3; popl %esi; L(POPSI2):
340 # define PUSHCARGS_5 _PUSHCARGS_5
341 # define DOCARGS_5 _DOARGS_5 (36)
342 # define POPCARGS_5 _POPCARGS_5
343 # define _PUSHCARGS_5 pushl %edi; L(PUSHDI2): _PUSHCARGS_4
344 # define _POPCARGS_5 _POPCARGS_4; popl %edi; L(POPDI2):
346 # ifdef IS_IN_libpthread
347 # define CENABLE call __pthread_enable_asynccancel;
348 # define CDISABLE call __pthread_disable_asynccancel
349 # elif !defined NOT_IN_libc
350 # define CENABLE call __libc_enable_asynccancel;
351 # define CDISABLE call __libc_disable_asynccancel
352 # elif defined IS_IN_librt
353 # define CENABLE call __librt_enable_asynccancel;
354 # define CDISABLE call __librt_disable_asynccancel
355 # else
356 # error Unsupported library
357 # endif
358 # define POPSTATE_0 \
359 pushl %eax; L(PUSHSTATE): movl %ecx, %eax; CDISABLE; popl %eax; L(POPSTATE):
360 # define POPSTATE_1 POPSTATE_0
361 # define POPSTATE_2 xchgl (%esp), %eax; CDISABLE; popl %eax; L(POPSTATE):
362 # define POPSTATE_3 POPSTATE_2
363 # define POPSTATE_4 POPSTATE_3
364 # define POPSTATE_5 POPSTATE_4
366 # ifndef __ASSEMBLER__
367 # define SINGLE_THREAD_P \
368 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
369 header.multiple_threads) == 0, 1)
370 # else
371 # define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET
372 # endif
374 #elif !defined __ASSEMBLER__
376 # define SINGLE_THREAD_P (1)
377 # define NO_CANCELLATION 1
379 #endif