OSDN Git Service

Replace FSF snail mail address with URLs
[uclinux-h8/uClibc.git] / libpthread / nptl / sysdeps / unix / sysv / linux / arm / sysdep-cancel.h
1 /* Copyright (C) 2003, 2004, 2005, 2009 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
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.
8
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.
13
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/>.  */
17
18 #include <sysdep.h>
19 #include <tcb-offsets.h>
20 #ifndef __ASSEMBLER__
21 # include <pthreadP.h>
22 #endif
23
24 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
25
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.  */
30
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     PSEUDO_RET;                                                         \
42     cfi_endproc;                                                        \
43   .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;      \
44   ENTRY (name);                                                         \
45     SINGLE_THREAD_P;                                                    \
46     DOARGS_##args;                                                      \
47     bne .Lpseudo_cancel;                                                \
48     cfi_remember_state;                                                 \
49     DO_CALL (syscall_name, 0);                                          \
50     UNDOARGS_##args;                                                    \
51     cmn r0, $4096;                                                      \
52     PSEUDO_RET;                                                         \
53     cfi_restore_state;                                                  \
54   .Lpseudo_cancel:                                                      \
55     .fnstart;                                                           \
56     DOCARGS_##args;     /* save syscall args etc. around CENABLE.  */   \
57     CENABLE;                                                            \
58     mov ip, r0;         /* put mask in safe place.  */                  \
59     UNDOCARGS_##args;   /* restore syscall args.  */                    \
60     ldr r7, =SYS_ify (syscall_name);                                    \
61     swi 0x0;            /* do the call.  */                             \
62     .fnend;             /* Past here we can't easily unwind.  */        \
63     mov r7, r0;         /* save syscall return value.  */               \
64     mov r0, ip;         /* get mask back.  */                           \
65     CDISABLE;                                                           \
66     mov r0, r7;         /* retrieve return value.  */                   \
67     RESTORE_LR_##args;                                                  \
68     UNDOARGS_##args;                                                    \
69     cmn r0, $4096
70
71 /* DOARGS pushes four bytes on the stack for five arguments, eight bytes for
72    six arguments, and nothing for fewer.  In order to preserve doubleword
73    alignment, sometimes we must save an extra register.  */
74
75 # define RESTART_UNWIND \
76   .fnend; \
77   .fnstart; \
78   .save {r7, lr}
79
80 # define DOCARGS_0 \
81   stmfd sp!, {r7, lr}; \
82   cfi_adjust_cfa_offset (8); \
83   cfi_rel_offset (r7, 0); \
84   cfi_rel_offset (lr, 4); \
85   .save {r7, lr}
86 # define UNDOCARGS_0
87 # define RESTORE_LR_0 \
88   ldmfd sp!, {r7, lr}; \
89   cfi_adjust_cfa_offset (-8); \
90   cfi_restore (r7); \
91   cfi_restore (lr)
92
93 # define DOCARGS_1 \
94   stmfd sp!, {r0, r1, r7, lr}; \
95   cfi_adjust_cfa_offset (16); \
96   cfi_rel_offset (r7, 8); \
97   cfi_rel_offset (lr, 12); \
98   .save {r7, lr}; \
99   .pad #8
100 # define UNDOCARGS_1 \
101   ldr r0, [sp], #8; \
102   cfi_adjust_cfa_offset (-8); \
103   RESTART_UNWIND
104 # define RESTORE_LR_1 \
105   RESTORE_LR_0
106
107 # define DOCARGS_2 \
108   stmfd sp!, {r0, r1, r7, lr}; \
109   cfi_adjust_cfa_offset (16); \
110   cfi_rel_offset (r7, 8); \
111   cfi_rel_offset (lr, 12); \
112   .save {r7, lr}; \
113   .pad #8
114 # define UNDOCARGS_2 \
115   ldmfd sp!, {r0, r1}; \
116   cfi_adjust_cfa_offset (-8); \
117   RESTART_UNWIND
118 # define RESTORE_LR_2 \
119   RESTORE_LR_0
120
121 # define DOCARGS_3 \
122   stmfd sp!, {r0, r1, r2, r3, r7, lr}; \
123   cfi_adjust_cfa_offset (24); \
124   cfi_rel_offset (r7, 16); \
125   cfi_rel_offset (lr, 20); \
126   .save {r7, lr}; \
127   .pad #16
128 # define UNDOCARGS_3 \
129   ldmfd sp!, {r0, r1, r2, r3}; \
130   cfi_adjust_cfa_offset (-16); \
131   RESTART_UNWIND
132 # define RESTORE_LR_3 \
133   RESTORE_LR_0
134
135 # define DOCARGS_4 \
136   stmfd sp!, {r0, r1, r2, r3, r7, lr}; \
137   cfi_adjust_cfa_offset (24); \
138   cfi_rel_offset (r7, 16); \
139   cfi_rel_offset (lr, 20); \
140   .save {r7, lr}; \
141   .pad #16
142 # define UNDOCARGS_4 \
143   ldmfd sp!, {r0, r1, r2, r3}; \
144   cfi_adjust_cfa_offset (-16); \
145   RESTART_UNWIND
146 # define RESTORE_LR_4 \
147   RESTORE_LR_0
148
149 /* r4 is only stmfd'ed for correct stack alignment.  */
150 # define DOCARGS_5 \
151   .save {r4}; \
152   stmfd sp!, {r0, r1, r2, r3, r4, r7, lr}; \
153   cfi_adjust_cfa_offset (28); \
154   cfi_rel_offset (r7, 20); \
155   cfi_rel_offset (lr, 24); \
156   .save {r7, 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}; \
164   .save {r7, lr}; \
165   .pad #4
166 # define RESTORE_LR_5 \
167   ldmfd sp!, {r4, r7, lr}; \
168   cfi_adjust_cfa_offset (-12); \
169   /* r4 will be marked as restored later.  */ \
170   cfi_restore (r7); \
171   cfi_restore (lr)
172
173 # define DOCARGS_6 \
174   .save {r4, r5}; \
175   stmfd sp!, {r0, r1, r2, r3, r7, lr}; \
176   cfi_adjust_cfa_offset (24); \
177   cfi_rel_offset (r7, 16); \
178   cfi_rel_offset (lr, 20); \
179   .save {r7, lr}; \
180   .pad #16
181 # define UNDOCARGS_6 \
182   ldmfd sp!, {r0, r1, r2, r3}; \
183   cfi_adjust_cfa_offset (-16); \
184   .fnend; \
185   .fnstart; \
186   .save {r4, r5}; \
187   .save {r7, lr}
188 # define RESTORE_LR_6 \
189   RESTORE_LR_0
190
191 # ifdef IS_IN_libpthread
192 #  define CENABLE       bl PLTJMP(__pthread_enable_asynccancel)
193 #  define CDISABLE      bl PLTJMP(__pthread_disable_asynccancel)
194 #  define __local_multiple_threads __pthread_multiple_threads
195 # elif !defined NOT_IN_libc
196 #  define CENABLE       bl PLTJMP(__libc_enable_asynccancel)
197 #  define CDISABLE      bl PLTJMP(__libc_disable_asynccancel)
198 #  define __local_multiple_threads __libc_multiple_threads
199 # elif defined IS_IN_librt
200 #  define CENABLE       bl PLTJMP(__librt_enable_asynccancel)
201 #  define CDISABLE      bl PLTJMP(__librt_disable_asynccancel)
202 # else
203 #  error Unsupported library
204 # endif
205
206 # if defined IS_IN_libpthread || !defined NOT_IN_libc
207 #  ifndef __ASSEMBLER__
208 extern int __local_multiple_threads attribute_hidden;
209 #   define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
210 #  else
211 #   define SINGLE_THREAD_P                                              \
212   ldr ip, 1b;                                                           \
213 2:                                                                      \
214   ldr ip, [pc, ip];                                                     \
215   teq ip, #0;
216 #   define PSEUDO_PROLOGUE                                              \
217   1:  .word __local_multiple_threads - 2f - 8;
218 #  endif
219 # else
220 /*  There is no __local_multiple_threads for librt, so use the TCB.  */
221 #  ifndef __ASSEMBLER__
222 #   define SINGLE_THREAD_P                                              \
223   __builtin_expect (THREAD_GETMEM (THREAD_SELF,                         \
224                                    header.multiple_threads) == 0, 1)
225 #  else
226 #   define PSEUDO_PROLOGUE
227 #   define SINGLE_THREAD_P                                              \
228   stmfd sp!, {r0, lr};                                                  \
229   cfi_adjust_cfa_offset (8);                                            \
230   cfi_rel_offset (lr, 4);                                               \
231   bl    __aeabi_read_tp;                                                \
232   ldr   ip, [r0, #MULTIPLE_THREADS_OFFSET];                             \
233   ldmfd sp!, {r0, lr};                                                  \
234   cfi_adjust_cfa_offset (-8);                                           \
235   cfi_restore (lr);                                                     \
236   teq   ip, #0
237 #   define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P
238 #  endif
239 # endif
240
241 #elif !defined __ASSEMBLER__
242
243 /* For rtld, et cetera.  */
244 # define SINGLE_THREAD_P 1
245 # define NO_CANCELLATION 1
246
247 #endif
248
249 #ifndef __ASSEMBLER__
250 # define RTLD_SINGLE_THREAD_P \
251   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
252                                    header.multiple_threads) == 0, 1)
253 #endif