Back to index

glibc  2.9
sysdep-cancel.h
Go to the documentation of this file.
00001 /* system call stubs with cancellation handling.  Linux/MIPS version.
00002    Copyright (C) 2003, 2004 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Chris Demetriou of Broadcom Corporation,
00005    based on work by Guido Guenther <agx@sigxcpu.org>.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 #include <sysdep.h>
00023 #ifndef __ASSEMBLER__
00024 # include <linuxthreads/internals.h>
00025 #endif
00026 #include <sys/asm.h>
00027 
00028 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
00029 
00030 #ifdef __PIC__
00031 # undef PSEUDO
00032 # define PSEUDO(name, syscall_name, args)                            \
00033   .align 2;                                                          \
00034   99:                                                                \
00035   PTR_LA t9,__syscall_error;                                                \
00036   /* manual cpreturn.  */                                            \
00037   REG_L gp, STKOFF_GP(sp);                                           \
00038   RESTORESTK ;                                                              \
00039   jr t9;                                                             \
00040   ENTRY (name)                                                              \
00041     SAVESTK ;                                                        \
00042     .cpsetup t9, STKOFF_GP, name ;                                   \
00043     .set reorder;                                                    \
00044     SINGLE_THREAD_P(t0);                                             \
00045     bne zero, t0, L(pseudo_cancel);                                         \
00046     .set noreorder;                                                  \
00047     li v0, SYS_ify(syscall_name);                                    \
00048     syscall;                                                         \
00049     .set reorder;                                                    \
00050     bne a3, zero, SYSCALL_ERROR_LABEL;                                             \
00051     /* manual cpreturn.  */                                          \
00052     REG_L gp, STKOFF_GP(sp);                                                \
00053     RESTORESTK ;                                                     \
00054     ret;                                                             \
00055   L(pseudo_cancel):                                                  \
00056     REG_S ra, STKOFF_RA(sp);                                                \
00057     PUSHARGS_##args;               /* save syscall args */                  \
00058     CENABLE;                                                         \
00059     REG_S v0, STKOFF_SVMSK(sp);           /* save mask */                          \
00060     POPARGS_##args;                /* restore syscall args */        \
00061     .set noreorder;                                                  \
00062     li v0, SYS_ify (syscall_name);                                   \
00063     syscall;                                                         \
00064     .set reorder;                                                    \
00065     REG_S v0, STKOFF_SC_V0(sp);           /* save syscall result */             \
00066     REG_S a3, STKOFF_SC_ERR(sp);   /* save syscall error flag */            \
00067     REG_L a0, STKOFF_SVMSK(sp);           /* pass mask as arg1 */                  \
00068     CDISABLE;                                                        \
00069     REG_L a3, STKOFF_SC_ERR(sp);   /* restore syscall error flag */      \
00070     REG_L ra, STKOFF_RA(sp);              /* restore return address */             \
00071     REG_L v0, STKOFF_SC_V0(sp);           /* restore syscall result */          \
00072     bne a3, zero, SYSCALL_ERROR_LABEL;                                      \
00073     /* manual cpreturn.  */                                          \
00074     REG_L gp, STKOFF_GP(sp);                                                \
00075     RESTORESTK ;                                                     \
00076   L(pseudo_end):
00077 #endif
00078 
00079 # define PUSHARGS_0  /* nothing to do */
00080 # define PUSHARGS_1  PUSHARGS_0 REG_S a0, STKOFF_A0(sp);
00081 # define PUSHARGS_2  PUSHARGS_1 REG_S a1, STKOFF_A1(sp);
00082 # define PUSHARGS_3  PUSHARGS_2 REG_S a2, STKOFF_A2(sp);
00083 # define PUSHARGS_4  PUSHARGS_3 REG_S a3, STKOFF_A3(sp);
00084 # define PUSHARGS_5  PUSHARGS_4 REG_S a4, STKOFF_A4(sp);
00085 # define PUSHARGS_6  PUSHARGS_5 REG_S a5, STKOFF_A5(sp);
00086 
00087 # define POPARGS_0   /* nothing to do */
00088 # define POPARGS_1   POPARGS_0 REG_L a0, STKOFF_A0(sp);
00089 # define POPARGS_2   POPARGS_1 REG_L a1, STKOFF_A1(sp);
00090 # define POPARGS_3   POPARGS_2 REG_L a2, STKOFF_A2(sp);
00091 # define POPARGS_4   POPARGS_3 REG_L a3, STKOFF_A3(sp);
00092 # define POPARGS_5   POPARGS_4 REG_L a4, STKOFF_A4(sp);
00093 # define POPARGS_6   POPARGS_5 REG_L a5, STKOFF_A5(sp);
00094 
00095 /* Save an even number of slots.  Should be 0 if an even number of slots
00096    are used below, or SZREG if an odd number are used.  */
00097 # define STK_PAD     SZREG
00098 
00099 /* Place values that we are more likely to use later in this sequence, i.e.
00100    closer to the SP at function entry.  If you do that, the are more
00101    likely to already be in your d-cache.  */
00102 # define STKOFF_A5   (STK_PAD)
00103 # define STKOFF_A4   (STKOFF_A5 + SZREG)
00104 # define STKOFF_A3   (STKOFF_A4 + SZREG)
00105 # define STKOFF_A2   (STKOFF_A3 + SZREG)  /* MT and more args.  */
00106 # define STKOFF_A1   (STKOFF_A2 + SZREG)  /* MT and 2 args.  */
00107 # define STKOFF_A0   (STKOFF_A1 + SZREG)  /* MT and 1 arg.  */
00108 # define STKOFF_RA   (STKOFF_A0 + SZREG)  /* Used if MT.  */
00109 # define STKOFF_SC_V0       (STKOFF_RA + SZREG)  /* Used if MT.  */
00110 # define STKOFF_SC_ERR      (STKOFF_SC_V0 + SZREG)      /* Used if MT.  */
00111 # define STKOFF_SVMSK       (STKOFF_SC_ERR + SZREG)     /* Used if MT.  */
00112 # define STKOFF_GP   (STKOFF_SVMSK + SZREG)      /* Always used.  */
00113 
00114 # define STKSPACE    (STKOFF_GP + SZREG)
00115 # define SAVESTK     PTR_SUBU sp, STKSPACE
00116 # define RESTORESTK  PTR_ADDU sp, STKSPACE
00117 
00118 # ifdef IS_IN_libpthread
00119 #  define CENABLE    PTR_LA t9, __pthread_enable_asynccancel; jalr t9;
00120 #  define CDISABLE   PTR_LA t9, __pthread_disable_asynccancel; jalr t9;
00121 #  define __local_multiple_threads __pthread_multiple_threads
00122 # elif defined IS_IN_librt
00123 #  define CENABLE    PTR_LA t9, __librt_enable_asynccancel; jalr t9;
00124 #  define CDISABLE   PTR_LA t9, __librt_disable_asynccancel; jalr t9;
00125 #  define __local_multiple_threads __librt_multiple_threads
00126 # else
00127 #  define CENABLE    PTR_LA t9, __libc_enable_asynccancel; jalr t9;
00128 #  define CDISABLE   PTR_LA t9, __libc_disable_asynccancel; jalr t9;
00129 #  define __local_multiple_threads __libc_multiple_threads
00130 # endif
00131 
00132 # ifndef __ASSEMBLER__
00133 extern int __local_multiple_threads attribute_hidden;
00134 #  define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
00135 # else
00136 #  define SINGLE_THREAD_P(reg) lw reg, __local_multiple_threads
00137 #endif
00138 
00139 #elif !defined __ASSEMBLER__
00140 
00141 /* This code should never be used but we define it anyhow.  */
00142 # define SINGLE_THREAD_P (1)
00143 
00144 #endif