1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Guido Guenther <agx@sigxcpu.org>, 2003.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <sysdep.h>
#ifndef __ASSEMBLER__
# include <linuxthreads/internals.h>
#endif
#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
#ifdef __PIC__
# undef PSEUDO
# define PSEUDO(name, syscall_name, args) \
.align 2; \
99: la t9,__syscall_error; \
jr t9; \
ENTRY (name) \
.set noreorder; \
.cpload t9; \
.set reorder; \
SINGLE_THREAD_P(t0); \
bne zero, t0, L(pseudo_cancel); \
.set noreorder; \
li v0, SYS_ify(syscall_name); \
syscall; \
.set reorder; \
bne a3, zero, SYSCALL_ERROR_LABEL; \
ret; \
L(pseudo_cancel): \
SAVESTK_##args; \
sw ra, 28(sp); \
sw gp, 32(sp); \
PUSHARGS_##args; /* save syscall args */ \
CENABLE; \
lw gp, 32(sp); \
sw v0, 44(sp); /* save mask */ \
POPARGS_##args; /* restore syscall args */ \
.set noreorder; \
li v0, SYS_ify (syscall_name); \
syscall; \
.set reorder; \
sw v0, 36(sp); /* save syscall result */ \
sw a3, 40(sp); /* save syscall error flag */ \
lw a0, 44(sp); /* pass mask as arg1 */ \
CDISABLE; \
lw gp, 32(sp); \
lw v0, 36(sp); /* restore syscall result */ \
lw a3, 40(sp); /* restore syscall error flag */ \
lw ra, 28(sp); /* restore return address */ \
RESTORESTK; \
bne a3, zero, SYSCALL_ERROR_LABEL; \
L(pseudo_end):
#endif
# define PUSHARGS_0 /* nothing to do */
# define PUSHARGS_1 PUSHARGS_0 sw a0, 0(sp);
# define PUSHARGS_2 PUSHARGS_1 sw a1, 4(sp);
# define PUSHARGS_3 PUSHARGS_2 sw a2, 8(sp);
# define PUSHARGS_4 PUSHARGS_3 sw a3, 12(sp);
# define PUSHARGS_5 PUSHARGS_4 /* handeld by SAVESTK_## */
# define PUSHARGS_6 PUSHARGS_5
# define PUSHARGS_7 PUSHARGS_6
# define POPARGS_0 /* nothing to do */
# define POPARGS_1 POPARGS_0 lw a0, 0(sp);
# define POPARGS_2 POPARGS_1 lw a1, 4(sp);
# define POPARGS_3 POPARGS_2 lw a2, 8(sp);
# define POPARGS_4 POPARGS_3 lw a3, 12(sp);
# define POPARGS_5 POPARGS_4 /* args already in new stackframe */
# define POPARGS_6 POPARGS_5
# define POPARGS_7 POPARGS_6
# define STKSPACE 48
# define SAVESTK_0 subu sp, STKSPACE
# define SAVESTK_1 SAVESTK_0
# define SAVESTK_2 SAVESTK_1
# define SAVESTK_3 SAVESTK_2
# define SAVESTK_4 SAVESTK_3
# define SAVESTK_5 lw t0, 16(sp); \
subu sp, STKSPACE; \
sw t0, 16(sp)
# define SAVESTK_6 lw t0, 16(sp); \
lw t1, 20(sp); \
subu sp, STKSPACE; \
sw t0, 16(sp); \
sw t1, 20(sp)
# define SAVESTK_7 lw t0, 16(sp); \
lw t1, 20(sp); \
lw t2, 24(sp); \
subu sp, STKSPACE; \
sw t0, 16(sp); \
sw t1, 20(sp); \
sw t2, 24(sp)
# define RESTORESTK addu sp, STKSPACE
# ifdef IS_IN_libpthread
# define CENABLE la t9, __pthread_enable_asynccancel; jalr t9;
# define CDISABLE la t9, __pthread_disable_asynccancel; jalr t9;
# define __local_multiple_threads __pthread_multiple_threads
# elif defined IS_IN_librt
# define CENABLE la t9, __librt_enable_asynccancel; jalr t9;
# define CDISABLE la t9, __librt_disable_asynccancel; jalr t9;
# define __local_multiple_threads __librt_multiple_threads
# else
# define CENABLE la t9, __libc_enable_asynccancel; jalr t9;
# define CDISABLE la t9, __libc_disable_asynccancel; jalr t9;
# define __local_multiple_threads __libc_multiple_threads
# endif
# ifndef __ASSEMBLER__
extern int __local_multiple_threads attribute_hidden;
# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
# else
# define SINGLE_THREAD_P(reg) lw reg, __local_multiple_threads
#endif
#elif !defined __ASSEMBLER__
/* This code should never be used but we define it anyhow. */
# define SINGLE_THREAD_P (1)
#endif
|