f9d010cf2984e0c743f12dd42451d805d242c805
[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 #ifdef SYSCALL_RESTARTABLE
34 # define DO_RESTART_CANCEL \
35     cmpl $ERESTART, %eax; \
36     je L(restart_cancel);
37 #else
38 # define DO_RESTART_CANCEL
39 #endif
40
41 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
42
43 /* Note that CDISABLE is an internal function, so we need to
44    pass-by-register (we pass the argument in %eax).  */
45
46 # undef  PSEUDO
47 # define PSEUDO(name, syscall_name, args)                      \
48   .text;                                      \
49   ENTRY (name)                                    \
50     cmpl $0, %gs:MULTIPLE_THREADS_OFFSET;                                     \
51     jne L(pseudo_cancel);                                                     \
52   .type __##syscall_name##_nocancel,@function;                                \
53   .globl __##syscall_name##_nocancel;                                         \
54   __##syscall_name##_nocancel:                                                \
55   L(restart):                                       \
56     DO_CALL (syscall_name, args);                         \
57     jnb 2f;                                                                             \
58     DO_RESTART                             \
59     jmp SYSCALL_ERROR_LABEL;                           \
60 2:  ret;                                            \
61   .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;            \
62   L(pseudo_cancel):                                                           \
63   L(restart_cancel):                                       \
64     CENABLE;                                                                  \
65     movl %eax, %ecx;                    \
66     DO_CALL (syscall_name, args);                         \
67     jnb 3f;                                                                             \
68     DO_RESTART_CANCEL                             \
69     pushl %eax; cfi_adjust_cfa_offset (4);  \
70     movl %ecx, %eax;                        \
71     CDISABLE;                           \
72     popl %eax; cfi_adjust_cfa_offset (-4);    \
73     jmp SYSCALL_ERROR_LABEL;                           \
74 3:                                                  \
75     pushl %eax; cfi_adjust_cfa_offset (4);  \
76     movl %ecx, %eax;                        \
77     CDISABLE;                           \
78     popl %eax; cfi_adjust_cfa_offset (-4);    \
79   L(pseudo_end):
80
81 /* XXX: This uses %edx, so subcalls that return 64-bit ints won't work.  */
82 # undef  PSEUDO_SUBCALL
83 # define PSEUDO_SUBCALL(name, syscall_name, subcall_name, args)                               \
84   .text;                                      \
85   ENTRY (name)                                    \
86     cmpl $0, %gs:MULTIPLE_THREADS_OFFSET;                                     \
87     jne L(pseudo_cancel);                                                     \
88   .type __##subcall_name##_nocancel,@function;                                \
89   .globl __##subcall_name##_nocancel;                                         \
90   __##subcall_name##_nocancel:                                                \
91     movl 0(%esp), %ecx;                               \
92     movl %ecx, -4(%esp);                                                        \
93     addl $-4, %esp;                             \
94     movl $SYS_ify (SUB_##subcall_name), 4(%esp);                                                        \
95   L(restart):                                       \
96     DO_CALL (syscall_name, args);                         \
97     jnb 2f;                                                                             \
98     DO_RESTART                             \
99     movl %ecx, 4(%esp);                                                 \
100     addl $-4, %esp;                             \
101     jmp SYSCALL_ERROR_LABEL;                           \
102 2:                                                                                      \
103     addl $4, %esp;                                     \
104     movl %ecx, 0(%esp);                                                 \
105     ret;                                            \
106   .size __##subcall_name##_nocancel,.-__##subcall_name##_nocancel;            \
107   L(pseudo_cancel):                                                           \
108     CENABLE;                                                                  \
109     movl %eax, %ecx;                    \
110     movl 0(%esp), %edx;                               \
111     movl %edx, -4(%esp);                        \
112     addl $-4, %esp;                             \
113     movl $SYS_ify (SUB_##subcall_name), 4(%esp);                                                        \
114   L(restart_cancel):                                       \
115     DO_CALL (syscall_name, args);                         \
116     jnb 3f;                                                                             \
117     DO_RESTART_CANCEL                             \
118     pushl %eax; cfi_adjust_cfa_offset (4);  \
119     movl %ecx, %eax;                        \
120     CDISABLE;                           \
121     popl %eax; cfi_adjust_cfa_offset (-4);    \
122     movl 0(%esp), %ecx;                               \
123     movl %ecx, 4(%esp);                                                 \
124     addl $4, %esp;                          \
125     jmp SYSCALL_ERROR_LABEL;                           \
126 3:                                                                                      \
127     pushl %eax; cfi_adjust_cfa_offset (4);  \
128     movl %ecx, %eax;                        \
129     CDISABLE;                           \
130     popl %eax; cfi_adjust_cfa_offset (-4);    \
131     movl 0(%esp), %ecx;                               \
132     movl %ecx, 4(%esp);                                                 \
133     addl $4, %esp;                          \
134   L(pseudo_end):
135
136
137 # define SAVE_OLDTYPE   movl %eax, %ecx;
138 # ifdef IS_IN_libpthread
139 #  define CENABLE       call __pthread_enable_asynccancel;
140 #  define CDISABLE      call __pthread_disable_asynccancel
141 # elif !defined NOT_IN_libc
142 #  define CENABLE       call __libc_enable_asynccancel;
143 #  define CDISABLE      call __libc_disable_asynccancel
144 # elif defined IS_IN_librt
145 #  define CENABLE       call __librt_enable_asynccancel;
146 #  define CDISABLE      call __librt_disable_asynccancel
147 # else
148 #  error Unsupported library
149 # endif
150
151 # ifndef __ASSEMBLER__
152 #  define SINGLE_THREAD_P \
153   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
154                                    header.multiple_threads) == 0, 1)
155 # else
156 #  define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET
157 # endif
158
159 #elif !defined __ASSEMBLER__
160
161 # define SINGLE_THREAD_P (1)
162 # define NO_CANCELLATION 1
163
164 #endif
165
166 #ifndef __ASSEMBLER__
167 # define RTLD_SINGLE_THREAD_P \
168   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
169                                    header.multiple_threads) == 0, 1)
170 #endif