Back to index

glibc  2.9
sysdep-cancel.h
Go to the documentation of this file.
00001 /* Copyright (C) 2003, 2004, 2005, 2006 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 #include <sys/asm.h>
00026 
00027 /* Gas will put the initial save of $gp into the CIE, because it appears to
00028    happen before any instructions.  So we use cfi_same_value instead of
00029    cfi_restore.  */
00030 
00031 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
00032 
00033 #ifdef __PIC__
00034 # undef PSEUDO
00035 # define PSEUDO(name, syscall_name, args)                            \
00036       .align 2;                                                             \
00037   L(pseudo_start):                                                   \
00038       cfi_startproc;                                                 \
00039       cfi_adjust_cfa_offset (STKSPACE);                                     \
00040       cfi_rel_offset (gp, STKOFF_GP);                                       \
00041   99: PTR_LA t9,__syscall_error;                                     \
00042       /* manual cpreturn */                                          \
00043       REG_L gp, STKOFF_GP(sp);                                              \
00044       cfi_same_value (gp);                                           \
00045       RESTORESTK;                                                    \
00046       jr t9;                                                         \
00047   .type __##syscall_name##_nocancel, @function;                             \
00048   .globl __##syscall_name##_nocancel;                                       \
00049   __##syscall_name##_nocancel:                                              \
00050     SAVESTK;                                                         \
00051     .cpsetup t9, STKOFF_GP, name;                                    \
00052     cfi_rel_offset (gp, STKOFF_GP);                                         \
00053     li v0, SYS_ify(syscall_name);                                    \
00054     syscall;                                                         \
00055     bne a3, zero, SYSCALL_ERROR_LABEL;                                             \
00056     /* manual cpreturn */                                            \
00057     REG_L gp, STKOFF_GP(sp);                                                \
00058     cfi_same_value (gp);                                             \
00059     RESTORESTK;                                                             \
00060     ret;                                                             \
00061   .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;          \
00062   ENTRY (name)                                                              \
00063     SAVESTK;                                                         \
00064     .cpsetup t9, STKOFF_GP, name;                                    \
00065     cfi_rel_offset (gp, STKOFF_GP);                                         \
00066     SINGLE_THREAD_P(v1);                                             \
00067     bne zero, v1, L(pseudo_cancel);                                         \
00068     .set noreorder;                                                  \
00069     li v0, SYS_ify(syscall_name);                                    \
00070     syscall;                                                         \
00071     .set reorder;                                                    \
00072     bne a3, zero, SYSCALL_ERROR_LABEL;                                             \
00073     /* manual cpreturn */                                            \
00074     REG_L gp, STKOFF_GP(sp);                                                \
00075     cfi_same_value (gp);                                             \
00076     RESTORESTK;                                                             \
00077     ret;                                                             \
00078   L(pseudo_cancel):                                                  \
00079     cfi_adjust_cfa_offset (STKSPACE);                                       \
00080     cfi_rel_offset (gp, STKOFF_GP);                                         \
00081     REG_S ra, STKOFF_RA(sp);                                                \
00082     cfi_rel_offset (ra, STKOFF_RA);                                         \
00083     PUSHARGS_##args;               /* save syscall args */                  \
00084     CENABLE;                                                         \
00085     REG_S v0, STKOFF_SVMSK(sp);           /* save mask */                          \
00086     POPARGS_##args;                /* restore syscall args */        \
00087     .set noreorder;                                                  \
00088     li v0, SYS_ify (syscall_name);                                   \
00089     syscall;                                                         \
00090     .set reorder;                                                    \
00091     REG_S v0, STKOFF_SC_V0(sp);           /* save syscall result */             \
00092     REG_S a3, STKOFF_SC_ERR(sp);   /* save syscall error flag */            \
00093     REG_L a0, STKOFF_SVMSK(sp);           /* pass mask as arg1 */                  \
00094     CDISABLE;                                                        \
00095     REG_L a3, STKOFF_SC_ERR(sp);   /* restore syscall error flag */      \
00096     REG_L ra, STKOFF_RA(sp);              /* restore return address */             \
00097     REG_L v0, STKOFF_SC_V0(sp);           /* restore syscall result */          \
00098     bne a3, zero, SYSCALL_ERROR_LABEL;                                      \
00099     /* manual cpreturn */                                            \
00100     REG_L gp, STKOFF_GP(sp);                                                \
00101     cfi_same_value (gp);                                             \
00102     RESTORESTK;                                                             \
00103   L(pseudo_end):
00104 
00105 
00106 # undef PSEUDO_END
00107 # define PSEUDO_END(sym) cfi_endproc; .end sym; .size sym,.-sym
00108 
00109 #endif
00110 
00111 # define PUSHARGS_0  /* nothing to do */
00112 # define PUSHARGS_1  PUSHARGS_0 REG_S a0, STKOFF_A0(sp); cfi_rel_offset (a0, STKOFF_A0);
00113 # define PUSHARGS_2  PUSHARGS_1 REG_S a1, STKOFF_A1(sp); cfi_rel_offset (a1, STKOFF_A1);
00114 # define PUSHARGS_3  PUSHARGS_2 REG_S a2, STKOFF_A2(sp); cfi_rel_offset (a2, STKOFF_A2);
00115 # define PUSHARGS_4  PUSHARGS_3 REG_S a3, STKOFF_A3(sp); cfi_rel_offset (a3, STKOFF_A3);
00116 # define PUSHARGS_5  PUSHARGS_4 REG_S a4, STKOFF_A4(sp); cfi_rel_offset (a3, STKOFF_A4);
00117 # define PUSHARGS_6  PUSHARGS_5 REG_S a5, STKOFF_A5(sp); cfi_rel_offset (a3, STKOFF_A5);
00118 
00119 # define POPARGS_0   /* nothing to do */
00120 # define POPARGS_1   POPARGS_0 REG_L a0, STKOFF_A0(sp);
00121 # define POPARGS_2   POPARGS_1 REG_L a1, STKOFF_A1(sp);
00122 # define POPARGS_3   POPARGS_2 REG_L a2, STKOFF_A2(sp);
00123 # define POPARGS_4   POPARGS_3 REG_L a3, STKOFF_A3(sp);
00124 # define POPARGS_5   POPARGS_4 REG_L a4, STKOFF_A4(sp);
00125 # define POPARGS_6   POPARGS_5 REG_L a5, STKOFF_A5(sp);
00126 
00127 /* Save an even number of slots.  Should be 0 if an even number of slots
00128    are used below, or SZREG if an odd number are used.  */
00129 # define STK_PAD     SZREG
00130 
00131 /* Place values that we are more likely to use later in this sequence, i.e.
00132    closer to the SP at function entry.  If you do that, the are more
00133    likely to already be in your d-cache.  */
00134 # define STKOFF_A5   (STK_PAD)
00135 # define STKOFF_A4   (STKOFF_A5 + SZREG)
00136 # define STKOFF_A3   (STKOFF_A4 + SZREG)
00137 # define STKOFF_A2   (STKOFF_A3 + SZREG)  /* MT and more args.  */
00138 # define STKOFF_A1   (STKOFF_A2 + SZREG)  /* MT and 2 args.  */
00139 # define STKOFF_A0   (STKOFF_A1 + SZREG)  /* MT and 1 arg.  */
00140 # define STKOFF_RA   (STKOFF_A0 + SZREG)  /* Used if MT.  */
00141 # define STKOFF_SC_V0       (STKOFF_RA + SZREG)  /* Used if MT.  */
00142 # define STKOFF_SC_ERR      (STKOFF_SC_V0 + SZREG)      /* Used if MT.  */
00143 # define STKOFF_SVMSK       (STKOFF_SC_ERR + SZREG)     /* Used if MT.  */
00144 # define STKOFF_GP   (STKOFF_SVMSK + SZREG)      /* Always used.  */
00145 
00146 # define STKSPACE    (STKOFF_GP + SZREG)
00147 # define SAVESTK     PTR_SUBU sp, STKSPACE; cfi_adjust_cfa_offset(STKSPACE)
00148 # define RESTORESTK  PTR_ADDU sp, STKSPACE; cfi_adjust_cfa_offset(-STKSPACE)
00149 
00150 # ifdef IS_IN_libpthread
00151 #  define CENABLE    PTR_LA t9, __pthread_enable_asynccancel; jalr t9
00152 #  define CDISABLE   PTR_LA t9, __pthread_disable_asynccancel; jalr t9
00153 # elif defined IS_IN_librt
00154 #  define CENABLE    PTR_LA t9, __librt_enable_asynccancel; jalr t9
00155 #  define CDISABLE   PTR_LA t9, __librt_disable_asynccancel; jalr t9
00156 # else
00157 #  define CENABLE    PTR_LA t9, __libc_enable_asynccancel; jalr t9
00158 #  define CDISABLE   PTR_LA t9, __libc_disable_asynccancel; jalr t9
00159 # endif
00160 
00161 # ifndef __ASSEMBLER__
00162 #  define SINGLE_THREAD_P                                      \
00163        __builtin_expect (THREAD_GETMEM (THREAD_SELF,                  \
00164                                     header.multiple_threads)   \
00165                        == 0, 1)
00166 # else
00167 #  define SINGLE_THREAD_P(reg)                                        \
00168        READ_THREAD_POINTER(reg);                               \
00169        lw reg, MULTIPLE_THREADS_OFFSET(reg)
00170 #endif
00171 
00172 #elif !defined __ASSEMBLER__
00173 
00174 # define SINGLE_THREAD_P 1
00175 # define NO_CANCELLATION 1
00176 
00177 #endif
00178 
00179 #ifndef __ASSEMBLER__
00180 # define RTLD_SINGLE_THREAD_P \
00181   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
00182                                header.multiple_threads) == 0, 1)
00183 #endif