Back to index

glibc  2.9
sysdep-cancel.h
Go to the documentation of this file.
00001 /* Copyright (C) 2003, 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 <tls.h>
00021 #ifndef __ASSEMBLER__
00022 # include <nptl/pthreadP.h>
00023 #endif
00024 
00025 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
00026 
00027 # ifdef PROF
00028 #  define PSEUDO_PROF                            \
00029        .set noat;                         \
00030        lda    AT, _mcount;                \
00031        jsr    AT, (AT), _mcount;          \
00032        .set at
00033 # else
00034 #  define PSEUDO_PROF
00035 # endif
00036 
00037 /* ??? Assumes that nothing comes between PSEUDO and PSEUDO_END
00038    besides "ret".  */
00039 
00040 # undef PSEUDO
00041 # define PSEUDO(name, syscall_name, args)               \
00042        .globl name;                                     \
00043        .align 4;                                        \
00044        .type name, @function;                                  \
00045        .usepv name, std;                                \
00046        cfi_startproc;                                          \
00047 __LABEL(name)                                           \
00048        ldgp   gp, 0(pv);                                \
00049        PSEUDO_PROF;                                     \
00050        PSEUDO_PREPARE_ARGS                              \
00051        SINGLE_THREAD_P(t0);                             \
00052        bne    t0, $pseudo_cancel;                       \
00053        lda    v0, SYS_ify(syscall_name);                \
00054        call_pal PAL_callsys;                                   \
00055        bne    a3, SYSCALL_ERROR_LABEL;                  \
00056 __LABEL($pseudo_ret)                                    \
00057        .subsection 2;                                          \
00058        cfi_startproc;                                          \
00059 __LABEL($pseudo_cancel)                                        \
00060        subq   sp, 64, sp;                               \
00061        cfi_def_cfa_offset(64);                                 \
00062        stq    ra, 0(sp);                                \
00063        cfi_offset(ra, -64);                             \
00064        SAVE_ARGS_##args;                                \
00065        CENABLE;                                         \
00066        LOAD_ARGS_##args;                                \
00067        /* Save the CENABLE return value in RA.  That register  \
00068           is preserved across syscall and the real return      \
00069           address is saved on the stack.  */                   \
00070        mov    v0, ra;                                          \
00071        lda    v0, SYS_ify(syscall_name);                \
00072        call_pal PAL_callsys;                                   \
00073        stq    v0, 8(sp);                                \
00074        mov    ra, a0;                                          \
00075        bne    a3, $multi_error;                         \
00076        CDISABLE;                                        \
00077        ldq    ra, 0(sp);                                \
00078        ldq    v0, 8(sp);                                \
00079        addq   sp, 64, sp;                               \
00080        cfi_remember_state;                              \
00081        cfi_restore(ra);                                 \
00082        cfi_def_cfa_offset(0);                                  \
00083        ret;                                             \
00084        cfi_restore_state;                               \
00085 __LABEL($multi_error)                                          \
00086        CDISABLE;                                        \
00087        ldq    ra, 0(sp);                                \
00088        ldq    v0, 8(sp);                                \
00089        addq   sp, 64, sp;                               \
00090        cfi_restore(ra);                                 \
00091        cfi_def_cfa_offset(0);                                  \
00092 __LABEL($syscall_error)                                        \
00093        SYSCALL_ERROR_HANDLER;                                  \
00094        cfi_endproc;                                     \
00095        .previous
00096 
00097 # undef PSEUDO_END
00098 # define PSEUDO_END(sym)                                \
00099        cfi_endproc;                                     \
00100        .subsection 2;                                          \
00101        .size sym, .-sym
00102 
00103 # define SAVE_ARGS_0 /* Nothing.  */
00104 # define SAVE_ARGS_1 SAVE_ARGS_0; stq a0, 8(sp)
00105 # define SAVE_ARGS_2 SAVE_ARGS_1; stq a1, 16(sp)
00106 # define SAVE_ARGS_3 SAVE_ARGS_2; stq a2, 24(sp)
00107 # define SAVE_ARGS_4 SAVE_ARGS_3; stq a3, 32(sp)
00108 # define SAVE_ARGS_5 SAVE_ARGS_4; stq a4, 40(sp)
00109 # define SAVE_ARGS_6 SAVE_ARGS_5; stq a5, 48(sp)
00110 
00111 # define LOAD_ARGS_0 /* Nothing.  */
00112 # define LOAD_ARGS_1 LOAD_ARGS_0; ldq a0, 8(sp)
00113 # define LOAD_ARGS_2 LOAD_ARGS_1; ldq a1, 16(sp)
00114 # define LOAD_ARGS_3 LOAD_ARGS_2; ldq a2, 24(sp)
00115 # define LOAD_ARGS_4 LOAD_ARGS_3; ldq a3, 32(sp)
00116 # define LOAD_ARGS_5 LOAD_ARGS_4; ldq a4, 40(sp)
00117 # define LOAD_ARGS_6 LOAD_ARGS_5; ldq a5, 48(sp)
00118 
00119 # ifdef IS_IN_libpthread
00120 #  define __local_enable_asynccancel      __pthread_enable_asynccancel
00121 #  define __local_disable_asynccancel     __pthread_disable_asynccancel
00122 #  define __local_multiple_threads __pthread_multiple_threads
00123 # elif !defined NOT_IN_libc
00124 #  define __local_enable_asynccancel      __libc_enable_asynccancel
00125 #  define __local_disable_asynccancel     __libc_disable_asynccancel
00126 #  define __local_multiple_threads __libc_multiple_threads
00127 # elif defined IS_IN_librt
00128 #  define __local_enable_asynccancel      __librt_enable_asynccancel
00129 #  define __local_disable_asynccancel     __librt_disable_asynccancel
00130 # else
00131 #  error Unsupported library
00132 # endif
00133 
00134 # ifdef PIC
00135 #  define CENABLE    bsr ra, __local_enable_asynccancel !samegp
00136 #  define CDISABLE   bsr ra, __local_disable_asynccancel !samegp
00137 # else
00138 #  define CENABLE    jsr ra, __local_enable_asynccancel; ldgp ra, 0(gp)
00139 #  define CDISABLE   jsr ra, __local_disable_asynccancel; ldgp ra, 0(gp)
00140 # endif
00141 
00142 # if defined IS_IN_libpthread || !defined NOT_IN_libc
00143 #  ifndef __ASSEMBLER__
00144 extern int __local_multiple_threads attribute_hidden;
00145 #   define SINGLE_THREAD_P \
00146        __builtin_expect (__local_multiple_threads == 0, 1)
00147 #  elif defined(PIC)
00148 #   define SINGLE_THREAD_P(reg)  ldl reg, __local_multiple_threads(gp) !gprel
00149 #  else
00150 #   define SINGLE_THREAD_P(reg)                                \
00151        ldah   reg, __local_multiple_threads(gp) !gprelhigh;    \
00152        ldl    reg, __local_multiple_threads(reg) !gprellow
00153 #  endif
00154 # else
00155 #  ifndef __ASSEMBLER__
00156 #   define SINGLE_THREAD_P \
00157        __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
00158                                header.multiple_threads) == 0, 1)
00159 #  else
00160 #   define SINGLE_THREAD_P(reg)                                \
00161        call_pal PAL_rduniq;                             \
00162        ldl reg, MULTIPLE_THREADS_OFFSET($0)
00163 #  endif
00164 # endif
00165 
00166 #else
00167 
00168 # define SINGLE_THREAD_P (1)
00169 # define NO_CANCELLATION 1
00170 
00171 #endif
00172 
00173 #ifndef __ASSEMBLER__
00174 # define RTLD_SINGLE_THREAD_P \
00175   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
00176                                header.multiple_threads) == 0, 1)
00177 #endif