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