(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / linuxthreads / sysdeps / unix / sysv / linux / hppa / sysdep-cancel.h
blob134977e074fb5b2a0aff24c5c2f1c0226b624676
1 /* cancellable system calls for Linux/HPPA.
2 Copyright (C) 2003 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Carlos O'Donell <carlos@baldric.uwo.ca>, 2003.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
21 #include <sysdep.h>
22 #ifndef __ASSEMBLER__
23 # include <linuxthreads/internals.h>
24 #endif
26 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
28 # ifndef NO_ERROR
29 # define NO_ERROR -0x1000
30 # endif
32 # undef PSEUDO
33 # define PSEUDO(name, syscall_name, args) \
34 ENTRY (name) \
35 SINGLE_THREAD_P ASM_LINE_SEP \
36 cmpib,<> 0,%ret0,Lpseudo_cancel ASM_LINE_SEP \
37 nop ASM_LINE_SEP \
38 DO_CALL(syscall_name, args) ASM_LINE_SEP \
39 /* DONE! */ ASM_LINE_SEP \
40 bv 0(2) ASM_LINE_SEP \
41 nop ASM_LINE_SEP \
42 Lpseudo_cancel: ASM_LINE_SEP \
43 /* store return ptr */ ASM_LINE_SEP \
44 stw %rp, -20(%sr0,%sp) ASM_LINE_SEP \
45 /* save syscall args */ ASM_LINE_SEP \
46 PUSHARGS_##args /* MACRO */ ASM_LINE_SEP \
47 STW_PIC ASM_LINE_SEP \
48 CENABLE /* FUNC CALL */ ASM_LINE_SEP \
49 ldo 64(%sp), %sp ASM_LINE_SEP \
50 ldo -64(%sp), %sp ASM_LINE_SEP \
51 LDW_PIC ASM_LINE_SEP \
52 /* restore syscall args */ ASM_LINE_SEP \
53 POPARGS_##args ASM_LINE_SEP \
54 /* save r4 in arg0 stack slot */ ASM_LINE_SEP \
55 stw %r4, -36(%sr0,%sp) ASM_LINE_SEP \
56 /* save mask from cenable */ ASM_LINE_SEP \
57 copy %ret0, %r4 ASM_LINE_SEP \
58 ble 0x100(%sr2,%r0) ASM_LINE_SEP \
59 ldi SYS_ify (syscall_name), %r20 ASM_LINE_SEP \
60 LDW_PIC ASM_LINE_SEP \
61 /* pass mask as arg0 to cdisable */ ASM_LINE_SEP \
62 copy %r4, %r26 ASM_LINE_SEP \
63 copy %ret0, %r4 ASM_LINE_SEP \
64 CDISABLE ASM_LINE_SEP \
65 ldo 64(%sp), %sp ASM_LINE_SEP \
66 ldo -64(%sp), %sp ASM_LINE_SEP \
67 LDW_PIC ASM_LINE_SEP \
68 /* compare error */ ASM_LINE_SEP \
69 ldi NO_ERROR,%r1 ASM_LINE_SEP \
70 /* branch if no error */ ASM_LINE_SEP \
71 cmpb,>>=,n %r1,%r4,Lpre_end ASM_LINE_SEP \
72 nop ASM_LINE_SEP \
73 SYSCALL_ERROR_HANDLER ASM_LINE_SEP \
74 ldo 64(%sp), %sp ASM_LINE_SEP \
75 ldo -64(%sp), %sp ASM_LINE_SEP \
76 /* No need to LDW_PIC */ ASM_LINE_SEP \
77 /* make syscall res value positive */ ASM_LINE_SEP \
78 sub %r0, %r4, %r4 ASM_LINE_SEP \
79 /* store into errno location */ ASM_LINE_SEP \
80 stw %r4, 0(%sr0,%ret0) ASM_LINE_SEP \
81 /* return -1 */ ASM_LINE_SEP \
82 ldo -1(%r0), %ret0 ASM_LINE_SEP \
83 Lpre_end: ASM_LINE_SEP \
84 ldw -20(%sr0,%sp), %rp ASM_LINE_SEP \
85 /* No need to LDW_PIC */ ASM_LINE_SEP \
86 ldw -36(%sr0,%sp), %r4 ASM_LINE_SEP
88 /* Save arguments into our frame */
89 # define PUSHARGS_0 /* nothing to do */
90 # define PUSHARGS_1 PUSHARGS_0 stw %r26, -36(%sr0,%sp) ASM_LINE_SEP
91 # define PUSHARGS_2 PUSHARGS_1 stw %r25, -40(%sr0,%sp) ASM_LINE_SEP
92 # define PUSHARGS_3 PUSHARGS_2 stw %r24, -44(%sr0,%sp) ASM_LINE_SEP
93 # define PUSHARGS_4 PUSHARGS_3 stw %r23, -48(%sr0,%sp) ASM_LINE_SEP
94 # define PUSHARGS_5 PUSHARGS_4 /* Args are on the stack... */
95 # define PUSHARGS_6 PUSHARGS_5
97 /* Bring them back from the stack */
98 # define POPARGS_0 /* nothing to do */
99 # define POPARGS_1 POPARGS_0 ldw -36(%sr0,%sp), %r26 ASM_LINE_SEP
100 # define POPARGS_2 POPARGS_1 ldw -40(%sr0,%sp), %r25 ASM_LINE_SEP
101 # define POPARGS_3 POPARGS_2 ldw -44(%sr0,%sp), %r24 ASM_LINE_SEP
102 # define POPARGS_4 POPARGS_3 ldw -48(%sr0,%sp), %r23 ASM_LINE_SEP
103 # define POPARGS_5 POPARGS_4 ldw -52(%sr0,%sp), %r22 ASM_LINE_SEP
104 # define POPARGS_6 POPARGS_5 ldw -54(%sr0,%sp), %r21 ASM_LINE_SEP
106 # ifdef IS_IN_libpthread
107 # ifdef PIC
108 # define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \
109 bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP
110 # define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \
111 bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP
112 # else
113 # define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \
114 bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP
115 # define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \
116 bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP
117 # endif
118 # elif !defined NOT_IN_libc
119 # ifdef PIC
120 # define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \
121 bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP
122 # define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \
123 bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP
124 # else
125 # define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \
126 bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP
127 # define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \
128 bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP
129 # endif
130 # else
131 # ifdef PIC
132 # define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \
133 bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP
134 # define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \
135 bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP
136 # else
137 # define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \
138 bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP
139 # define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \
140 bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP
141 # endif
142 # endif
144 /* p_header.multiple_threads is +12 from the pthread_descr struct start,
145 We could have called __get_cr27() but we really want less overhead */
146 # define MULTIPLE_THREADS_OFFSET 0xC
148 /* cr27 has been initialized to 0x0 by kernel */
149 # define NO_THREAD_CR27 0x0
151 # ifdef IS_IN_libpthread
152 # define __local_multiple_threads __pthread_multiple_threads
153 # elif !defined NOT_IN_libc
154 # define __local_multiple_threads __libc_multiple_threads
155 # else
156 # define __local_multiple_threads __librt_multiple_threads
157 # endif
159 # ifndef __ASSEMBLER__
160 extern int __local_multiple_threads attribute_hidden;
161 # define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
162 # else
163 /* This ALT version requires newer kernel support */
164 # define SINGLE_THREAD_P_MFCTL \
165 mfctl %cr27, %ret0 ASM_LINE_SEP \
166 cmpib,= NO_THREAD_CR27,%ret0,Lstp ASM_LINE_SEP \
167 nop ASM_LINE_SEP \
168 ldw MULTIPLE_THREADS_OFFSET(%sr0,%ret0),%ret0 ASM_LINE_SEP \
169 Lstp: ASM_LINE_SEP
170 # ifdef PIC
171 /* Slower version uses GOT to get value of __local_multiple_threads */
172 # define SINGLE_THREAD_P \
173 addil LT%__local_multiple_threads, %r19 ASM_LINE_SEP \
174 ldw RT%__local_multiple_threads(%sr0,%r1), %ret0 ASM_LINE_SEP \
175 ldw 0(%sr0,%ret0), %ret0 ASM_LINE_SEP
176 # else
177 /* Slow non-pic version using DP */
178 # define SINGLE_THREAD_P \
179 addil LR%__local_multiple_threads-$global$,%r27 ASM_LINE_SEP \
180 ldw RR%__local_multiple_threads-$global$(%sr0,%r1),%ret0 ASM_LINE_SEP
181 # endif
182 # endif
183 #elif !defined __ASSEMBLER__
185 /* This code should never be used but we define it anyhow. */
186 # define SINGLE_THREAD_P (1)
188 #endif
189 /* !defined NOT_IN_libc || defined IS_IN_libpthread */