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 <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 /* NOTE: We do mark syscalls with unwind annotations, for the benefit of
00028    cancellation; but they're really only accurate at the point of the
00029    syscall.  The ARM unwind directives are not rich enough without adding
00030    a custom personality function.  */
00031 
00032 # undef PSEUDO
00033 # define PSEUDO(name, syscall_name, args)                      \
00034   .section ".text";                                            \
00035     PSEUDO_PROLOGUE;                                           \
00036   .type __##syscall_name##_nocancel,%function;                        \
00037   .globl __##syscall_name##_nocancel;                                 \
00038   __##syscall_name##_nocancel:                                        \
00039     DO_CALL (syscall_name, args);                              \
00040     PSEUDO_RET;                                                       \
00041   .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;    \
00042   ENTRY (name);                                                       \
00043     SINGLE_THREAD_P;                                           \
00044     DOARGS_##args;                                             \
00045     bne .Lpseudo_cancel;                                       \
00046     DO_CALL (syscall_name, 0);                                        \
00047     UNDOARGS_##args;                                           \
00048     cmn r0, $4096;                                             \
00049     PSEUDO_RET;                                                       \
00050   .Lpseudo_cancel:                                             \
00051     .fnstart;                                                  \
00052     DOCARGS_##args;  /* save syscall args etc. around CENABLE.  */    \
00053     CENABLE;                                                   \
00054     mov ip, r0;             /* put mask in safe place.  */                   \
00055     UNDOCARGS_##args;       /* restore syscall args.  */                     \
00056     ldr r7, =SYS_ify (syscall_name);                                  \
00057     swi 0x0;         /* do the call.  */                       \
00058     .fnend;          /* Past here we can't easily unwind.  */  \
00059     mov r7, r0;             /* save syscall return value.  */         \
00060     mov r0, ip;             /* get mask back.  */                            \
00061     CDISABLE;                                                  \
00062     mov r0, r7;             /* retrieve return value.  */                    \
00063     RESTORE_LR_##args;                                                \
00064     UNDOARGS_##args;                                           \
00065     cmn r0, $4096;
00066 
00067 /* DOARGS pushes four bytes on the stack for five arguments, eight bytes for
00068    six arguments, and nothing for fewer.  In order to preserve doubleword
00069    alignment, sometimes we must save an extra register.  */
00070 
00071 # define RESTART_UNWIND .fnend; .fnstart; .save {r7, lr}
00072 
00073 # define DOCARGS_0   stmfd sp!, {r7, lr}; .save {r7, lr}
00074 # define UNDOCARGS_0
00075 # define RESTORE_LR_0       ldmfd sp!, {r7, lr};
00076 
00077 # define DOCARGS_1   stmfd sp!, {r0, r1, r7, lr}; .save {r7, lr}; .pad #8
00078 # define UNDOCARGS_1 ldr r0, [sp], #8; RESTART_UNWIND
00079 # define RESTORE_LR_1       RESTORE_LR_0
00080 
00081 # define DOCARGS_2   stmfd sp!, {r0, r1, r7, lr}; .save {r7, lr}; .pad #8
00082 # define UNDOCARGS_2 ldmfd sp!, {r0, r1}; RESTART_UNWIND
00083 # define RESTORE_LR_2       RESTORE_LR_0
00084 
00085 # define DOCARGS_3   stmfd sp!, {r0, r1, r2, r3, r7, lr}; .save {r7, lr}; .pad #16
00086 # define UNDOCARGS_3 ldmfd sp!, {r0, r1, r2, r3}; RESTART_UNWIND
00087 # define RESTORE_LR_3       RESTORE_LR_0
00088 
00089 # define DOCARGS_4   stmfd sp!, {r0, r1, r2, r3, r7, lr}; .save {r7, lr}; .pad #16
00090 # define UNDOCARGS_4 ldmfd sp!, {r0, r1, r2, r3}; RESTART_UNWIND
00091 # define RESTORE_LR_4       RESTORE_LR_0
00092 
00093 # define DOCARGS_5   .save {r4}; stmfd sp!, {r0, r1, r2, r3, r4, r7, lr}; .save {r7, lr}; .pad #20
00094 # define UNDOCARGS_5 ldmfd sp!, {r0, r1, r2, r3}; .fnend; .fnstart; .save {r4}; .save {r7, lr}; .pad #4
00095 # define RESTORE_LR_5       ldmfd sp!, {r4, r7, lr}
00096 
00097 # define DOCARGS_6   .save {r4, r5}; stmfd sp!, {r0, r1, r2, r3, r7, lr}; .save {r7, lr}; .pad #16
00098 # define UNDOCARGS_6 ldmfd sp!, {r0, r1, r2, r3}; .fnend; .fnstart; .save {r4, r5}; .save {r7, lr}
00099 # define RESTORE_LR_6       RESTORE_LR_0
00100 
00101 # ifdef IS_IN_libpthread
00102 #  define CENABLE    bl PLTJMP(__pthread_enable_asynccancel)
00103 #  define CDISABLE   bl PLTJMP(__pthread_disable_asynccancel)
00104 #  define __local_multiple_threads __pthread_multiple_threads
00105 # elif !defined NOT_IN_libc
00106 #  define CENABLE    bl PLTJMP(__libc_enable_asynccancel)
00107 #  define CDISABLE   bl PLTJMP(__libc_disable_asynccancel)
00108 #  define __local_multiple_threads __libc_multiple_threads
00109 # elif defined IS_IN_librt
00110 #  define CENABLE    bl PLTJMP(__librt_enable_asynccancel)
00111 #  define CDISABLE   bl PLTJMP(__librt_disable_asynccancel)
00112 # else
00113 #  error Unsupported library
00114 # endif
00115 
00116 # if defined IS_IN_libpthread || !defined NOT_IN_libc
00117 #  ifndef __ASSEMBLER__
00118 extern int __local_multiple_threads attribute_hidden;
00119 #   define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
00120 #  else
00121 #   define SINGLE_THREAD_P                                     \
00122   ldr ip, 1b;                                                  \
00123 2:                                                             \
00124   ldr ip, [pc, ip];                                            \
00125   teq ip, #0;
00126 #   define PSEUDO_PROLOGUE                                     \
00127   1:  .word __local_multiple_threads - 2f - 8;
00128 #  endif
00129 # else
00130 /*  There is no __local_multiple_threads for librt, so use the TCB.  */
00131 #  ifndef __ASSEMBLER__
00132 #   define SINGLE_THREAD_P                                     \
00133   __builtin_expect (THREAD_GETMEM (THREAD_SELF,                       \
00134                                header.multiple_threads) == 0, 1)
00135 #  else
00136 #   define PSEUDO_PROLOGUE
00137 #   define SINGLE_THREAD_P                                     \
00138   stmfd       sp!, {r0, lr};                                                 \
00139   bl   __aeabi_read_tp;                                        \
00140   ldr  ip, [r0, #MULTIPLE_THREADS_OFFSET];                            \
00141   ldmfd       sp!, {r0, lr};                                                 \
00142   teq  ip, #0
00143 #   define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P
00144 #  endif
00145 # endif
00146 
00147 #elif !defined __ASSEMBLER__
00148 
00149 /* For rtld, et cetera.  */
00150 # define SINGLE_THREAD_P 1
00151 # define NO_CANCELLATION 1
00152 
00153 #endif
00154 
00155 #ifndef __ASSEMBLER__
00156 # define RTLD_SINGLE_THREAD_P \
00157   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
00158                                header.multiple_threads) == 0, 1)
00159 #endif