(PSEUDO): Code reordering.
[kopensolaris-gnu/glibc.git] / linuxthreads / sysdeps / unix / sysv / linux / i386 / sysdep-cancel.h
1 /* Copyright (C) 2002 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <sysdep.h>
21 #include <tls.h>
22 #include <pt-machine.h>
23 #ifndef __ASSEMBLER__
24 # include <linuxthreads/internals.h>
25 #endif
26
27 #if !defined NOT_IN_libc || defined IS_IN_libpthread
28
29 # undef PSEUDO
30 # define PSEUDO(name, syscall_name, args)                                     \
31   .text;                                                                      \
32   ENTRY (name)                                                                \
33     SINGLE_THREAD_P;                                                          \
34     jne L(pseudo_cancel);                                                     \
35     DO_CALL (syscall_name, args);                                             \
36     cmpl $-4095, %eax;                                                        \
37     jae SYSCALL_ERROR_LABEL;                                                  \
38     ret;                                                                      \
39   L(pseudo_cancel):                                                           \
40     CENABLE                                                                   \
41     SAVE_OLDTYPE_##args                                                       \
42     PUSHARGS_##args                                                           \
43     DOCARGS_##args                                                            \
44     movl $SYS_ify (syscall_name), %eax;                                       \
45     int $0x80                                                                 \
46     POPARGS_##args;                                                           \
47     POPCARGS_##args                                                           \
48     cmpl $-4095, %eax;                                                        \
49     jae SYSCALL_ERROR_LABEL;                                                  \
50   L(pseudo_end):
51
52 # define SAVE_OLDTYPE_0 movl %eax, %edx;
53 # define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0
54 # define SAVE_OLDTYPE_2 pushl %eax;
55 # define SAVE_OLDTYPE_3 SAVE_OLDTYPE_2
56 # define SAVE_OLDTYPE_4 SAVE_OLDTYPE_2
57 # define SAVE_OLDTYPE_5 SAVE_OLDTYPE_2
58
59 # define DOCARGS_0      DOARGS_0
60 # define DOCARGS_1      DOARGS_1
61 # define DOCARGS_2      _DOARGS_2 (12)
62 # define DOCARGS_3      _DOARGS_3 (20)
63 # define DOCARGS_4      _DOARGS_4 (28)
64 # define DOCARGS_5      _DOARGS_5 (36)
65
66 # ifdef IS_IN_libpthread
67 #  define CENABLE       call __pthread_enable_asynccancel;
68 #  define CDISABLE      call __pthread_disable_asynccancel
69 # else
70 #  define CENABLE       call __libc_enable_asynccancel;
71 #  define CDISABLE      call __libc_disable_asynccancel
72 # endif
73 # define POPCARGS_0     pushl %eax; movl %ecx, %eax; CDISABLE; popl %eax;
74 # define POPCARGS_1     POPCARGS_0
75 # define POPCARGS_2     xchgl (%esp), %eax; CDISABLE; popl %eax;
76 # define POPCARGS_3     POPCARGS_2
77 # define POPCARGS_4     POPCARGS_2
78 # define POPCARGS_5     POPCARGS_2
79
80 #if !defined NOT_IN_libc
81 # define __local_multiple_threads __libc_multiple_threads
82 #else
83 # define __local_multiple_threads __pthread_multiple_threads
84 #endif
85
86 # ifndef __ASSEMBLER__
87 #  if defined FLOATING_STACKS && USE___THREAD && defined PIC
88 #   define SINGLE_THREAD_P \
89   __builtin_expect (THREAD_GETMEM (THREAD_SELF,                               \
90                                    p_header.data.multiple_threads) == 0, 1)
91 #  else
92 extern int __local_multiple_threads attribute_hidden;
93 #   define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
94 #  endif
95 # else
96 #  if !defined PIC
97 #   define SINGLE_THREAD_P cmpl $0, __local_multiple_threads
98 #  elif defined FLOATING_STACKS && USE___THREAD
99 #   define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET
100 #  else
101 #   if !defined HAVE_HIDDEN || !USE___THREAD
102 #    define SINGLE_THREAD_P \
103   SETUP_PIC_REG (cx);                           \
104   addl $_GLOBAL_OFFSET_TABLE_, %ecx;            \
105   cmpl $0, __local_multiple_threads@GOTOFF(%ecx)
106 #   else
107 #    define SINGLE_THREAD_P \
108   call __i686.get_pc_thunk.cx;                  \
109   addl $_GLOBAL_OFFSET_TABLE_, %ecx;            \
110   cmpl $0, __local_multiple_threads@GOTOFF(%ecx)
111 #   endif
112 #  endif
113 # endif
114
115 #elif !defined __ASSEMBLER__
116
117 /* This code should never be used but we define it anyhow.  */
118 # define SINGLE_THREAD_P (1)
119
120 #endif