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 # undef PSEUDO
00028 # define PSEUDO(name, syscall_name, args)                      \
00029   .section ".text";                                            \
00030     PSEUDO_PROLOGUE;                                           \
00031   .type __##syscall_name##_nocancel,%function;                        \
00032   .globl __##syscall_name##_nocancel;                                 \
00033   __##syscall_name##_nocancel:                                        \
00034     DO_CALL (syscall_name, args);                              \
00035     PSEUDO_RET;                                                       \
00036   .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;    \
00037   ENTRY (name);                                                       \
00038     SINGLE_THREAD_P;                                           \
00039     DOARGS_##args;                                             \
00040     bne .Lpseudo_cancel;                                       \
00041     DO_CALL (syscall_name, 0);                                        \
00042     UNDOARGS_##args;                                           \
00043     cmn r0, $4096;                                             \
00044     PSEUDO_RET;                                                       \
00045   .Lpseudo_cancel:                                             \
00046     DOCARGS_##args;  /* save syscall args etc. around CENABLE.  */    \
00047     CENABLE;                                                   \
00048     mov ip, r0;             /* put mask in safe place.  */                   \
00049     UNDOCARGS_##args;       /* restore syscall args.  */                     \
00050     swi SYS_ify (syscall_name);    /* do the call.  */                \
00051     str r0, [sp, $-4]!; /* save syscall return value.  */             \
00052     mov r0, ip;             /* get mask back.  */                            \
00053     CDISABLE;                                                  \
00054     ldmfd sp!, {r0, lr}; /* retrieve return value and address.  */    \
00055     UNDOARGS_##args;                                           \
00056     cmn r0, $4096;
00057 
00058 # define DOCARGS_0   str lr, [sp, #-4]!;
00059 # define UNDOCARGS_0
00060 
00061 # define DOCARGS_1   stmfd sp!, {r0, lr};
00062 # define UNDOCARGS_1 ldr r0, [sp], #4;
00063 
00064 # define DOCARGS_2   stmfd sp!, {r0, r1, lr};
00065 # define UNDOCARGS_2 ldmfd sp!, {r0, r1};
00066 
00067 # define DOCARGS_3   stmfd sp!, {r0, r1, r2, lr};
00068 # define UNDOCARGS_3 ldmfd sp!, {r0, r1, r2};
00069 
00070 # define DOCARGS_4   stmfd sp!, {r0, r1, r2, r3, lr};
00071 # define UNDOCARGS_4 ldmfd sp!, {r0, r1, r2, r3};
00072 
00073 # define DOCARGS_5   DOCARGS_4
00074 # define UNDOCARGS_5 UNDOCARGS_4
00075 
00076 # define DOCARGS_6   DOCARGS_5
00077 # define UNDOCARGS_6 UNDOCARGS_5
00078 
00079 # ifdef IS_IN_libpthread
00080 #  define CENABLE    bl PLTJMP(__pthread_enable_asynccancel)
00081 #  define CDISABLE   bl PLTJMP(__pthread_disable_asynccancel)
00082 #  define __local_multiple_threads __pthread_multiple_threads
00083 # elif !defined NOT_IN_libc
00084 #  define CENABLE    bl PLTJMP(__libc_enable_asynccancel)
00085 #  define CDISABLE   bl PLTJMP(__libc_disable_asynccancel)
00086 #  define __local_multiple_threads __libc_multiple_threads
00087 # elif defined IS_IN_librt
00088 #  define CENABLE    bl PLTJMP(__librt_enable_asynccancel)
00089 #  define CDISABLE   bl PLTJMP(__librt_disable_asynccancel)
00090 # else
00091 #  error Unsupported library
00092 # endif
00093 
00094 # if defined IS_IN_libpthread || !defined NOT_IN_libc
00095 #  ifndef __ASSEMBLER__
00096 extern int __local_multiple_threads attribute_hidden;
00097 #   define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
00098 #  else
00099 #   define SINGLE_THREAD_P                                     \
00100   ldr ip, 1b;                                                  \
00101 2:                                                             \
00102   ldr ip, [pc, ip];                                            \
00103   teq ip, #0;
00104 #   define PSEUDO_PROLOGUE                                     \
00105   1:  .word __local_multiple_threads - 2f - 8;
00106 #  endif
00107 # else
00108 /*  There is no __local_multiple_threads for librt, so use the TCB.  */
00109 #  ifndef __ASSEMBLER__
00110 #   define SINGLE_THREAD_P                                     \
00111   __builtin_expect (THREAD_GETMEM (THREAD_SELF,                       \
00112                                header.multiple_threads) == 0, 1)
00113 #  else
00114 #   define PSEUDO_PROLOGUE
00115 #   define SINGLE_THREAD_P                                     \
00116   stmfd       sp!, {r0, lr};                                                 \
00117   bl   __aeabi_read_tp;                                        \
00118   ldr  ip, [r0, #MULTIPLE_THREADS_OFFSET];                            \
00119   ldmfd       sp!, {r0, lr};                                                 \
00120   teq  ip, #0
00121 #   define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P
00122 #  endif
00123 # endif
00124 
00125 #elif !defined __ASSEMBLER__
00126 
00127 /* For rtld, et cetera.  */
00128 # define SINGLE_THREAD_P 1
00129 # define NO_CANCELLATION 1
00130 
00131 #endif
00132 
00133 #ifndef __ASSEMBLER__
00134 # define RTLD_SINGLE_THREAD_P \
00135   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
00136                                header.multiple_threads) == 0, 1)
00137 #endif