]> git.ipfire.org Git - thirdparty/glibc.git/blame - ports/sysdeps/unix/sysv/linux/hppa/nptl/sysdep-cancel.h
Update copyright notices with scripts/update-copyrights
[thirdparty/glibc.git] / ports / sysdeps / unix / sysv / linux / hppa / nptl / sysdep-cancel.h
CommitLineData
d4697bc9 1/* Copyright (C) 2005-2014 Free Software Foundation, Inc.
da1ea0f0
CD
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/>. */
da1ea0f0
CD
17
18#include <sysdep.h>
19#include <sysdeps/generic/sysdep.h>
20#include <tls.h>
21#ifndef __ASSEMBLER__
22# include <nptl/pthreadP.h>
23#endif
24
25#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
26
27# ifndef NO_ERROR
28# define NO_ERROR -0x1000
29# endif
30
31/* The syscall cancellation mechanism requires userspace
32 assistance, the following code does roughly this:
33
34 do arguments (read arg5 and arg6 to registers)
35 setup frame
5556231d 36
da1ea0f0 37 check if there are threads, yes jump to pseudo_cancel
5556231d 38
da1ea0f0
CD
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)
5556231d 45
da1ea0f0
CD
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
5556231d 53
da1ea0f0
CD
54 pre_end
55 restore stack
5556231d 56
da1ea0f0 57 It is expected that 'ret' and 'END' macros will
5556231d 58 append an 'undo arguments' and 'return' to the
da1ea0f0 59 this PSEUDO macro. */
5556231d 60
da1ea0f0
CD
61# undef PSEUDO
62# define PSEUDO(name, syscall_name, args) \
8cb8321f
CD
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 \
91L(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 \
da1ea0f0
CD
102 ENTRY (name) \
103 DOARGS_##args ASM_LINE_SEP \
0daa0500 104 stwm TREG, 64(%sp) ASM_LINE_SEP \
8cb8321f 105 .cfi_adjust_cfa_offset 64 ASM_LINE_SEP \
0daa0500 106 stw %sp, -4(%sp) ASM_LINE_SEP \
8cb8321f 107 .cfi_offset 30, -4 ASM_LINE_SEP \
0daa0500 108 stw %r19, -32(%sp) ASM_LINE_SEP \
8cb8321f 109 .cfi_offset 19, -32 ASM_LINE_SEP \
da1ea0f0
CD
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 \
113L(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 \
0daa0500 133 ldi -1, %ret0 /* delay */ ASM_LINE_SEP \
da1ea0f0
CD
134L(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 \
0daa0500 167 ldi -1, %ret0 ASM_LINE_SEP \
da1ea0f0 168L(pre_end): ASM_LINE_SEP \
0daa0500 169 /* No need to LOAD_PIC */ ASM_LINE_SEP \
da1ea0f0
CD
170 /* Undo frame */ ASM_LINE_SEP \
171 ldwm -64(%sp),TREG ASM_LINE_SEP \
8cb8321f 172 .cfi_adjust_cfa_offset -64 ASM_LINE_SEP \
0daa0500 173 /* Restore rp before exit */ ASM_LINE_SEP \
8cb8321f
CD
174 ldw -20(%sp), %rp ASM_LINE_SEP \
175 .cfi_restore 2 ASM_LINE_SEP
da1ea0f0
CD
176
177/* Save arguments into our frame */
178# define PUSHARGS_0 /* nothing to do */
8cb8321f
CD
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
da1ea0f0
CD
191
192/* Bring them back from the stack */
193# define POPARGS_0 /* nothing to do */
8cb8321f
CD
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
da1ea0f0
CD
206
207# ifdef 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 !defined NOT_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
cd153083 231# elif defined IS_IN_librt
da1ea0f0
CD
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
cd153083
CD
243# else
244# error Unsupported library
da1ea0f0
CD
245# endif
246
247# ifdef IS_IN_libpthread
248# define __local_multiple_threads __pthread_multiple_threads
249# elif !defined NOT_IN_libc
250# define __local_multiple_threads __libc_multiple_threads
cd153083 251# elif IS_IN_librt
da1ea0f0 252# define __local_multiple_threads __librt_multiple_threads
cd153083
CD
253# else
254# error Unsupported library
da1ea0f0
CD
255# endif
256
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__
268
269/* This code should never be used but we define it anyhow. */
270# define SINGLE_THREAD_P (1)
271# define NO_CANCELLATION 1
272
273#endif
d396ccd5
CD
274/* !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt */
275
276#ifndef __ASSEMBLER__
277# define RTLD_SINGLE_THREAD_P \
278 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
279 header.multiple_threads) == 0, 1)
280#endif
281