Move all files into ports/ subdirectory in preparation for merge with glibc
[glibc.git] / ports / sysdeps / unix / sysv / linux / arm / nptl / sysdep-cancel.h
blobc26bec3dcaead20958a84fca64bd8db043736510
1 /* Copyright (C) 2003, 2004, 2005, 2009 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library. If not, see
16 <http://www.gnu.org/licenses/>. */
18 #include <sysdep.h>
19 #include <tls.h>
20 #ifndef __ASSEMBLER__
21 # include <nptl/pthreadP.h>
22 #endif
24 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
26 /* NOTE: We do mark syscalls with unwind annotations, for the benefit of
27 cancellation; but they're really only accurate at the point of the
28 syscall. The ARM unwind directives are not rich enough without adding
29 a custom personality function. */
31 # undef PSEUDO
32 # define PSEUDO(name, syscall_name, args) \
33 .section ".text"; \
34 PSEUDO_PROLOGUE; \
35 .type __##syscall_name##_nocancel,%function; \
36 .globl __##syscall_name##_nocancel; \
37 __##syscall_name##_nocancel: \
38 .cfi_sections .debug_frame; \
39 cfi_startproc; \
40 DO_CALL (syscall_name, args); \
41 cmn r0, $4096; \
42 PSEUDO_RET; \
43 cfi_endproc; \
44 .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
45 ENTRY (name); \
46 SINGLE_THREAD_P; \
47 DOARGS_##args; \
48 bne .Lpseudo_cancel; \
49 cfi_remember_state; \
50 ldr r7, =SYS_ify (syscall_name); \
51 swi 0x0; \
52 UNDOARGS_##args; \
53 cmn r0, $4096; \
54 PSEUDO_RET; \
55 cfi_restore_state; \
56 .Lpseudo_cancel: \
57 .fnstart; /* matched by the .fnend in UNDOARGS below. */ \
58 DOCARGS_##args; /* save syscall args etc. around CENABLE. */ \
59 CENABLE; \
60 mov ip, r0; /* put mask in safe place. */ \
61 UNDOCARGS_##args; /* restore syscall args. */ \
62 ldr r7, =SYS_ify (syscall_name); \
63 swi 0x0; /* do the call. */ \
64 mov r7, r0; /* save syscall return value. */ \
65 mov r0, ip; /* get mask back. */ \
66 CDISABLE; \
67 mov r0, r7; /* retrieve return value. */ \
68 RESTORE_LR_##args; \
69 UNDOARGS_##args; \
70 cmn r0, $4096
72 /* DOARGS pushes eight bytes on the stack for five arguments, twelve bytes for
73 six arguments, and four bytes for fewer. In order to preserve doubleword
74 alignment, sometimes we must save an extra register. */
76 # define RESTART_UNWIND \
77 .fnend; \
78 .fnstart; \
79 .save {r7}; \
80 .save {lr}
82 # define DOCARGS_0 \
83 .save {r7}; \
84 str lr, [sp, #-4]!; \
85 cfi_adjust_cfa_offset (4); \
86 cfi_rel_offset (lr, 0); \
87 .save {lr}
88 # define UNDOCARGS_0
89 # define RESTORE_LR_0 \
90 ldr lr, [sp], #4; \
91 cfi_adjust_cfa_offset (-4); \
92 cfi_restore (lr)
94 # define DOCARGS_1 \
95 .save {r7}; \
96 stmfd sp!, {r0, r1, lr}; \
97 cfi_adjust_cfa_offset (12); \
98 cfi_rel_offset (lr, 8); \
99 .save {lr}; \
100 .pad #8
101 # define UNDOCARGS_1 \
102 ldr r0, [sp], #8; \
103 cfi_adjust_cfa_offset (-8); \
104 RESTART_UNWIND
105 # define RESTORE_LR_1 \
106 RESTORE_LR_0
108 # define DOCARGS_2 \
109 .save {r7}; \
110 stmfd sp!, {r0, r1, lr}; \
111 cfi_adjust_cfa_offset (12); \
112 cfi_rel_offset (lr, 8); \
113 .save {lr}; \
114 .pad #8
115 # define UNDOCARGS_2 \
116 ldmfd sp!, {r0, r1}; \
117 cfi_adjust_cfa_offset (-8); \
118 RESTART_UNWIND
119 # define RESTORE_LR_2 \
120 RESTORE_LR_0
122 # define DOCARGS_3 \
123 .save {r7}; \
124 stmfd sp!, {r0, r1, r2, r3, lr}; \
125 cfi_adjust_cfa_offset (20); \
126 cfi_rel_offset (lr, 16); \
127 .save {lr}; \
128 .pad #16
129 # define UNDOCARGS_3 \
130 ldmfd sp!, {r0, r1, r2, r3}; \
131 cfi_adjust_cfa_offset (-16); \
132 RESTART_UNWIND
133 # define RESTORE_LR_3 \
134 RESTORE_LR_0
136 # define DOCARGS_4 \
137 .save {r7}; \
138 stmfd sp!, {r0, r1, r2, r3, lr}; \
139 cfi_adjust_cfa_offset (20); \
140 cfi_rel_offset (lr, 16); \
141 .save {lr}; \
142 .pad #16
143 # define UNDOCARGS_4 \
144 ldmfd sp!, {r0, r1, r2, r3}; \
145 cfi_adjust_cfa_offset (-16); \
146 RESTART_UNWIND
147 # define RESTORE_LR_4 \
148 RESTORE_LR_0
150 /* r4 is only stmfd'ed for correct stack alignment. */
151 # define DOCARGS_5 \
152 .save {r4, r7}; \
153 stmfd sp!, {r0, r1, r2, r3, r4, lr}; \
154 cfi_adjust_cfa_offset (24); \
155 cfi_rel_offset (lr, 20); \
156 .save {lr}; \
157 .pad #20
158 # define UNDOCARGS_5 \
159 ldmfd sp!, {r0, r1, r2, r3}; \
160 cfi_adjust_cfa_offset (-16); \
161 .fnend; \
162 .fnstart; \
163 .save {r4, r7}; \
164 .save {lr}; \
165 .pad #4
166 # define RESTORE_LR_5 \
167 ldmfd sp!, {r4, lr}; \
168 cfi_adjust_cfa_offset (-8); \
169 /* r4 will be marked as restored later. */ \
170 cfi_restore (lr)
172 # define DOCARGS_6 \
173 .save {r4, r5, r7}; \
174 stmfd sp!, {r0, r1, r2, r3, lr}; \
175 cfi_adjust_cfa_offset (20); \
176 cfi_rel_offset (lr, 16); \
177 .save {lr}; \
178 .pad #16
179 # define UNDOCARGS_6 \
180 ldmfd sp!, {r0, r1, r2, r3}; \
181 cfi_adjust_cfa_offset (-16); \
182 .fnend; \
183 .fnstart; \
184 .save {r4, r5, r7}; \
185 .save {lr};
186 # define RESTORE_LR_6 \
187 RESTORE_LR_0
189 # ifdef IS_IN_libpthread
190 # define CENABLE bl PLTJMP(__pthread_enable_asynccancel)
191 # define CDISABLE bl PLTJMP(__pthread_disable_asynccancel)
192 # define __local_multiple_threads __pthread_multiple_threads
193 # elif !defined NOT_IN_libc
194 # define CENABLE bl PLTJMP(__libc_enable_asynccancel)
195 # define CDISABLE bl PLTJMP(__libc_disable_asynccancel)
196 # define __local_multiple_threads __libc_multiple_threads
197 # elif defined IS_IN_librt
198 # define CENABLE bl PLTJMP(__librt_enable_asynccancel)
199 # define CDISABLE bl PLTJMP(__librt_disable_asynccancel)
200 # else
201 # error Unsupported library
202 # endif
204 # if defined IS_IN_libpthread || !defined NOT_IN_libc
205 # ifndef __ASSEMBLER__
206 extern int __local_multiple_threads attribute_hidden;
207 # define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
208 # else
209 # define SINGLE_THREAD_P \
210 ldr ip, 1b; \
211 2: \
212 ldr ip, [pc, ip]; \
213 teq ip, #0;
214 # define PSEUDO_PROLOGUE \
215 1: .word __local_multiple_threads - 2f - 8;
216 # endif
217 # else
218 /* There is no __local_multiple_threads for librt, so use the TCB. */
219 # ifndef __ASSEMBLER__
220 # define SINGLE_THREAD_P \
221 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
222 header.multiple_threads) == 0, 1)
223 # else
224 # define PSEUDO_PROLOGUE
225 # define SINGLE_THREAD_P \
226 stmfd sp!, {r0, lr}; \
227 cfi_adjust_cfa_offset (8); \
228 cfi_rel_offset (lr, 4); \
229 bl __aeabi_read_tp; \
230 ldr ip, [r0, #MULTIPLE_THREADS_OFFSET]; \
231 ldmfd sp!, {r0, lr}; \
232 cfi_adjust_cfa_offset (-8); \
233 cfi_restore (lr); \
234 teq ip, #0
235 # define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P
236 # endif
237 # endif
239 #elif !defined __ASSEMBLER__
241 /* For rtld, et cetera. */
242 # define SINGLE_THREAD_P 1
243 # define NO_CANCELLATION 1
245 #endif
247 #ifndef __ASSEMBLER__
248 # define RTLD_SINGLE_THREAD_P \
249 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
250 header.multiple_threads) == 0, 1)
251 #endif