Updated to fedora-glibc-20041006T0900
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / sysdep-cancel.h
1 /* Copyright (C) 2002, 2003, 2004 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 #ifndef __ASSEMBLER__
23 # include <nptl/pthreadP.h>
24 #endif
25
26 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
27
28 # undef PSEUDO
29 # define PSEUDO(name, syscall_name, args)                                     \
30   .text;                                                                      \
31   ENTRY (name)                                                                \
32     SINGLE_THREAD_P;                                                          \
33     jne L(pseudo_cancel);                                                     \
34   .type __##syscall_name##_nocancel,@function;                                \
35   .globl __##syscall_name##_nocancel;                                         \
36   __##syscall_name##_nocancel:                                                \
37     DO_CALL (syscall_name, args);                                             \
38     cmpq $-4095, %rax;                                                        \
39     jae SYSCALL_ERROR_LABEL;                                                  \
40     ret;                                                                      \
41   .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;            \
42   L(pseudo_cancel):                                                           \
43     /* Save registers that might get destroyed.  */                           \
44     SAVESTK_##args                                                            \
45     PUSHARGS_##args                                                           \
46     CENABLE                                                                   \
47     /* Restore registers.  */                                                 \
48     POPARGS_##args                                                            \
49     /* The return value from CENABLE is argument for CDISABLE.  */            \
50     movq %rax, (%rsp);                                                        \
51     movq $SYS_ify (syscall_name), %rax;                                       \
52     syscall;                                                                  \
53     movq (%rsp), %rdi;                                                        \
54     /* Save %rax since it's the error code from the syscall.  */              \
55     movq %rax, 8(%rsp);                                                       \
56     CDISABLE                                                                  \
57     movq 8(%rsp), %rax;                                                       \
58     RESTSTK_##args                                                            \
59     cmpq $-4095, %rax;                                                        \
60     jae SYSCALL_ERROR_LABEL;                                                  \
61   L(pseudo_end):
62
63
64 # define PUSHARGS_0     /* Nothing.  */
65 # define PUSHARGS_1     PUSHARGS_0 movq %rdi, 8(%rsp);
66 # define PUSHARGS_2     PUSHARGS_1 movq %rsi, 16(%rsp);
67 # define PUSHARGS_3     PUSHARGS_2 movq %rdx, 24(%rsp);
68 # define PUSHARGS_4     PUSHARGS_3 movq %rcx, 32(%rsp);
69 # define PUSHARGS_5     PUSHARGS_4 movq %r8, 40(%rsp);
70 # define PUSHARGS_6     PUSHARGS_5 movq %r9, 48(%rsp);
71
72 # define POPARGS_0      /* Nothing.  */
73 # define POPARGS_1      POPARGS_0 movq 8(%rsp), %rdi;
74 # define POPARGS_2      POPARGS_1 movq 16(%rsp), %rsi;
75 # define POPARGS_3      POPARGS_2 movq 24(%rsp), %rdx;
76 # define POPARGS_4      POPARGS_3 movq 32(%rsp), %r10;
77 # define POPARGS_5      POPARGS_4 movq 40(%rsp), %r8;
78 # define POPARGS_6      POPARGS_5 movq 48(%rsp), %r9;
79
80 /* We always have to align the stack before calling a function.  */
81 # define SAVESTK_0      subq $24, %rsp; cfi_adjust_cfa_offset (24);
82 # define SAVESTK_1      SAVESTK_0
83 # define SAVESTK_2      SAVESTK_1
84 # define SAVESTK_3      subq $40, %rsp; cfi_adjust_cfa_offset (40);
85 # define SAVESTK_4      SAVESTK_3
86 # define SAVESTK_5      subq $56, %rsp; cfi_adjust_cfa_offset (56);
87 # define SAVESTK_6      SAVESTK_5
88
89 # define RESTSTK_0      addq $24,%rsp; cfi_adjust_cfa_offset (-24);
90 # define RESTSTK_1      RESTSTK_0
91 # define RESTSTK_2      RESTSTK_1
92 # define RESTSTK_3      addq $40, %rsp; cfi_adjust_cfa_offset (-40);
93 # define RESTSTK_4      RESTSTK_3
94 # define RESTSTK_5      addq $56, %rsp; cfi_adjust_cfa_offset (-56);
95 # define RESTSTK_6      RESTSTK_5
96
97 # ifdef IS_IN_libpthread
98 #  define CENABLE       call __pthread_enable_asynccancel;
99 #  define CDISABLE      call __pthread_disable_asynccancel;
100 #  define __local_multiple_threads __pthread_multiple_threads
101 # elif !defined NOT_IN_libc
102 #  define CENABLE       call __libc_enable_asynccancel;
103 #  define CDISABLE      call __libc_disable_asynccancel;
104 #  define __local_multiple_threads __libc_multiple_threads
105 # elif defined IS_IN_librt
106 #  define CENABLE       call __librt_enable_asynccancel;
107 #  define CDISABLE      call __librt_disable_asynccancel;
108 # else
109 #  error Unsupported library
110 # endif
111
112 # if defined IS_IN_libpthread || !defined NOT_IN_libc
113 #  ifndef __ASSEMBLER__
114 extern int __local_multiple_threads attribute_hidden;
115 #   define SINGLE_THREAD_P \
116   __builtin_expect (__local_multiple_threads == 0, 1)
117 #  else
118 #   define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip)
119 #  endif
120
121 # else
122
123 #  ifndef __ASSEMBLER__
124 #   define SINGLE_THREAD_P \
125   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
126                                    header.multiple_threads) == 0, 1)
127 #  else
128 #   define SINGLE_THREAD_P cmpl $0, %fs:MULTIPLE_THREADS_OFFSET
129 #  endif
130
131 # endif
132
133 #elif !defined __ASSEMBLER__
134
135 # define SINGLE_THREAD_P (1)
136 # define NO_CANCELLATION 1
137
138 #endif