]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/arm/sysdep-cancel.h
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / arm / sysdep-cancel.h
CommitLineData
b168057a 1/* Copyright (C) 2003-2015 Free Software Foundation, Inc.
02a9f771
DJ
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
ab84e3ff
PE
15 License along with the GNU C Library. If not, see
16 <http://www.gnu.org/licenses/>. */
02a9f771
DJ
17
18#include <sysdep.h>
19#include <tls.h>
20#ifndef __ASSEMBLER__
21# include <nptl/pthreadP.h>
22#endif
23
4f41c682 24#if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
02a9f771
DJ
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) \
63cc0e75 33 .text; \
63cc0e75
RH
34 ENTRY (__##syscall_name##_nocancel); \
35 CFI_SECTIONS; \
36 DO_CALL (syscall_name, args); \
37 cmn r0, $4096; \
38 PSEUDO_RET; \
39 END (__##syscall_name##_nocancel); \
02a9f771 40 ENTRY (name); \
63cc0e75
RH
41 SINGLE_THREAD_P; \
42 DOARGS_##args; \
43 bne .Lpseudo_cancel; \
44 cfi_remember_state; \
45 ldr r7, =SYS_ify (syscall_name); \
46 swi 0x0; \
47 UNDOARGS_##args; \
48 cmn r0, $4096; \
49 PSEUDO_RET; \
50 cfi_restore_state; \
02a9f771 51 .Lpseudo_cancel: \
63cc0e75
RH
52 .fnstart; /* matched by the .fnend in UNDOARGS below. */ \
53 DOCARGS_##args; /* save syscall args etc. around CENABLE. */ \
54 CENABLE; \
55 mov ip, r0; /* put mask in safe place. */ \
56 UNDOCARGS_##args; /* restore syscall args. */ \
57 ldr r7, =SYS_ify (syscall_name); \
58 swi 0x0; /* do the call. */ \
59 mov r7, r0; /* save syscall return value. */ \
60 mov r0, ip; /* get mask back. */ \
61 CDISABLE; \
62 mov r0, r7; /* retrieve return value. */ \
63 RESTORE_LR_##args; \
64 UNDOARGS_##args; \
65 cmn r0, $4096
02a9f771 66
73886008
UW
67/* DOARGS pushes eight bytes on the stack for five arguments, twelve bytes for
68 six arguments, and four bytes for fewer. In order to preserve doubleword
e5b5ba47 69 alignment, sometimes we must save an extra register. */
02a9f771 70
63cc0e75
RH
71# define RESTART_UNWIND \
72 .fnend; \
73 .fnstart; \
74 .save {r7}; \
75 .save {lr}
76
77# define DOCARGS_0 \
78 .save {r7}; \
55668624 79 push {lr}; \
63cc0e75
RH
80 cfi_adjust_cfa_offset (4); \
81 cfi_rel_offset (lr, 0); \
82 .save {lr}
02a9f771 83# define UNDOCARGS_0
63cc0e75 84# define RESTORE_LR_0 \
55668624 85 pop {lr}; \
63cc0e75
RH
86 cfi_adjust_cfa_offset (-4); \
87 cfi_restore (lr)
88
89# define DOCARGS_1 \
90 .save {r7}; \
55668624 91 push {r0, r1, lr}; \
63cc0e75
RH
92 cfi_adjust_cfa_offset (12); \
93 cfi_rel_offset (lr, 8); \
94 .save {lr}; \
95 .pad #8
96# define UNDOCARGS_1 \
97 ldr r0, [sp], #8; \
98 cfi_adjust_cfa_offset (-8); \
99 RESTART_UNWIND
100# define RESTORE_LR_1 \
101 RESTORE_LR_0
102
103# define DOCARGS_2 \
104 .save {r7}; \
55668624 105 push {r0, r1, lr}; \
63cc0e75
RH
106 cfi_adjust_cfa_offset (12); \
107 cfi_rel_offset (lr, 8); \
108 .save {lr}; \
109 .pad #8
110# define UNDOCARGS_2 \
55668624 111 pop {r0, r1}; \
63cc0e75
RH
112 cfi_adjust_cfa_offset (-8); \
113 RESTART_UNWIND
114# define RESTORE_LR_2 \
115 RESTORE_LR_0
116
117# define DOCARGS_3 \
118 .save {r7}; \
55668624 119 push {r0, r1, r2, r3, lr}; \
63cc0e75
RH
120 cfi_adjust_cfa_offset (20); \
121 cfi_rel_offset (lr, 16); \
122 .save {lr}; \
123 .pad #16
124# define UNDOCARGS_3 \
55668624 125 pop {r0, r1, r2, r3}; \
63cc0e75
RH
126 cfi_adjust_cfa_offset (-16); \
127 RESTART_UNWIND
128# define RESTORE_LR_3 \
129 RESTORE_LR_0
130
131# define DOCARGS_4 \
132 .save {r7}; \
55668624 133 push {r0, r1, r2, r3, lr}; \
63cc0e75
RH
134 cfi_adjust_cfa_offset (20); \
135 cfi_rel_offset (lr, 16); \
136 .save {lr}; \
137 .pad #16
138# define UNDOCARGS_4 \
55668624 139 pop {r0, r1, r2, r3}; \
63cc0e75
RH
140 cfi_adjust_cfa_offset (-16); \
141 RESTART_UNWIND
142# define RESTORE_LR_4 \
143 RESTORE_LR_0
01b32e73
TS
144
145/* r4 is only stmfd'ed for correct stack alignment. */
63cc0e75
RH
146# define DOCARGS_5 \
147 .save {r4, r7}; \
55668624 148 push {r0, r1, r2, r3, r4, lr}; \
63cc0e75
RH
149 cfi_adjust_cfa_offset (24); \
150 cfi_rel_offset (lr, 20); \
151 .save {lr}; \
152 .pad #20
153# define UNDOCARGS_5 \
55668624 154 pop {r0, r1, r2, r3}; \
63cc0e75
RH
155 cfi_adjust_cfa_offset (-16); \
156 .fnend; \
157 .fnstart; \
158 .save {r4, r7}; \
159 .save {lr}; \
160 .pad #4
161# define RESTORE_LR_5 \
55668624 162 pop {r4, lr}; \
63cc0e75
RH
163 cfi_adjust_cfa_offset (-8); \
164 /* r4 will be marked as restored later. */ \
165 cfi_restore (lr)
166
167# define DOCARGS_6 \
168 .save {r4, r5, r7}; \
55668624 169 push {r0, r1, r2, r3, lr}; \
63cc0e75
RH
170 cfi_adjust_cfa_offset (20); \
171 cfi_rel_offset (lr, 16); \
172 .save {lr}; \
173 .pad #16
174# define UNDOCARGS_6 \
55668624 175 pop {r0, r1, r2, r3}; \
63cc0e75
RH
176 cfi_adjust_cfa_offset (-16); \
177 .fnend; \
178 .fnstart; \
179 .save {r4, r5, r7}; \
180 .save {lr};
181# define RESTORE_LR_6 \
182 RESTORE_LR_0
e5b5ba47 183
ce9f10f7 184# if IS_IN (libpthread)
02a9f771
DJ
185# define CENABLE bl PLTJMP(__pthread_enable_asynccancel)
186# define CDISABLE bl PLTJMP(__pthread_disable_asynccancel)
187# define __local_multiple_threads __pthread_multiple_threads
4f41c682 188# elif IS_IN (libc)
02a9f771
DJ
189# define CENABLE bl PLTJMP(__libc_enable_asynccancel)
190# define CDISABLE bl PLTJMP(__libc_disable_asynccancel)
191# define __local_multiple_threads __libc_multiple_threads
016afc75 192# elif IS_IN (librt)
02a9f771
DJ
193# define CENABLE bl PLTJMP(__librt_enable_asynccancel)
194# define CDISABLE bl PLTJMP(__librt_disable_asynccancel)
195# else
196# error Unsupported library
197# endif
198
4f41c682 199# if IS_IN (libpthread) || IS_IN (libc)
02a9f771
DJ
200# ifndef __ASSEMBLER__
201extern int __local_multiple_threads attribute_hidden;
202# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
203# else
204# define SINGLE_THREAD_P \
cd24e113
RH
205 LDST_PCREL(ldr, ip, ip, __local_multiple_threads); \
206 teq ip, #0
02a9f771
DJ
207# endif
208# else
209/* There is no __local_multiple_threads for librt, so use the TCB. */
210# ifndef __ASSEMBLER__
211# define SINGLE_THREAD_P \
212 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
213 header.multiple_threads) == 0, 1)
214# else
02a9f771 215# define SINGLE_THREAD_P \
55668624 216 push {r0, lr}; \
63cc0e75
RH
217 cfi_adjust_cfa_offset (8); \
218 cfi_rel_offset (lr, 4); \
5232b909 219 GET_TLS (lr); \
3ae44082
RH
220 NEGOFF_ADJ_BASE (r0, MULTIPLE_THREADS_OFFSET); \
221 ldr ip, NEGOFF_OFF1 (r0, MULTIPLE_THREADS_OFFSET); \
55668624 222 pop {r0, lr}; \
63cc0e75
RH
223 cfi_adjust_cfa_offset (-8); \
224 cfi_restore (lr); \
225 teq ip, #0
02a9f771
DJ
226# endif
227# endif
228
229#elif !defined __ASSEMBLER__
230
231/* For rtld, et cetera. */
232# define SINGLE_THREAD_P 1
233# define NO_CANCELLATION 1
234
235#endif
80d6637f
DJ
236
237#ifndef __ASSEMBLER__
238# define RTLD_SINGLE_THREAD_P \
239 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
240 header.multiple_threads) == 0, 1)
241#endif