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
23 # include <linuxthreads/internals.h>
26 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
29 # define NO_ERROR -0x1000
33 # define PSEUDO(name, syscall_name, args) \
35 SINGLE_THREAD_P ASM_LINE_SEP \
36 cmpib,<> 0,%ret0,Lpseudo_cancel ASM_LINE_SEP \
38 DO_CALL(syscall_name, args) ASM_LINE_SEP \
39 /* DONE! */ ASM_LINE_SEP \
40 bv 0(2) 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 \
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
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
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
118 # elif !defined NOT_IN_libc
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
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
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
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
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
156 # define __local_multiple_threads __librt_multiple_threads
159 # ifndef __ASSEMBLER__
160 extern int __local_multiple_threads attribute_hidden
;
161 # define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
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 \
168 ldw MULTIPLE_THREADS_OFFSET(%sr0,%ret0),%ret0 ASM_LINE_SEP \
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
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
183 #elif !defined __ASSEMBLER__
185 /* This code should never be used but we define it anyhow. */
186 # define SINGLE_THREAD_P (1)
189 /* !defined NOT_IN_libc || defined IS_IN_libpthread */