Back to index

glibc  2.9
sysdep-cancel.h
Go to the documentation of this file.
00001 /* Copyright (C) 2003, 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 #ifndef __ASSEMBLER__
00021 # include <linuxthreads/internals.h>
00022 #endif
00023 
00024 #if !defined NOT_IN_libc || defined IS_IN_libpthread
00025 
00026 # undef PSEUDO
00027 # define PSEUDO(name, syscall_name, args)                      \
00028   .section ".text";                                            \
00029     PSEUDO_PROLOGUE;                                           \
00030   ENTRY (name);                                                       \
00031     SINGLE_THREAD_P;                                           \
00032     DOARGS_##args;                                             \
00033     bne .Lpseudo_cancel;                                       \
00034     mov ip, r7;                                                       \
00035     ldr r7, =SYS_ify (syscall_name);                                  \
00036     swi 0x0;                                                   \
00037     mov r7, ip;                                                       \
00038     UNDOARGS_##args;                                           \
00039     cmn r0, $4096;                                             \
00040     PSEUDO_RET;                                                       \
00041   .Lpseudo_cancel:                                             \
00042     DOCARGS_##args;  /* save syscall args etc. around CENABLE.  */    \
00043     CENABLE;                                                   \
00044     mov ip, r0;             /* put mask in safe place.  */                   \
00045     UNDOCARGS_##args;       /* restore syscall args.  */                     \
00046     ldr r7, =SYS_ify (syscall_name);                                  \
00047     swi 0x0;         /* do the call.  */                       \
00048     mov r7, r0;             /* save syscall return value.  */         \
00049     mov r0, ip;             /* get mask back.  */                            \
00050     CDISABLE;                                                  \
00051     mov r0, r7;             /* retrieve return value.  */                    \
00052     RESTORE_LR_##args;                                                \
00053     UNDOARGS_##args;                                           \
00054     cmn r0, $4096;
00055 
00056 /* DOARGS pushes four bytes on the stack for five arguments, eight bytes for
00057    six arguments, and nothing for fewer.  In order to preserve doubleword
00058    alignment, sometimes we must save an extra register.  */
00059 
00060 # define DOCARGS_0   stmfd sp!, {r7, lr}
00061 # define UNDOCARGS_0
00062 # define RESTORE_LR_0       ldmfd sp!, {r7, lr}
00063 
00064 # define DOCARGS_1   stmfd sp!, {r0, r1, r7, lr}
00065 # define UNDOCARGS_1 ldr r0, [sp], #8
00066 # define RESTORE_LR_1       RESTORE_LR_0
00067 
00068 # define DOCARGS_2   stmfd sp!, {r0, r1, r7, lr}
00069 # define UNDOCARGS_2 ldmfd sp!, {r0, r1}
00070 # define RESTORE_LR_2       RESTORE_LR_0
00071 
00072 # define DOCARGS_3   stmfd sp!, {r0, r1, r2, r3, r7, lr}
00073 # define UNDOCARGS_3 ldmfd sp!, {r0, r1, r2, r3}
00074 # define RESTORE_LR_3       RESTORE_LR_0
00075 
00076 # define DOCARGS_4   stmfd sp!, {r0, r1, r2, r3, r7, lr}
00077 # define UNDOCARGS_4 ldmfd sp!, {r0, r1, r2, r3}
00078 # define RESTORE_LR_4       RESTORE_LR_0
00079 
00080 # define DOCARGS_5   stmfd sp!, {r0, r1, r2, r3, r4, r7, lr}
00081 # define UNDOCARGS_5 ldmfd sp!, {r0, r1, r2, r3}
00082 # define RESTORE_LR_5       ldmfd sp!, {r4, r7, lr}
00083 
00084 # define DOCARGS_6   stmfd sp!, {r0, r1, r2, r3, r7, lr}
00085 # define UNDOCARGS_6 ldmfd sp!, {r0, r1, r2, r3}
00086 # define RESTORE_LR_6       RESTORE_LR_0
00087 
00088 # ifdef IS_IN_libpthread
00089 #  define CENABLE    bl PLTJMP(__pthread_enable_asynccancel)
00090 #  define CDISABLE   bl PLTJMP(__pthread_disable_asynccancel)
00091 #  define __local_multiple_threads __pthread_multiple_threads
00092 # else
00093 #  define CENABLE    bl PLTJMP(__libc_enable_asynccancel)
00094 #  define CDISABLE   bl PLTJMP(__libc_disable_asynccancel)
00095 #  define __local_multiple_threads __libc_multiple_threads
00096 # endif
00097 
00098 # ifndef __ASSEMBLER__
00099 extern int __local_multiple_threads attribute_hidden;
00100 #  define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
00101 # else
00102 #  define SINGLE_THREAD_P                                      \
00103   ldr ip, 1b;                                                  \
00104 2:                                                             \
00105   ldr ip, [pc, ip];                                            \
00106   teq ip, #0;
00107 #  define PSEUDO_PROLOGUE                                      \
00108   1:  .word __local_multiple_threads - 2f - 8;
00109 # endif
00110 
00111 #else
00112 
00113 /* For rtld, et cetera.  */
00114 # define SINGLE_THREAD_P 1
00115 
00116 #endif