Fix %edx clobbering in lseek64, forkx, and pipe syscalls
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / solaris2 / kopensolaris-gnu / i386 / sysdep-cancel.h
1 /* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2008
2     Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
5
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.
10
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.
15
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.  */
20
21 #include <sysdep.h>
22 #include <tls.h>
23 #ifndef __ASSEMBLER__
24 # include <pthreadP.h>
25 #endif
26
27 /* XXX: We don't support _NOERRNO or _ERRVAL varietites.  */
28 #undef PSEUDO_ERRNO
29 #undef PSEUDO_SUBCALL_NOERRNO
30 #undef PSEUDO_ERRVAL
31 #undef PSEUDO_SUBCALL_NOERRNO
32
33 /* This is needed so that we don't clobber %edx in the cancellation calls.  */
34 #ifdef SYSCALL_64BIT_RETURN
35 # define SYSCALL_64BIT_PUSH_ASM     pushl %edx; cfi_adjust_cfa_offset (4);
36 # define SYSCALL_64BIT_POP_ASM      popl %edx; cfi_adjust_cfa_offset (-4);
37 #else
38 # define SYSCALL_64BIT_PUSH_ASM
39 # define SYSCALL_64BIT_POP_ASM
40 #endif
41
42 #ifdef SYSCALL_RESTARTABLE
43 # define DO_RESTART_CANCEL \
44     cmpl $ERESTART, %eax; \
45     je L(restart_cancel);
46 #else
47 # define DO_RESTART_CANCEL
48 #endif
49
50 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
51
52 /* Note that CDISABLE is an internal function, so we need to
53    pass-by-register (we pass the argument in %eax).  */
54
55 # undef  PSEUDO
56 # define PSEUDO(name, syscall_name, args)                      \
57   .text;                                      \
58   ENTRY (name)                                    \
59     cmpl $0, %gs:MULTIPLE_THREADS_OFFSET;                                     \
60     jne L(pseudo_cancel);                                                     \
61   .type __##syscall_name##_nocancel,@function;                                \
62   .globl __##syscall_name##_nocancel;                                         \
63   __##syscall_name##_nocancel:                                                \
64   L(restart):                                       \
65     DO_CALL (syscall_name, args);                         \
66     jnb 2f;                                                                             \
67     DO_RESTART                             \
68     jmp SYSCALL_ERROR_LABEL;                           \
69 2:  ret;                                            \
70   .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;            \
71   L(pseudo_cancel):                                                           \
72   L(restart_cancel):                                       \
73     CENABLE;                                                                  \
74     movl %eax, %ecx;                    \
75     DO_CALL (syscall_name, args);                         \
76     jnb 3f;                                                                             \
77     DO_RESTART_CANCEL                             \
78     pushl %eax; cfi_adjust_cfa_offset (4);  \
79     SYSCALL_64BIT_PUSH_ASM                  \
80     movl %ecx, %eax;                        \
81     CDISABLE;                           \
82     SYSCALL_64BIT_POP_ASM                     \
83     popl %eax; cfi_adjust_cfa_offset (-4);    \
84     jmp SYSCALL_ERROR_LABEL;                           \
85 3:                                                  \
86     pushl %eax; cfi_adjust_cfa_offset (4);  \
87     SYSCALL_64BIT_PUSH_ASM                  \
88     movl %ecx, %eax;                        \
89     CDISABLE;                           \
90     SYSCALL_64BIT_POP_ASM                     \
91     popl %eax; cfi_adjust_cfa_offset (-4);    \
92   L(pseudo_end):
93
94 /* XXX: This uses %edx, so subcalls that return 64-bit ints won't work.  */
95 # undef  PSEUDO_SUBCALL
96 # define PSEUDO_SUBCALL(name, syscall_name, subcall_name, args)                               \
97   .text;                                      \
98   ENTRY (name)                                    \
99     cmpl $0, %gs:MULTIPLE_THREADS_OFFSET;                                     \
100     jne L(pseudo_cancel);                                                     \
101   .type __##subcall_name##_nocancel,@function;                                \
102   .globl __##subcall_name##_nocancel;                                         \
103   __##subcall_name##_nocancel:                                                \
104     movl 0(%esp), %ecx;                               \
105     movl %ecx, -4(%esp);                                                        \
106     addl $-4, %esp;                             \
107     movl $SYS_ify (SUB_##subcall_name), 4(%esp);                                                        \
108   L(restart):                                       \
109     DO_CALL (syscall_name, args);                         \
110     jnb 2f;                                                                             \
111     DO_RESTART                             \
112     movl %ecx, 4(%esp);                                                 \
113     addl $-4, %esp;                             \
114     jmp SYSCALL_ERROR_LABEL;                           \
115 2:                                                                                      \
116     addl $4, %esp;                                     \
117     movl %ecx, 0(%esp);                                                 \
118     ret;                                            \
119   .size __##subcall_name##_nocancel,.-__##subcall_name##_nocancel;            \
120   L(pseudo_cancel):                                                           \
121     CENABLE;                                                                  \
122     movl %eax, %ecx;                    \
123     movl 0(%esp), %edx;                               \
124     movl %edx, -4(%esp);                        \
125     addl $-4, %esp;                             \
126     movl $SYS_ify (SUB_##subcall_name), 4(%esp);                                                        \
127   L(restart_cancel):                                       \
128     DO_CALL (syscall_name, args);                         \
129     jnb 3f;                                                                             \
130     DO_RESTART_CANCEL                             \
131     pushl %eax; cfi_adjust_cfa_offset (4);  \
132     SYSCALL_64BIT_PUSH_ASM                  \
133     movl %ecx, %eax;                        \
134     CDISABLE;                           \
135     SYSCALL_64BIT_POP_ASM                     \
136     popl %eax; cfi_adjust_cfa_offset (-4);    \
137     movl 0(%esp), %ecx;                               \
138     movl %ecx, 4(%esp);                                                 \
139     addl $4, %esp;                          \
140     jmp SYSCALL_ERROR_LABEL;                           \
141 3:                                                                                      \
142     pushl %eax; cfi_adjust_cfa_offset (4);  \
143     SYSCALL_64BIT_PUSH_ASM                  \
144     movl %ecx, %eax;                        \
145     CDISABLE;                           \
146     SYSCALL_64BIT_POP_ASM                     \
147     popl %eax; cfi_adjust_cfa_offset (-4);    \
148     movl 0(%esp), %ecx;                               \
149     movl %ecx, 4(%esp);                                                 \
150     addl $4, %esp;                          \
151   L(pseudo_end):
152
153
154 # define SAVE_OLDTYPE   movl %eax, %ecx;
155 # ifdef IS_IN_libpthread
156 #  define CENABLE       call __pthread_enable_asynccancel;
157 #  define CDISABLE      call __pthread_disable_asynccancel
158 # elif !defined NOT_IN_libc
159 #  define CENABLE       call __libc_enable_asynccancel;
160 #  define CDISABLE      call __libc_disable_asynccancel
161 # elif defined IS_IN_librt
162 #  define CENABLE       call __librt_enable_asynccancel;
163 #  define CDISABLE      call __librt_disable_asynccancel
164 # else
165 #  error Unsupported library
166 # endif
167
168 # ifndef __ASSEMBLER__
169 #  define SINGLE_THREAD_P \
170   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
171                                    header.multiple_threads) == 0, 1)
172 # else
173 #  define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET
174 # endif
175
176 #elif !defined __ASSEMBLER__
177
178 # define SINGLE_THREAD_P (1)
179 # define NO_CANCELLATION 1
180
181 #endif
182
183 #ifndef __ASSEMBLER__
184 # define RTLD_SINGLE_THREAD_P \
185   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
186                                    header.multiple_threads) == 0, 1)
187 #endif