MIPS: Consolidate nptl/ subdirectories under linux/...
[platform/upstream/glibc.git] / sysdeps / unix / sysv / linux / mips / mips64 / sysdep-cancel.h
1 /* Copyright (C) 2003-2014 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library.  If not, see
16    <http://www.gnu.org/licenses/>.  */
17
18 #include <sysdep.h>
19 #include <sysdeps/generic/sysdep.h>
20 #include <tls.h>
21 #ifndef __ASSEMBLER__
22 # include <nptl/pthreadP.h>
23 #endif
24 #include <sys/asm.h>
25
26 /* Gas will put the initial save of $gp into the CIE, because it appears to
27    happen before any instructions.  So we use cfi_same_value instead of
28    cfi_restore.  */
29
30 #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
31
32 #ifdef __PIC__
33 # undef PSEUDO
34 # define PSEUDO(name, syscall_name, args)                                     \
35       .align 2;                                                               \
36   L(pseudo_start):                                                            \
37       cfi_startproc;                                                          \
38       cfi_adjust_cfa_offset (STKSPACE);                                       \
39       cfi_rel_offset (gp, STKOFF_GP);                                         \
40   99: PTR_LA t9,__syscall_error;                                              \
41       /* manual cpreturn */                                                   \
42       REG_L gp, STKOFF_GP(sp);                                                \
43       cfi_same_value (gp);                                                    \
44       RESTORESTK;                                                             \
45       jr t9;                                                                  \
46   .type __##syscall_name##_nocancel, @function;                               \
47   .globl __##syscall_name##_nocancel;                                         \
48   __##syscall_name##_nocancel:                                                \
49     SAVESTK;                                                                  \
50     .cpsetup t9, STKOFF_GP, __##syscall_name##_nocancel;                      \
51     cfi_rel_offset (gp, STKOFF_GP);                                           \
52     li v0, SYS_ify(syscall_name);                                             \
53     syscall;                                                                  \
54     bne a3, zero, SYSCALL_ERROR_LABEL;                                        \
55     /* manual cpreturn */                                                     \
56     REG_L gp, STKOFF_GP(sp);                                                  \
57     cfi_same_value (gp);                                                      \
58     RESTORESTK;                                                               \
59     ret;                                                                      \
60     cfi_endproc;                                                              \
61   .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;            \
62   ENTRY (name)                                                                \
63     SAVESTK;                                                                  \
64     .cpsetup t9, STKOFF_GP, name;                                             \
65     cfi_rel_offset (gp, STKOFF_GP);                                           \
66     SINGLE_THREAD_P(v1);                                                      \
67     bne zero, v1, L(pseudo_cancel);                                           \
68     .set noreorder;                                                           \
69     li v0, SYS_ify(syscall_name);                                             \
70     syscall;                                                                  \
71     .set reorder;                                                             \
72     bne a3, zero, SYSCALL_ERROR_LABEL;                                        \
73     /* manual cpreturn */                                                     \
74     REG_L gp, STKOFF_GP(sp);                                                  \
75     cfi_same_value (gp);                                                      \
76     RESTORESTK;                                                               \
77     ret;                                                                      \
78   L(pseudo_cancel):                                                           \
79     cfi_adjust_cfa_offset (STKSPACE);                                         \
80     cfi_rel_offset (gp, STKOFF_GP);                                           \
81     REG_S ra, STKOFF_RA(sp);                                                  \
82     cfi_rel_offset (ra, STKOFF_RA);                                           \
83     PUSHARGS_##args;                    /* save syscall args */               \
84     CENABLE;                                                                  \
85     REG_S v0, STKOFF_SVMSK(sp);         /* save mask */                       \
86     POPARGS_##args;                     /* restore syscall args */            \
87     .set noreorder;                                                           \
88     li v0, SYS_ify (syscall_name);                                            \
89     syscall;                                                                  \
90     .set reorder;                                                             \
91     REG_S v0, STKOFF_SC_V0(sp);         /* save syscall result */             \
92     REG_S a3, STKOFF_SC_ERR(sp);        /* save syscall error flag */         \
93     REG_L a0, STKOFF_SVMSK(sp);         /* pass mask as arg1 */               \
94     CDISABLE;                                                                 \
95     REG_L a3, STKOFF_SC_ERR(sp);        /* restore syscall error flag */      \
96     REG_L ra, STKOFF_RA(sp);            /* restore return address */          \
97     REG_L v0, STKOFF_SC_V0(sp);         /* restore syscall result */          \
98     bne a3, zero, SYSCALL_ERROR_LABEL;                                        \
99     /* manual cpreturn */                                                     \
100     REG_L gp, STKOFF_GP(sp);                                                  \
101     cfi_same_value (gp);                                                      \
102     RESTORESTK;                                                               \
103   L(pseudo_end):
104 #else
105 # undef PSEUDO
106 # define PSEUDO(name, syscall_name, args)                                     \
107       .align 2;                                                               \
108   L(pseudo_start):                                                            \
109       cfi_startproc;                                                          \
110       cfi_adjust_cfa_offset (STKSPACE);                                       \
111   99: RESTORESTK;                                                             \
112       j __syscall_error;                                                      \
113   .type __##syscall_name##_nocancel, @function;                               \
114   .globl __##syscall_name##_nocancel;                                         \
115   __##syscall_name##_nocancel:                                                \
116     SAVESTK;                                                                  \
117     li v0, SYS_ify(syscall_name);                                             \
118     syscall;                                                                  \
119     bne a3, zero, SYSCALL_ERROR_LABEL;                                        \
120     RESTORESTK;                                                               \
121     ret;                                                                      \
122     cfi_endproc;                                                              \
123   .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;            \
124   ENTRY (name)                                                                \
125     SAVESTK;                                                                  \
126     SINGLE_THREAD_P(v1);                                                      \
127     bne zero, v1, L(pseudo_cancel);                                           \
128     .set noreorder;                                                           \
129     li v0, SYS_ify(syscall_name);                                             \
130     syscall;                                                                  \
131     .set reorder;                                                             \
132     bne a3, zero, SYSCALL_ERROR_LABEL;                                        \
133     RESTORESTK;                                                               \
134     ret;                                                                      \
135   L(pseudo_cancel):                                                           \
136     cfi_adjust_cfa_offset (STKSPACE);                                         \
137     REG_S ra, STKOFF_RA(sp);                                                  \
138     cfi_rel_offset (ra, STKOFF_RA);                                           \
139     PUSHARGS_##args;                    /* save syscall args */               \
140     CENABLE;                                                                  \
141     REG_S v0, STKOFF_SVMSK(sp);         /* save mask */                       \
142     POPARGS_##args;                     /* restore syscall args */            \
143     .set noreorder;                                                           \
144     li v0, SYS_ify (syscall_name);                                            \
145     syscall;                                                                  \
146     .set reorder;                                                             \
147     REG_S v0, STKOFF_SC_V0(sp);         /* save syscall result */             \
148     REG_S a3, STKOFF_SC_ERR(sp);        /* save syscall error flag */         \
149     REG_L a0, STKOFF_SVMSK(sp);         /* pass mask as arg1 */               \
150     CDISABLE;                                                                 \
151     REG_L a3, STKOFF_SC_ERR(sp);        /* restore syscall error flag */      \
152     REG_L ra, STKOFF_RA(sp);            /* restore return address */          \
153     REG_L v0, STKOFF_SC_V0(sp);         /* restore syscall result */          \
154     bne a3, zero, SYSCALL_ERROR_LABEL;                                        \
155     RESTORESTK;                                                               \
156   L(pseudo_end):
157 #endif
158
159 # undef PSEUDO_END
160 # define PSEUDO_END(sym) cfi_endproc; .end sym; .size sym,.-sym
161
162 # define PUSHARGS_0     /* nothing to do */
163 # define PUSHARGS_1     PUSHARGS_0 REG_S a0, STKOFF_A0(sp); cfi_rel_offset (a0, STKOFF_A0);
164 # define PUSHARGS_2     PUSHARGS_1 REG_S a1, STKOFF_A1(sp); cfi_rel_offset (a1, STKOFF_A1);
165 # define PUSHARGS_3     PUSHARGS_2 REG_S a2, STKOFF_A2(sp); cfi_rel_offset (a2, STKOFF_A2);
166 # define PUSHARGS_4     PUSHARGS_3 REG_S a3, STKOFF_A3(sp); cfi_rel_offset (a3, STKOFF_A3);
167 # define PUSHARGS_5     PUSHARGS_4 REG_S a4, STKOFF_A4(sp); cfi_rel_offset (a3, STKOFF_A4);
168 # define PUSHARGS_6     PUSHARGS_5 REG_S a5, STKOFF_A5(sp); cfi_rel_offset (a3, STKOFF_A5);
169
170 # define POPARGS_0      /* nothing to do */
171 # define POPARGS_1      POPARGS_0 REG_L a0, STKOFF_A0(sp);
172 # define POPARGS_2      POPARGS_1 REG_L a1, STKOFF_A1(sp);
173 # define POPARGS_3      POPARGS_2 REG_L a2, STKOFF_A2(sp);
174 # define POPARGS_4      POPARGS_3 REG_L a3, STKOFF_A3(sp);
175 # define POPARGS_5      POPARGS_4 REG_L a4, STKOFF_A4(sp);
176 # define POPARGS_6      POPARGS_5 REG_L a5, STKOFF_A5(sp);
177
178 /* Save an even number of slots.  Should be 0 if an even number of slots
179    are used below, or SZREG if an odd number are used.  */
180 # ifdef __PIC__
181 #  define STK_PAD       SZREG
182 # else
183 #  define STK_PAD       0
184 # endif
185
186 /* Place values that we are more likely to use later in this sequence, i.e.
187    closer to the SP at function entry.  If you do that, the are more
188    likely to already be in your d-cache.  */
189 # define STKOFF_A5      (STK_PAD)
190 # define STKOFF_A4      (STKOFF_A5 + SZREG)
191 # define STKOFF_A3      (STKOFF_A4 + SZREG)
192 # define STKOFF_A2      (STKOFF_A3 + SZREG)     /* MT and more args.  */
193 # define STKOFF_A1      (STKOFF_A2 + SZREG)     /* MT and 2 args.  */
194 # define STKOFF_A0      (STKOFF_A1 + SZREG)     /* MT and 1 arg.  */
195 # define STKOFF_RA      (STKOFF_A0 + SZREG)     /* Used if MT.  */
196 # define STKOFF_SC_V0   (STKOFF_RA + SZREG)     /* Used if MT.  */
197 # define STKOFF_SC_ERR  (STKOFF_SC_V0 + SZREG)  /* Used if MT.  */
198 # define STKOFF_SVMSK   (STKOFF_SC_ERR + SZREG) /* Used if MT.  */
199
200 # ifdef __PIC__
201 #  define STKOFF_GP     (STKOFF_SVMSK + SZREG)  /* Always used.  */
202 #  define STKSPACE      (STKOFF_GP + SZREG)
203 # else
204 #  define STKSPACE      (STKOFF_SVMSK + SZREG)
205 # endif
206
207 # define SAVESTK        PTR_SUBU sp, STKSPACE; cfi_adjust_cfa_offset(STKSPACE)
208 # define RESTORESTK     PTR_ADDU sp, STKSPACE; cfi_adjust_cfa_offset(-STKSPACE)
209
210 # ifdef __PIC__
211 #  define PSEUDO_JMP(sym) PTR_LA t9, sym; jalr t9
212 # else
213 #  define PSEUDO_JMP(sym) jal sym
214 # endif
215
216 # ifdef IS_IN_libpthread
217 #  define CENABLE       PSEUDO_JMP (__pthread_enable_asynccancel)
218 #  define CDISABLE      PSEUDO_JMP (__pthread_disable_asynccancel)
219 # elif defined IS_IN_librt
220 #  define CENABLE       PSEUDO_JMP (__librt_enable_asynccancel)
221 #  define CDISABLE      PSEUDO_JMP (__librt_disable_asynccancel)
222 # else
223 #  define CENABLE       PSEUDO_JMP (__libc_enable_asynccancel)
224 #  define CDISABLE      PSEUDO_JMP (__libc_disable_asynccancel)
225 # endif
226
227 # ifndef __ASSEMBLER__
228 #  define SINGLE_THREAD_P                                               \
229         __builtin_expect (THREAD_GETMEM (THREAD_SELF,                   \
230                                          header.multiple_threads)       \
231                           == 0, 1)
232 # else
233 #  define SINGLE_THREAD_P(reg)                                          \
234         READ_THREAD_POINTER(reg);                                       \
235         lw reg, MULTIPLE_THREADS_OFFSET(reg)
236 #endif
237
238 #elif !defined __ASSEMBLER__
239
240 # define SINGLE_THREAD_P 1
241 # define NO_CANCELLATION 1
242
243 #endif
244
245 #ifndef __ASSEMBLER__
246 # define RTLD_SINGLE_THREAD_P \
247   __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
248                                    header.multiple_threads) == 0, 1)
249 #endif