Back to index

glibc  2.9
sysdep-cancel.h
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <sysdep.h>
00021 #include <tls.h>
00022 #include <pt-machine.h>
00023 #ifndef __ASSEMBLER__
00024 # include <linuxthreads/internals.h>
00025 #endif
00026 
00027 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
00028 
00029 # undef PSEUDO
00030 # define PSEUDO(name, syscall_name, args)                            \
00031   .text;                                                             \
00032   ENTRY (name)                                                              \
00033     SINGLE_THREAD_P;                                                 \
00034     jne L(pseudo_cancel);                                            \
00035     DO_CALL (syscall_name, args);                                    \
00036     cmpq $-4095, %rax;                                                      \
00037     jae SYSCALL_ERROR_LABEL;                                                \
00038     ret;                                                             \
00039   L(pseudo_cancel):                                                  \
00040     /* Save registers that might get destroyed.  */                         \
00041     SAVESTK_##args                                                   \
00042     PUSHARGS_##args                                                  \
00043     CENABLE                                                          \
00044     /* Restore registers.  */                                               \
00045     POPARGS_##args                                                   \
00046     /* The return value from CENABLE is argument for CDISABLE.  */          \
00047     movq %rax, (%rsp);                                                      \
00048     movl $SYS_ify (syscall_name), %eax;                                     \
00049     syscall;                                                         \
00050     movq (%rsp), %rdi;                                                      \
00051     /* Save %rax since it's the error code from the syscall.  */            \
00052     movq %rax, 8(%rsp);                                                     \
00053     CDISABLE                                                         \
00054     movq 8(%rsp), %rax;                                                     \
00055     RESTSTK_##args                                                   \
00056     cmpq $-4095, %rax;                                                      \
00057     jae SYSCALL_ERROR_LABEL;                                                \
00058   L(pseudo_end):
00059 
00060 # define PUSHARGS_0  /* Nothing.  */
00061 # define PUSHARGS_1  PUSHARGS_0 movq %rdi, 8(%rsp);
00062 # define PUSHARGS_2  PUSHARGS_1 movq %rsi, 16(%rsp);
00063 # define PUSHARGS_3  PUSHARGS_2 movq %rdx, 24(%rsp);
00064 # define PUSHARGS_4  PUSHARGS_3 movq %rcx, 32(%rsp);
00065 # define PUSHARGS_5  PUSHARGS_4 movq %r8, 40(%rsp);
00066 # define PUSHARGS_6  PUSHARGS_5 movq %r9, 48(%rsp);
00067 
00068 # define POPARGS_0   /* Nothing.  */
00069 # define POPARGS_1   POPARGS_0 movq 8(%rsp), %rdi;
00070 # define POPARGS_2   POPARGS_1 movq 16(%rsp), %rsi;
00071 # define POPARGS_3   POPARGS_2 movq 24(%rsp), %rdx;
00072 # define POPARGS_4   POPARGS_3 movq 32(%rsp), %r10;
00073 # define POPARGS_5   POPARGS_4 movq 40(%rsp), %r8;
00074 # define POPARGS_6   POPARGS_5 movq 48(%rsp), %r9;
00075 
00076 /* We always have to align the stack before calling a function.  */
00077 # define SAVESTK_0   subq $24, %rsp;cfi_adjust_cfa_offset(24);
00078 # define SAVESTK_1   SAVESTK_0
00079 # define SAVESTK_2   SAVESTK_1
00080 # define SAVESTK_3   subq $40, %rsp;cfi_adjust_cfa_offset(40);
00081 # define SAVESTK_4   SAVESTK_3
00082 # define SAVESTK_5   subq $56, %rsp;cfi_adjust_cfa_offset(56);
00083 # define SAVESTK_6   SAVESTK_5
00084 
00085 # define RESTSTK_0   addq $24,%rsp;cfi_adjust_cfa_offset(-24);
00086 # define RESTSTK_1   RESTSTK_0
00087 # define RESTSTK_2   RESTSTK_1
00088 # define RESTSTK_3   addq $40, %rsp;cfi_adjust_cfa_offset(-40);
00089 # define RESTSTK_4   RESTSTK_3
00090 # define RESTSTK_5   addq $56, %rsp;cfi_adjust_cfa_offset(-56);
00091 # define RESTSTK_6   RESTSTK_5
00092 
00093 # ifdef IS_IN_libpthread
00094 #  define CENABLE    call __pthread_enable_asynccancel;
00095 #  define CDISABLE   call __pthread_disable_asynccancel;
00096 #  define __local_multiple_threads __pthread_multiple_threads
00097 # elif !defined NOT_IN_libc
00098 #  define CENABLE    call __libc_enable_asynccancel;
00099 #  define CDISABLE   call __libc_disable_asynccancel;
00100 #  define __local_multiple_threads __libc_multiple_threads
00101 # else
00102 #  define CENABLE    call __librt_enable_asynccancel@plt;
00103 #  define CDISABLE   call __librt_disable_asynccancel@plt;
00104 # endif
00105 
00106 # if defined IS_IN_libpthread || !defined NOT_IN_libc
00107 #  ifndef __ASSEMBLER__
00108 extern int __local_multiple_threads attribute_hidden;
00109 #   define SINGLE_THREAD_P \
00110   __builtin_expect (__local_multiple_threads == 0, 1)
00111 #  else
00112 #   define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip)
00113 #  endif
00114 
00115 # else
00116 
00117 #  ifndef __ASSEMBLER__
00118 #   define SINGLE_THREAD_P \
00119   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
00120                                p_header.data.multiple_threads) == 0, 1)
00121 #  else
00122 #   define SINGLE_THREAD_P cmpl $0, %fs:MULTIPLE_THREADS_OFFSET
00123 #  endif
00124 
00125 # endif
00126 
00127 #elif !defined __ASSEMBLER__
00128 
00129 /* This code should never be used but we define it anyhow.  */
00130 # define SINGLE_THREAD_P (1)
00131 
00132 #endif