]> git.ipfire.org Git - thirdparty/glibc.git/blame - 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
CommitLineData
bfff8b1b 1/* Copyright (C) 2005-2017 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>
da1ea0f0
CD
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)
da1ea0f0
CD
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
5abebba4 33 do arguments (read arg5 and arg6 to registers)
da1ea0f0 34 setup frame
5556231d 35
da1ea0f0 36 check if there are threads, yes jump to pseudo_cancel
5556231d 37
da1ea0f0
CD
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)
5556231d 44
da1ea0f0
CD
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
5556231d 52
da1ea0f0
CD
53 pre_end
54 restore stack
5556231d 55
da1ea0f0 56 It is expected that 'ret' and 'END' macros will
5556231d 57 append an 'undo arguments' and 'return' to the
da1ea0f0 58 this PSEUDO macro. */
5556231d 59
da1ea0f0
CD
60# undef PSEUDO
61# define PSEUDO(name, syscall_name, args) \
8cb8321f
CD
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 \
90L(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 \
da1ea0f0
CD
101 ENTRY (name) \
102 DOARGS_##args ASM_LINE_SEP \
0daa0500 103 stwm TREG, 64(%sp) ASM_LINE_SEP \
8cb8321f 104 .cfi_adjust_cfa_offset 64 ASM_LINE_SEP \
0daa0500 105 stw %sp, -4(%sp) ASM_LINE_SEP \
8cb8321f 106 .cfi_offset 30, -4 ASM_LINE_SEP \
0daa0500 107 stw %r19, -32(%sp) ASM_LINE_SEP \
8cb8321f 108 .cfi_offset 19, -32 ASM_LINE_SEP \
da1ea0f0
CD
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 \
112L(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 \
0daa0500 132 ldi -1, %ret0 /* delay */ ASM_LINE_SEP \
da1ea0f0
CD
133L(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 \
0daa0500 166 ldi -1, %ret0 ASM_LINE_SEP \
da1ea0f0 167L(pre_end): ASM_LINE_SEP \
0daa0500 168 /* No need to LOAD_PIC */ ASM_LINE_SEP \
da1ea0f0
CD
169 /* Undo frame */ ASM_LINE_SEP \
170 ldwm -64(%sp),TREG ASM_LINE_SEP \
8cb8321f 171 .cfi_adjust_cfa_offset -64 ASM_LINE_SEP \
0daa0500 172 /* Restore rp before exit */ ASM_LINE_SEP \
8cb8321f
CD
173 ldw -20(%sp), %rp ASM_LINE_SEP \
174 .cfi_restore 2 ASM_LINE_SEP
da1ea0f0
CD
175
176/* Save arguments into our frame */
177# define PUSHARGS_0 /* nothing to do */
8cb8321f
CD
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
da1ea0f0
CD
190
191/* Bring them back from the stack */
192# define POPARGS_0 /* nothing to do */
8cb8321f
CD
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
da1ea0f0 205
ce9f10f7 206# if IS_IN (libpthread)
da1ea0f0
CD
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
4f41c682 218# elif IS_IN (libc)
da1ea0f0
CD
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
016afc75 230# elif IS_IN (librt)
da1ea0f0
CD
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
cd153083
CD
242# else
243# error Unsupported library
da1ea0f0
CD
244# endif
245
ce9f10f7 246# if IS_IN (libpthread)
da1ea0f0 247# define __local_multiple_threads __pthread_multiple_threads
4f41c682 248# elif IS_IN (libc)
da1ea0f0 249# define __local_multiple_threads __libc_multiple_threads
016afc75 250# elif IS_IN (librt)
da1ea0f0 251# define __local_multiple_threads __librt_multiple_threads
cd153083
CD
252# else
253# error Unsupported library
da1ea0f0
CD
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 */
5abebba4 262# define SINGLE_THREAD_P \
da1ea0f0
CD
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
4f41c682 273/* IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt) */
d396ccd5
CD
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