Back to index

glibc  2.9
sysdep-cancel.h
Go to the documentation of this file.
00001 /* Copyright (C) 2005 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <sysdep.h>
00020 #include <sysdeps/generic/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 # ifndef NO_ERROR
00029 #  define NO_ERROR -0x1000
00030 # endif
00031 
00032 /* The syscall cancellation mechanism requires userspace
00033    assistance, the following code does roughly this:
00034 
00035        do arguments (read arg5 and arg6 to registers)
00036        setup frame
00037        
00038        check if there are threads, yes jump to pseudo_cancel
00039        
00040        unthreaded:
00041               syscall
00042               check syscall return (jump to pre_end)
00043               set errno
00044               set return to -1
00045               (jump to pre_end)
00046               
00047        pseudo_cancel:
00048               cenable
00049               syscall
00050               cdisable
00051               check syscall return (jump to pre_end)
00052               set errno
00053               set return to -1
00054               
00055        pre_end
00056               restore stack
00057        
00058        It is expected that 'ret' and 'END' macros will
00059        append an 'undo arguments' and 'return' to the 
00060        this PSEUDO macro. */
00061    
00062 # undef PSEUDO
00063 # define PSEUDO(name, syscall_name, args)                      \
00064        ENTRY (name)                                            \
00065        DOARGS_##args                             ASM_LINE_SEP  \
00066        stwm TREG, 64(%sp)                        ASM_LINE_SEP  \
00067        stw %sp, -4(%sp)                          ASM_LINE_SEP  \
00068        stw %r19, -32(%sp)                        ASM_LINE_SEP  \
00069        /* Done setting up frame, continue... */  ASM_LINE_SEP  \
00070        SINGLE_THREAD_P                                  ASM_LINE_SEP  \
00071        cmpib,<>,n 0,%ret0,L(pseudo_cancel)              ASM_LINE_SEP  \
00072 L(unthreaded):                                          ASM_LINE_SEP  \
00073        /* Save r19 */                                   ASM_LINE_SEP  \
00074        SAVE_PIC(TREG)                                   ASM_LINE_SEP  \
00075        /* Do syscall, delay loads # */                  ASM_LINE_SEP  \
00076        ble  0x100(%sr2,%r0)                      ASM_LINE_SEP  \
00077        ldi SYS_ify (syscall_name), %r20 /* delay */     ASM_LINE_SEP  \
00078        ldi NO_ERROR,%r1                          ASM_LINE_SEP  \
00079        cmpb,>>=,n %r1,%ret0,L(pre_end)                  ASM_LINE_SEP  \
00080        /* Restore r19 from TREG */               ASM_LINE_SEP  \
00081        LOAD_PIC(TREG) /* delay */                ASM_LINE_SEP  \
00082        SYSCALL_ERROR_HANDLER                            ASM_LINE_SEP  \
00083        /* Use TREG for temp storage */                  ASM_LINE_SEP  \
00084        copy %ret0, TREG /* delay */                     ASM_LINE_SEP  \
00085        /* OPTIMIZE: Don't reload r19 */          ASM_LINE_SEP  \
00086        /* do a -1*syscall_ret0 */                ASM_LINE_SEP  \
00087        sub %r0, TREG, TREG                       ASM_LINE_SEP  \
00088        /* Store into errno location */                  ASM_LINE_SEP  \
00089        stw TREG, 0(%sr0,%ret0)                          ASM_LINE_SEP  \
00090        b L(pre_end)                              ASM_LINE_SEP  \
00091        /* return -1 as error */                  ASM_LINE_SEP  \
00092        ldi -1, %ret0 /* delay */                 ASM_LINE_SEP  \
00093 L(pseudo_cancel):                                ASM_LINE_SEP  \
00094        PUSHARGS_##args /* Save args */                  ASM_LINE_SEP  \
00095        /* Save r19 into TREG */                  ASM_LINE_SEP  \
00096        CENABLE /* FUNC CALL */                          ASM_LINE_SEP  \
00097        SAVE_PIC(TREG) /* delay */                ASM_LINE_SEP  \
00098        /* restore syscall args */                ASM_LINE_SEP  \
00099        POPARGS_##args                                   ASM_LINE_SEP  \
00100        /* save mask from cenable (use stub rp slot) */  ASM_LINE_SEP  \
00101        stw %ret0, -24(%sp)                       ASM_LINE_SEP  \
00102        /* ... SYSCALL ... */                            ASM_LINE_SEP  \
00103        ble 0x100(%sr2,%r0)                       ASM_LINE_SEP    \
00104        ldi SYS_ify (syscall_name), %r20 /* delay */     ASM_LINE_SEP  \
00105        /* ............... */                            ASM_LINE_SEP  \
00106        LOAD_PIC(TREG)                                   ASM_LINE_SEP  \
00107        /* pass mask as arg0 to cdisable */              ASM_LINE_SEP  \
00108        ldw -24(%sp), %r26                        ASM_LINE_SEP  \
00109        CDISABLE                                  ASM_LINE_SEP  \
00110        stw %ret0, -24(%sp) /* delay */                  ASM_LINE_SEP  \
00111        /* Restore syscall return */                     ASM_LINE_SEP  \
00112        ldw -24(%sp), %ret0                       ASM_LINE_SEP  \
00113        /* compare error */                       ASM_LINE_SEP  \
00114        ldi NO_ERROR,%r1                          ASM_LINE_SEP  \
00115        /* branch if no error */                  ASM_LINE_SEP  \
00116        cmpb,>>=,n %r1,%ret0,L(pre_end)                  ASM_LINE_SEP  \
00117        LOAD_PIC(TREG)       /* cond. nullify */         ASM_LINE_SEP  \
00118        copy %ret0, TREG /* save syscall return */       ASM_LINE_SEP  \
00119        SYSCALL_ERROR_HANDLER                            ASM_LINE_SEP  \
00120        /* make syscall res value positive */            ASM_LINE_SEP  \
00121        sub %r0, TREG, TREG  /* delay */          ASM_LINE_SEP  \
00122        /* No need to LOAD_PIC */                 ASM_LINE_SEP  \
00123        /* store into errno location */                  ASM_LINE_SEP  \
00124        stw TREG, 0(%sr0,%ret0)                          ASM_LINE_SEP  \
00125        /* return -1 */                                  ASM_LINE_SEP  \
00126        ldi -1, %ret0                             ASM_LINE_SEP  \
00127 L(pre_end):                                      ASM_LINE_SEP  \
00128        /* No need to LOAD_PIC */                 ASM_LINE_SEP  \
00129        /* Undo frame */                          ASM_LINE_SEP  \
00130        ldwm -64(%sp),TREG                        ASM_LINE_SEP  \
00131        /* Restore rp before exit */                     ASM_LINE_SEP  \
00132        ldw -20(%sp), %rp                         ASM_LINE_SEP
00133 
00134 /* Save arguments into our frame */
00135 # define PUSHARGS_0  /* nothing to do */
00136 # define PUSHARGS_1  PUSHARGS_0 stw %r26, -36(%sr0,%sp) ASM_LINE_SEP
00137 # define PUSHARGS_2  PUSHARGS_1 stw %r25, -40(%sr0,%sp) ASM_LINE_SEP
00138 # define PUSHARGS_3  PUSHARGS_2 stw %r24, -44(%sr0,%sp) ASM_LINE_SEP
00139 # define PUSHARGS_4  PUSHARGS_3 stw %r23, -48(%sr0,%sp) ASM_LINE_SEP
00140 # define PUSHARGS_5  PUSHARGS_4 stw %r22, -52(%sr0,%sp) ASM_LINE_SEP 
00141 # define PUSHARGS_6  PUSHARGS_5 stw %r21, -56(%sr0,%sp) ASM_LINE_SEP
00142 
00143 /* Bring them back from the stack */
00144 # define POPARGS_0   /* nothing to do */
00145 # define POPARGS_1   POPARGS_0 ldw -36(%sr0,%sp), %r26  ASM_LINE_SEP
00146 # define POPARGS_2   POPARGS_1 ldw -40(%sr0,%sp), %r25  ASM_LINE_SEP
00147 # define POPARGS_3   POPARGS_2 ldw -44(%sr0,%sp), %r24  ASM_LINE_SEP
00148 # define POPARGS_4   POPARGS_3 ldw -48(%sr0,%sp), %r23  ASM_LINE_SEP
00149 # define POPARGS_5   POPARGS_4 ldw -52(%sr0,%sp), %r22  ASM_LINE_SEP
00150 # define POPARGS_6   POPARGS_5 ldw -56(%sr0,%sp), %r21  ASM_LINE_SEP
00151 
00152 # ifdef IS_IN_libpthread
00153 #  ifdef PIC
00154 #   define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \
00155                      bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP
00156 #   define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \
00157                      bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP
00158 #  else
00159 #   define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \
00160                      bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP
00161 #   define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \
00162                      bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP
00163 #  endif
00164 # elif !defined NOT_IN_libc
00165 #  ifdef PIC
00166 #   define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \
00167                      bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP
00168 #   define CDISABLE  .import __libc_disable_asynccancel,code ASM_LINE_SEP \
00169                      bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP
00170 #  else
00171 #   define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \
00172                      bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP
00173 #   define CDISABLE  .import __libc_disable_asynccancel,code ASM_LINE_SEP \
00174                      bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP
00175 #  endif
00176 # elif defined IS_IN_librt
00177 #  ifdef PIC
00178 #   define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \
00179                      bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP
00180 #   define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \
00181                      bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP
00182 #  else
00183 #   define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \
00184                      bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP
00185 #   define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \
00186                      bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP
00187 #  endif
00188 # else
00189 #  error Unsupported library
00190 # endif
00191 
00192 # ifdef IS_IN_libpthread
00193 #  define __local_multiple_threads __pthread_multiple_threads
00194 # elif !defined NOT_IN_libc
00195 #  define __local_multiple_threads __libc_multiple_threads
00196 # elif IS_IN_librt
00197 #  define __local_multiple_threads __librt_multiple_threads
00198 # else
00199 #  error Unsupported library
00200 # endif
00201 
00202 # ifndef __ASSEMBLER__
00203 #  define SINGLE_THREAD_P \
00204   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
00205                                header.multiple_threads) == 0, 1)
00206 # else
00207 /* Read the value of header.multiple_threads from the thread pointer */
00208 #  define SINGLE_THREAD_P                                             \
00209        mfctl %cr27, %ret0                               ASM_LINE_SEP  \
00210        ldw MULTIPLE_THREADS_THREAD_OFFSET(%sr0,%ret0),%ret0    ASM_LINE_SEP
00211 # endif
00212 #elif !defined __ASSEMBLER__
00213 
00214 /* This code should never be used but we define it anyhow.  */
00215 # define SINGLE_THREAD_P (1)
00216 # define NO_CANCELLATION 1
00217 
00218 #endif
00219 /* !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt */
00220 
00221 #ifndef __ASSEMBLER__
00222 # define RTLD_SINGLE_THREAD_P \
00223   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
00224                                header.multiple_threads) == 0, 1)
00225 #endif
00226