]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / hppa / sysdep-cancel.h
1 /* Copyright (C) 2005-2016 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 <tls.h>
20 #ifndef __ASSEMBLER__
21 # include <nptl/pthreadP.h>
22 #endif
23
24 #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
25
26 # ifndef NO_ERROR
27 # define NO_ERROR -0x1000
28 # endif
29
30 /* The syscall cancellation mechanism requires userspace
31 assistance, the following code does roughly this:
32
33 do arguments (read arg5 and arg6 to registers)
34 setup frame
35
36 check if there are threads, yes jump to pseudo_cancel
37
38 unthreaded:
39 syscall
40 check syscall return (jump to pre_end)
41 set errno
42 set return to -1
43 (jump to pre_end)
44
45 pseudo_cancel:
46 cenable
47 syscall
48 cdisable
49 check syscall return (jump to pre_end)
50 set errno
51 set return to -1
52
53 pre_end
54 restore stack
55
56 It is expected that 'ret' and 'END' macros will
57 append an 'undo arguments' and 'return' to the
58 this PSEUDO macro. */
59
60 # undef PSEUDO
61 # define PSEUDO(name, syscall_name, args) \
62 ENTRY (__##syscall_name##_nocancel) \
63 DOARGS_##args ASM_LINE_SEP \
64 stwm TREG, 64(%sp) ASM_LINE_SEP \
65 .cfi_offset TREG, 0 ASM_LINE_SEP \
66 .cfi_adjust_cfa_offset 64 ASM_LINE_SEP \
67 stw %sp, -4(%sp) ASM_LINE_SEP \
68 .cfi_offset 30, -4 ASM_LINE_SEP \
69 stw %r19, -32(%sp) ASM_LINE_SEP \
70 .cfi_offset 19, -32 ASM_LINE_SEP \
71 /* Save r19 */ ASM_LINE_SEP \
72 SAVE_PIC(TREG) ASM_LINE_SEP \
73 /* Do syscall, delay loads # */ ASM_LINE_SEP \
74 ble 0x100(%sr2,%r0) ASM_LINE_SEP \
75 ldi SYS_ify (syscall_name), %r20 /* delay */ ASM_LINE_SEP \
76 ldi NO_ERROR,%r1 ASM_LINE_SEP \
77 cmpb,>>=,n %r1,%ret0,L(pre_nc_end) ASM_LINE_SEP \
78 /* Restore r19 from TREG */ ASM_LINE_SEP \
79 LOAD_PIC(TREG) /* delay */ ASM_LINE_SEP \
80 SYSCALL_ERROR_HANDLER ASM_LINE_SEP \
81 /* Use TREG for temp storage */ ASM_LINE_SEP \
82 copy %ret0, TREG /* delay */ ASM_LINE_SEP \
83 /* OPTIMIZE: Don't reload r19 */ ASM_LINE_SEP \
84 /* do a -1*syscall_ret0 */ ASM_LINE_SEP \
85 sub %r0, TREG, TREG ASM_LINE_SEP \
86 /* Store into errno location */ ASM_LINE_SEP \
87 stw TREG, 0(%sr0,%ret0) ASM_LINE_SEP \
88 /* return -1 as error */ ASM_LINE_SEP \
89 ldi -1, %ret0 ASM_LINE_SEP \
90 L(pre_nc_end): ASM_LINE_SEP \
91 /* No need to LOAD_PIC */ ASM_LINE_SEP \
92 /* Undo frame */ ASM_LINE_SEP \
93 ldwm -64(%sp),TREG ASM_LINE_SEP \
94 .cfi_adjust_cfa_offset -64 ASM_LINE_SEP \
95 /* Restore rp before exit */ ASM_LINE_SEP \
96 ldw -20(%sp), %rp ASM_LINE_SEP \
97 .cfi_restore 2 ASM_LINE_SEP \
98 ret ASM_LINE_SEP \
99 END(__##syscall_name##_nocancel) ASM_LINE_SEP \
100 /**********************************************/ASM_LINE_SEP \
101 ENTRY (name) \
102 DOARGS_##args ASM_LINE_SEP \
103 stwm TREG, 64(%sp) ASM_LINE_SEP \
104 .cfi_adjust_cfa_offset 64 ASM_LINE_SEP \
105 stw %sp, -4(%sp) ASM_LINE_SEP \
106 .cfi_offset 30, -4 ASM_LINE_SEP \
107 stw %r19, -32(%sp) ASM_LINE_SEP \
108 .cfi_offset 19, -32 ASM_LINE_SEP \
109 /* Done setting up frame, continue... */ ASM_LINE_SEP \
110 SINGLE_THREAD_P ASM_LINE_SEP \
111 cmpib,<>,n 0,%ret0,L(pseudo_cancel) ASM_LINE_SEP \
112 L(unthreaded): ASM_LINE_SEP \
113 /* Save r19 */ ASM_LINE_SEP \
114 SAVE_PIC(TREG) ASM_LINE_SEP \
115 /* Do syscall, delay loads # */ ASM_LINE_SEP \
116 ble 0x100(%sr2,%r0) ASM_LINE_SEP \
117 ldi SYS_ify (syscall_name), %r20 /* delay */ ASM_LINE_SEP \
118 ldi NO_ERROR,%r1 ASM_LINE_SEP \
119 cmpb,>>=,n %r1,%ret0,L(pre_end) ASM_LINE_SEP \
120 /* Restore r19 from TREG */ ASM_LINE_SEP \
121 LOAD_PIC(TREG) /* delay */ ASM_LINE_SEP \
122 SYSCALL_ERROR_HANDLER ASM_LINE_SEP \
123 /* Use TREG for temp storage */ ASM_LINE_SEP \
124 copy %ret0, TREG /* delay */ ASM_LINE_SEP \
125 /* OPTIMIZE: Don't reload r19 */ ASM_LINE_SEP \
126 /* do a -1*syscall_ret0 */ ASM_LINE_SEP \
127 sub %r0, TREG, TREG ASM_LINE_SEP \
128 /* Store into errno location */ ASM_LINE_SEP \
129 stw TREG, 0(%sr0,%ret0) ASM_LINE_SEP \
130 b L(pre_end) ASM_LINE_SEP \
131 /* return -1 as error */ ASM_LINE_SEP \
132 ldi -1, %ret0 /* delay */ ASM_LINE_SEP \
133 L(pseudo_cancel): ASM_LINE_SEP \
134 PUSHARGS_##args /* Save args */ ASM_LINE_SEP \
135 /* Save r19 into TREG */ ASM_LINE_SEP \
136 CENABLE /* FUNC CALL */ ASM_LINE_SEP \
137 SAVE_PIC(TREG) /* delay */ ASM_LINE_SEP \
138 /* restore syscall args */ ASM_LINE_SEP \
139 POPARGS_##args ASM_LINE_SEP \
140 /* save mask from cenable (use stub rp slot) */ ASM_LINE_SEP \
141 stw %ret0, -24(%sp) ASM_LINE_SEP \
142 /* ... SYSCALL ... */ ASM_LINE_SEP \
143 ble 0x100(%sr2,%r0) ASM_LINE_SEP \
144 ldi SYS_ify (syscall_name), %r20 /* delay */ ASM_LINE_SEP \
145 /* ............... */ ASM_LINE_SEP \
146 LOAD_PIC(TREG) ASM_LINE_SEP \
147 /* pass mask as arg0 to cdisable */ ASM_LINE_SEP \
148 ldw -24(%sp), %r26 ASM_LINE_SEP \
149 CDISABLE ASM_LINE_SEP \
150 stw %ret0, -24(%sp) /* delay */ ASM_LINE_SEP \
151 /* Restore syscall return */ ASM_LINE_SEP \
152 ldw -24(%sp), %ret0 ASM_LINE_SEP \
153 /* compare error */ ASM_LINE_SEP \
154 ldi NO_ERROR,%r1 ASM_LINE_SEP \
155 /* branch if no error */ ASM_LINE_SEP \
156 cmpb,>>=,n %r1,%ret0,L(pre_end) ASM_LINE_SEP \
157 LOAD_PIC(TREG) /* cond. nullify */ ASM_LINE_SEP \
158 copy %ret0, TREG /* save syscall return */ ASM_LINE_SEP \
159 SYSCALL_ERROR_HANDLER ASM_LINE_SEP \
160 /* make syscall res value positive */ ASM_LINE_SEP \
161 sub %r0, TREG, TREG /* delay */ ASM_LINE_SEP \
162 /* No need to LOAD_PIC */ ASM_LINE_SEP \
163 /* store into errno location */ ASM_LINE_SEP \
164 stw TREG, 0(%sr0,%ret0) ASM_LINE_SEP \
165 /* return -1 */ ASM_LINE_SEP \
166 ldi -1, %ret0 ASM_LINE_SEP \
167 L(pre_end): ASM_LINE_SEP \
168 /* No need to LOAD_PIC */ ASM_LINE_SEP \
169 /* Undo frame */ ASM_LINE_SEP \
170 ldwm -64(%sp),TREG ASM_LINE_SEP \
171 .cfi_adjust_cfa_offset -64 ASM_LINE_SEP \
172 /* Restore rp before exit */ ASM_LINE_SEP \
173 ldw -20(%sp), %rp ASM_LINE_SEP \
174 .cfi_restore 2 ASM_LINE_SEP
175
176 /* Save arguments into our frame */
177 # define PUSHARGS_0 /* nothing to do */
178 # define PUSHARGS_1 PUSHARGS_0 stw %r26, -36(%sr0,%sp) ASM_LINE_SEP \
179 .cfi_offset 26, -36 ASM_LINE_SEP
180 # define PUSHARGS_2 PUSHARGS_1 stw %r25, -40(%sr0,%sp) ASM_LINE_SEP \
181 .cfi_offset 25, -40 ASM_LINE_SEP
182 # define PUSHARGS_3 PUSHARGS_2 stw %r24, -44(%sr0,%sp) ASM_LINE_SEP \
183 .cfi_offset 24, -44 ASM_LINE_SEP
184 # define PUSHARGS_4 PUSHARGS_3 stw %r23, -48(%sr0,%sp) ASM_LINE_SEP \
185 .cfi_offset 23, -48 ASM_LINE_SEP
186 # define PUSHARGS_5 PUSHARGS_4 stw %r22, -52(%sr0,%sp) ASM_LINE_SEP \
187 .cfi_offset 22, -52 ASM_LINE_SEP
188 # define PUSHARGS_6 PUSHARGS_5 stw %r21, -56(%sr0,%sp) ASM_LINE_SEP \
189 .cfi_offset 21, -56 ASM_LINE_SEP
190
191 /* Bring them back from the stack */
192 # define POPARGS_0 /* nothing to do */
193 # define POPARGS_1 POPARGS_0 ldw -36(%sr0,%sp), %r26 ASM_LINE_SEP \
194 .cfi_restore 26 ASM_LINE_SEP
195 # define POPARGS_2 POPARGS_1 ldw -40(%sr0,%sp), %r25 ASM_LINE_SEP \
196 .cfi_restore 25 ASM_LINE_SEP
197 # define POPARGS_3 POPARGS_2 ldw -44(%sr0,%sp), %r24 ASM_LINE_SEP \
198 .cfi_restore 24 ASM_LINE_SEP
199 # define POPARGS_4 POPARGS_3 ldw -48(%sr0,%sp), %r23 ASM_LINE_SEP \
200 .cfi_restore 23 ASM_LINE_SEP
201 # define POPARGS_5 POPARGS_4 ldw -52(%sr0,%sp), %r22 ASM_LINE_SEP \
202 .cfi_restore 22 ASM_LINE_SEP
203 # define POPARGS_6 POPARGS_5 ldw -56(%sr0,%sp), %r21 ASM_LINE_SEP \
204 .cfi_restore 21 ASM_LINE_SEP
205
206 # if IS_IN (libpthread)
207 # ifdef PIC
208 # define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \
209 bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP
210 # define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \
211 bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP
212 # else
213 # define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \
214 bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP
215 # define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \
216 bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP
217 # endif
218 # elif IS_IN (libc)
219 # ifdef PIC
220 # define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \
221 bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP
222 # define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \
223 bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP
224 # else
225 # define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \
226 bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP
227 # define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \
228 bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP
229 # endif
230 # elif IS_IN (librt)
231 # ifdef PIC
232 # define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \
233 bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP
234 # define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \
235 bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP
236 # else
237 # define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \
238 bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP
239 # define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \
240 bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP
241 # endif
242 # else
243 # error Unsupported library
244 # endif
245
246 # if IS_IN (libpthread)
247 # define __local_multiple_threads __pthread_multiple_threads
248 # elif IS_IN (libc)
249 # define __local_multiple_threads __libc_multiple_threads
250 # elif IS_IN (librt)
251 # define __local_multiple_threads __librt_multiple_threads
252 # else
253 # error Unsupported library
254 # endif
255
256 # ifndef __ASSEMBLER__
257 # define SINGLE_THREAD_P \
258 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
259 header.multiple_threads) == 0, 1)
260 # else
261 /* Read the value of header.multiple_threads from the thread pointer */
262 # define SINGLE_THREAD_P \
263 mfctl %cr27, %ret0 ASM_LINE_SEP \
264 ldw MULTIPLE_THREADS_THREAD_OFFSET(%sr0,%ret0),%ret0 ASM_LINE_SEP
265 # endif
266 #elif !defined __ASSEMBLER__
267
268 /* This code should never be used but we define it anyhow. */
269 # define SINGLE_THREAD_P (1)
270 # define NO_CANCELLATION 1
271
272 #endif
273 /* IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt) */
274
275 #ifndef __ASSEMBLER__
276 # define RTLD_SINGLE_THREAD_P \
277 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
278 header.multiple_threads) == 0, 1)
279 #endif