summaryrefslogtreecommitdiff
path: root/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h
blob: 4e6dec7754ca333bb87a27069221d79b1ec341da (plain)
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, see
   <http://www.gnu.org/licenses/>.  */

#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: move a0, v0; 							      \
  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