Back to index

glibc  2.9
sysdep-cancel.h
Go to the documentation of this file.
00001 /* Copyright (C) 2003, 2004, 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 # ifdef __PIC__
00029 #  define PSEUDO_CPLOAD .cpload t9;
00030 #  define PSEUDO_ERRJMP la t9, __syscall_error; jr t9;
00031 #  define PSEUDO_SAVEGP sw gp, 32(sp); cfi_rel_offset (gp, 32);
00032 #  define PSEUDO_LOADGP lw gp, 32(sp);
00033 # else
00034 #  define PSEUDO_CPLOAD
00035 #  define PSEUDO_ERRJMP j __syscall_error;
00036 #  define PSEUDO_SAVEGP
00037 #  define PSEUDO_LOADGP
00038 # endif
00039 
00040 # undef PSEUDO
00041 # define PSEUDO(name, syscall_name, args)                            \
00042       .align 2;                                                             \
00043   L(pseudo_start):                                                   \
00044       cfi_startproc;                                                 \
00045   99: PSEUDO_ERRJMP                                                  \
00046   .type __##syscall_name##_nocancel, @function;                             \
00047   .globl __##syscall_name##_nocancel;                                       \
00048   __##syscall_name##_nocancel:                                              \
00049     .set noreorder;                                                  \
00050     PSEUDO_CPLOAD                                                    \
00051     li v0, SYS_ify(syscall_name);                                    \
00052     syscall;                                                         \
00053     .set reorder;                                                    \
00054     bne a3, zero, 99b;                                                             \
00055     ret;                                                             \
00056   .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;          \
00057   ENTRY (name)                                                              \
00058     .set noreorder;                                                  \
00059     PSEUDO_CPLOAD                                                    \
00060     .set reorder;                                                    \
00061     SINGLE_THREAD_P(v1);                                             \
00062     bne zero, v1, L(pseudo_cancel);                                         \
00063     .set noreorder;                                                  \
00064     li v0, SYS_ify(syscall_name);                                    \
00065     syscall;                                                         \
00066     .set reorder;                                                    \
00067     bne a3, zero, 99b;                                                             \
00068     ret;                                                             \
00069   L(pseudo_cancel):                                                  \
00070     SAVESTK_##args;                                                   \
00071     sw ra, 28(sp);                                                   \
00072     cfi_rel_offset (ra, 28);                                                \
00073     PSEUDO_SAVEGP                                                    \
00074     PUSHARGS_##args;               /* save syscall args */                  \
00075     CENABLE;                                                         \
00076     PSEUDO_LOADGP                                                    \
00077     sw v0, 44(sp);                 /* save mask */                          \
00078     POPARGS_##args;                /* restore syscall args */        \
00079     .set noreorder;                                                  \
00080     li v0, SYS_ify (syscall_name);                                   \
00081     syscall;                                                         \
00082     .set reorder;                                                    \
00083     sw v0, 36(sp);                 /* save syscall result */             \
00084     sw a3, 40(sp);                 /* save syscall error flag */            \
00085     lw a0, 44(sp);                 /* pass mask as arg1 */                  \
00086     CDISABLE;                                                        \
00087     PSEUDO_LOADGP                                                    \
00088     lw v0, 36(sp);                 /* restore syscall result */          \
00089     lw a3, 40(sp);                 /* restore syscall error flag */      \
00090     lw ra, 28(sp);                 /* restore return address */             \
00091     .set noreorder;                                                  \
00092     bne a3, zero, 99b;                                                      \
00093      RESTORESTK;                                                      \
00094   L(pseudo_end):                                                     \
00095     .set reorder;
00096 
00097 # undef PSEUDO_END
00098 # define PSEUDO_END(sym) cfi_endproc; .end sym; .size sym,.-sym
00099 
00100 # define PUSHARGS_0  /* nothing to do */
00101 # define PUSHARGS_1  PUSHARGS_0 sw a0, 0(sp); cfi_rel_offset (a0, 0);
00102 # define PUSHARGS_2  PUSHARGS_1 sw a1, 4(sp); cfi_rel_offset (a1, 4);
00103 # define PUSHARGS_3  PUSHARGS_2 sw a2, 8(sp); cfi_rel_offset (a2, 8);
00104 # define PUSHARGS_4  PUSHARGS_3 sw a3, 12(sp); cfi_rel_offset (a3, 12);
00105 # define PUSHARGS_5  PUSHARGS_4 /* handled by SAVESTK_## */
00106 # define PUSHARGS_6  PUSHARGS_5
00107 # define PUSHARGS_7  PUSHARGS_6
00108 
00109 # define POPARGS_0   /* nothing to do */
00110 # define POPARGS_1   POPARGS_0 lw a0, 0(sp);
00111 # define POPARGS_2   POPARGS_1 lw a1, 4(sp);
00112 # define POPARGS_3   POPARGS_2 lw a2, 8(sp);
00113 # define POPARGS_4   POPARGS_3 lw a3, 12(sp);
00114 # define POPARGS_5   POPARGS_4 /* args already in new stackframe */
00115 # define POPARGS_6   POPARGS_5
00116 # define POPARGS_7   POPARGS_6
00117 
00118 
00119 # define STKSPACE    48
00120 # define SAVESTK_0   subu sp, STKSPACE; cfi_adjust_cfa_offset(STKSPACE)
00121 # define SAVESTK_1      SAVESTK_0
00122 # define SAVESTK_2      SAVESTK_1
00123 # define SAVESTK_3      SAVESTK_2
00124 # define SAVESTK_4      SAVESTK_3
00125 # define SAVESTK_5      lw t0, 16(sp);           \
00126                      SAVESTK_0;           \
00127                      sw t0, 16(sp)
00128 
00129 # define SAVESTK_6      lw t0, 16(sp);           \
00130                      lw t1, 20(sp);              \
00131                      SAVESTK_0;           \
00132                      sw t0, 16(sp);              \
00133                      sw t1, 20(sp)
00134 
00135 # define SAVESTK_7      lw t0, 16(sp);           \
00136                      lw t1, 20(sp);              \
00137                      lw t2, 24(sp);              \
00138                      SAVESTK_0;           \
00139                      sw t0, 16(sp);              \
00140                      sw t1, 20(sp);              \
00141                      sw t2, 24(sp)
00142 
00143 # define RESTORESTK  addu sp, STKSPACE; cfi_adjust_cfa_offset(-STKSPACE)
00144 
00145 
00146 # ifdef __PIC__
00147 /* We use jalr rather than jal.  This means that the assembler will not
00148    automatically restore $gp (in case libc has multiple GOTs) so we must
00149    do it manually - which we have to do anyway since we don't use .cprestore.
00150    It also shuts up the assembler warning about not using .cprestore.  */
00151 #  define PSEUDO_JMP(sym) la t9, sym; jalr t9;
00152 # else
00153 #  define PSEUDO_JMP(sym) jal sym;
00154 # endif
00155 
00156 # ifdef IS_IN_libpthread
00157 #  define CENABLE    PSEUDO_JMP (__pthread_enable_asynccancel)
00158 #  define CDISABLE   PSEUDO_JMP (__pthread_disable_asynccancel)
00159 # elif defined IS_IN_librt
00160 #  define CENABLE    PSEUDO_JMP (__librt_enable_asynccancel)
00161 #  define CDISABLE   PSEUDO_JMP (__librt_disable_asynccancel)
00162 # else
00163 #  define CENABLE    PSEUDO_JMP (__libc_enable_asynccancel)
00164 #  define CDISABLE   PSEUDO_JMP (__libc_disable_asynccancel)
00165 # endif
00166 
00167 # ifndef __ASSEMBLER__
00168 #  define SINGLE_THREAD_P                                      \
00169        __builtin_expect (THREAD_GETMEM (THREAD_SELF,                  \
00170                                     header.multiple_threads)   \
00171                        == 0, 1)
00172 # else
00173 #  define SINGLE_THREAD_P(reg)                                        \
00174        READ_THREAD_POINTER(reg);                               \
00175        lw reg, MULTIPLE_THREADS_OFFSET(reg)
00176 #endif
00177 
00178 #elif !defined __ASSEMBLER__
00179 
00180 # define SINGLE_THREAD_P 1
00181 # define NO_CANCELLATION 1
00182 
00183 #endif
00184 
00185 #ifndef __ASSEMBLER__
00186 # define RTLD_SINGLE_THREAD_P \
00187   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
00188                                header.multiple_threads) == 0, 1)
00189 #endif