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, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 # include <nptl/pthreadP.h>
25 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
27 /* NOTE: We do mark syscalls with unwind annotations, for the benefit of
28 cancellation; but they're really only accurate at the point of the
29 syscall. The ARM unwind directives are not rich enough without adding
30 a custom personality function. */
33 # define PSEUDO(name, syscall_name, args) \
36 .type __##syscall_name##_nocancel,%function; \
37 .globl __##syscall_name##_nocancel; \
38 __##syscall_name##_nocancel: \
39 .cfi_sections .debug_frame; \
41 DO_CALL (syscall_name, args); \
44 .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
48 bne .Lpseudo_cancel; \
50 DO_CALL (syscall_name, 0); \
57 DOCARGS_##args; /* save syscall args etc. around CENABLE. */ \
59 mov ip, r0; /* put mask in safe place. */ \
60 UNDOCARGS_##args; /* restore syscall args. */ \
61 ldr r7, =SYS_ify (syscall_name); \
62 swi 0x0; /* do the call. */ \
63 .fnend; /* Past here we can't easily unwind. */ \
64 mov r7, r0; /* save syscall return value. */ \
65 mov r0, ip; /* get mask back. */ \
67 mov r0, r7; /* retrieve return value. */ \
72 /* DOARGS pushes four bytes on the stack for five arguments, eight bytes for
73 six arguments, and nothing for fewer. In order to preserve doubleword
74 alignment, sometimes we must save an extra register. */
76 # define RESTART_UNWIND \
82 stmfd sp!, {r7, lr}; \
83 cfi_adjust_cfa_offset (8); \
84 cfi_rel_offset (r7, 0); \
85 cfi_rel_offset (lr, 4); \
88 # define RESTORE_LR_0 \
89 ldmfd sp!, {r7, lr}; \
90 cfi_adjust_cfa_offset (-8); \
95 stmfd sp!, {r0, r1, r7, lr}; \
96 cfi_adjust_cfa_offset (16); \
97 cfi_rel_offset (r7, 8); \
98 cfi_rel_offset (lr, 12); \
101 # define UNDOCARGS_1 \
103 cfi_adjust_cfa_offset (-8); \
105 # define RESTORE_LR_1 \
109 stmfd sp!, {r0, r1, r7, lr}; \
110 cfi_adjust_cfa_offset (16); \
111 cfi_rel_offset (r7, 8); \
112 cfi_rel_offset (lr, 12); \
115 # define UNDOCARGS_2 \
116 ldmfd sp!, {r0, r1}; \
117 cfi_adjust_cfa_offset (-8); \
119 # define RESTORE_LR_2 \
123 stmfd sp!, {r0, r1, r2, r3, r7, lr}; \
124 cfi_adjust_cfa_offset (24); \
125 cfi_rel_offset (r7, 16); \
126 cfi_rel_offset (lr, 20); \
129 # define UNDOCARGS_3 \
130 ldmfd sp!, {r0, r1, r2, r3}; \
131 cfi_adjust_cfa_offset (-16); \
133 # define RESTORE_LR_3 \
137 stmfd sp!, {r0, r1, r2, r3, r7, lr}; \
138 cfi_adjust_cfa_offset (24); \
139 cfi_rel_offset (r7, 16); \
140 cfi_rel_offset (lr, 20); \
143 # define UNDOCARGS_4 \
144 ldmfd sp!, {r0, r1, r2, r3}; \
145 cfi_adjust_cfa_offset (-16); \
147 # define RESTORE_LR_4 \
150 /* r4 is only stmfd'ed for correct stack alignment. */
153 stmfd sp!, {r0, r1, r2, r3, r4, r7, lr}; \
154 cfi_adjust_cfa_offset (28); \
155 cfi_rel_offset (r7, 20); \
156 cfi_rel_offset (lr, 24); \
159 # define UNDOCARGS_5 \
160 ldmfd sp!, {r0, r1, r2, r3}; \
161 cfi_adjust_cfa_offset (-16); \
167 # define RESTORE_LR_5 \
168 ldmfd sp!, {r4, r7, lr}; \
169 cfi_adjust_cfa_offset (-12); \
170 /* r4 will be marked as restored later. */ \
176 stmfd sp!, {r0, r1, r2, r3, r7, lr}; \
177 cfi_adjust_cfa_offset (24); \
178 cfi_rel_offset (r7, 16); \
179 cfi_rel_offset (lr, 20); \
182 # define UNDOCARGS_6 \
183 ldmfd sp!, {r0, r1, r2, r3}; \
184 cfi_adjust_cfa_offset (-16); \
189 # define RESTORE_LR_6 \
192 # ifdef IS_IN_libpthread
193 # define CENABLE bl PLTJMP(__pthread_enable_asynccancel)
194 # define CDISABLE bl PLTJMP(__pthread_disable_asynccancel)
195 # define __local_multiple_threads __pthread_multiple_threads
196 # elif !defined NOT_IN_libc
197 # define CENABLE bl PLTJMP(__libc_enable_asynccancel)
198 # define CDISABLE bl PLTJMP(__libc_disable_asynccancel)
199 # define __local_multiple_threads __libc_multiple_threads
200 # elif defined IS_IN_librt
201 # define CENABLE bl PLTJMP(__librt_enable_asynccancel)
202 # define CDISABLE bl PLTJMP(__librt_disable_asynccancel)
204 # error Unsupported library
207 # if defined IS_IN_libpthread || !defined NOT_IN_libc
208 # ifndef __ASSEMBLER__
209 extern int __local_multiple_threads attribute_hidden
;
210 # define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
212 # define SINGLE_THREAD_P \
217 # define PSEUDO_PROLOGUE \
218 1: .word __local_multiple_threads - 2f - 8;
221 /* There is no __local_multiple_threads for librt, so use the TCB. */
222 # ifndef __ASSEMBLER__
223 # define SINGLE_THREAD_P \
224 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
225 header.multiple_threads) == 0, 1)
227 # define PSEUDO_PROLOGUE
228 # define SINGLE_THREAD_P \
229 stmfd sp!, {r0, lr}; \
230 cfi_adjust_cfa_offset (8); \
231 cfi_rel_offset (lr, 4); \
232 bl __aeabi_read_tp; \
233 ldr ip, [r0, #MULTIPLE_THREADS_OFFSET]; \
234 ldmfd sp!, {r0, lr}; \
235 cfi_adjust_cfa_offset (-8); \
238 # define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P
242 #elif !defined __ASSEMBLER__
244 /* For rtld, et cetera. */
245 # define SINGLE_THREAD_P 1
246 # define NO_CANCELLATION 1
250 #ifndef __ASSEMBLER__
251 # define RTLD_SINGLE_THREAD_P \
252 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
253 header.multiple_threads) == 0, 1)