Back to index

glibc  2.9
sysdep-cancel.h
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003, 2004, 2005, 2006 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 #ifndef __ASSEMBLER__
00023 # include <nptl/pthreadP.h>
00024 #endif
00025 
00026 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
00027 
00028 # undef PSEUDO
00029 # define PSEUDO(name, syscall_name, args)                            \
00030   .text;                                                             \
00031   ENTRY (name)                                                              \
00032     SINGLE_THREAD_P;                                                 \
00033     jne L(pseudo_cancel);                                            \
00034   .type __##syscall_name##_nocancel,@function;                              \
00035   .globl __##syscall_name##_nocancel;                                       \
00036   __##syscall_name##_nocancel:                                              \
00037     DO_CALL (syscall_name, args);                                    \
00038     cmpq $-4095, %rax;                                                      \
00039     jae SYSCALL_ERROR_LABEL;                                                \
00040     ret;                                                             \
00041   .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;          \
00042   L(pseudo_cancel):                                                  \
00043     /* Save registers that might get destroyed.  */                         \
00044     SAVESTK_##args                                                   \
00045     PUSHARGS_##args                                                  \
00046     CENABLE                                                          \
00047     /* Restore registers.  */                                               \
00048     POPARGS_##args                                                   \
00049     /* The return value from CENABLE is argument for CDISABLE.  */          \
00050     movq %rax, (%rsp);                                                      \
00051     movl $SYS_ify (syscall_name), %eax;                                     \
00052     syscall;                                                         \
00053     movq (%rsp), %rdi;                                                      \
00054     /* Save %rax since it's the error code from the syscall.  */            \
00055     movq %rax, 8(%rsp);                                                     \
00056     CDISABLE                                                         \
00057     movq 8(%rsp), %rax;                                                     \
00058     RESTSTK_##args                                                   \
00059     cmpq $-4095, %rax;                                                      \
00060     jae SYSCALL_ERROR_LABEL;                                                \
00061   L(pseudo_end):
00062 
00063 
00064 # define PUSHARGS_0  /* Nothing.  */
00065 # define PUSHARGS_1  PUSHARGS_0 movq %rdi, 8(%rsp);
00066 # define PUSHARGS_2  PUSHARGS_1 movq %rsi, 16(%rsp);
00067 # define PUSHARGS_3  PUSHARGS_2 movq %rdx, 24(%rsp);
00068 # define PUSHARGS_4  PUSHARGS_3 movq %rcx, 32(%rsp);
00069 # define PUSHARGS_5  PUSHARGS_4 movq %r8, 40(%rsp);
00070 # define PUSHARGS_6  PUSHARGS_5 movq %r9, 48(%rsp);
00071 
00072 # define POPARGS_0   /* Nothing.  */
00073 # define POPARGS_1   POPARGS_0 movq 8(%rsp), %rdi;
00074 # define POPARGS_2   POPARGS_1 movq 16(%rsp), %rsi;
00075 # define POPARGS_3   POPARGS_2 movq 24(%rsp), %rdx;
00076 # define POPARGS_4   POPARGS_3 movq 32(%rsp), %r10;
00077 # define POPARGS_5   POPARGS_4 movq 40(%rsp), %r8;
00078 # define POPARGS_6   POPARGS_5 movq 48(%rsp), %r9;
00079 
00080 /* We always have to align the stack before calling a function.  */
00081 # define SAVESTK_0   subq $24, %rsp; cfi_adjust_cfa_offset (24);
00082 # define SAVESTK_1   SAVESTK_0
00083 # define SAVESTK_2   SAVESTK_1
00084 # define SAVESTK_3   subq $40, %rsp; cfi_adjust_cfa_offset (40);
00085 # define SAVESTK_4   SAVESTK_3
00086 # define SAVESTK_5   subq $56, %rsp; cfi_adjust_cfa_offset (56);
00087 # define SAVESTK_6   SAVESTK_5
00088 
00089 # define RESTSTK_0   addq $24,%rsp; cfi_adjust_cfa_offset (-24);
00090 # define RESTSTK_1   RESTSTK_0
00091 # define RESTSTK_2   RESTSTK_1
00092 # define RESTSTK_3   addq $40, %rsp; cfi_adjust_cfa_offset (-40);
00093 # define RESTSTK_4   RESTSTK_3
00094 # define RESTSTK_5   addq $56, %rsp; cfi_adjust_cfa_offset (-56);
00095 # define RESTSTK_6   RESTSTK_5
00096 
00097 # ifdef IS_IN_libpthread
00098 #  define CENABLE    call __pthread_enable_asynccancel;
00099 #  define CDISABLE   call __pthread_disable_asynccancel;
00100 #  define __local_multiple_threads __pthread_multiple_threads
00101 # elif !defined NOT_IN_libc
00102 #  define CENABLE    call __libc_enable_asynccancel;
00103 #  define CDISABLE   call __libc_disable_asynccancel;
00104 #  define __local_multiple_threads __libc_multiple_threads
00105 # elif defined IS_IN_librt
00106 #  define CENABLE    call __librt_enable_asynccancel;
00107 #  define CDISABLE   call __librt_disable_asynccancel;
00108 # else
00109 #  error Unsupported library
00110 # endif
00111 
00112 # if defined IS_IN_libpthread || !defined NOT_IN_libc
00113 #  ifndef __ASSEMBLER__
00114 extern int __local_multiple_threads attribute_hidden;
00115 #   define SINGLE_THREAD_P \
00116   __builtin_expect (__local_multiple_threads == 0, 1)
00117 #  else
00118 #   define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip)
00119 #  endif
00120 
00121 # else
00122 
00123 #  ifndef __ASSEMBLER__
00124 #   define SINGLE_THREAD_P \
00125   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
00126                                header.multiple_threads) == 0, 1)
00127 #  else
00128 #   define SINGLE_THREAD_P cmpl $0, %fs:MULTIPLE_THREADS_OFFSET
00129 #  endif
00130 
00131 # endif
00132 
00133 #elif !defined __ASSEMBLER__
00134 
00135 # define SINGLE_THREAD_P (1)
00136 # define NO_CANCELLATION 1
00137 
00138 #endif
00139 
00140 #ifndef __ASSEMBLER__
00141 # define RTLD_SINGLE_THREAD_P \
00142   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
00143                                header.multiple_threads) == 0, 1)
00144 #endif