1 /* Copyright (C) 2014-2015 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
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/>. */
21 # include <nptl/pthreadP.h>
24 #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
26 # if !IS_IN (librt) || !defined(PIC)
27 # define AC_STACK_SIZE 16 /* space for r15, async_cancel arg and 2 temp words */
28 # define AC_SET_GOT /* empty */
29 # define AC_RESTORE_GOT /* empty */
31 # define AC_STACK_SIZE 20 /* extra 4 bytes for r20 */
33 swi r20, r1, AC_STACK_SIZE-4; \
35 addik r20, r20, _GLOBAL_OFFSET_TABLE_+8;
36 # define AC_RESTORE_GOT \
37 lwi r20, r1, AC_STACK_SIZE-4;
41 # define PSEUDO(name, syscall_name, args) \
44 SINGLE_THREAD_P(r12); \
45 bnei r12, L(pseudo_cancel); \
46 .globl __##syscall_name##_nocancel; \
47 .type __##syscall_name##_nocancel,@function; \
48 __##syscall_name##_nocancel: \
49 DO_CALL (syscall_name, args); \
50 addik r4, r0, -4095; \
52 bgei r4, SYSCALL_ERROR_LABEL; \
55 .size __##syscall_name##_nocancel, .-__##syscall_name##_nocancel; \
57 addik r1, r1, -AC_STACK_SIZE; \
64 DO_CALL (syscall_name, args); \
71 addik r1, r1, AC_STACK_SIZE; \
72 addik r4, r0, -4095; \
74 bgei r4, SYSCALL_ERROR_LABEL; \
79 * Macros to save/restore syscall arguments across CENABLE
80 * The arguments are saved into the caller's stack (original r1 + 4)
84 # define DOCARGS_1 swi r5, r1, AC_STACK_SIZE + 4;
85 # define DOCARGS_2 swi r6, r1, AC_STACK_SIZE + 8; DOCARGS_1
86 # define DOCARGS_3 swi r7, r1, AC_STACK_SIZE + 12; DOCARGS_2
87 # define DOCARGS_4 swi r8, r1, AC_STACK_SIZE + 16; DOCARGS_3
88 # define DOCARGS_5 swi r9, r1, AC_STACK_SIZE + 20; DOCARGS_4
89 # define DOCARGS_6 swi r10, r1, AC_STACK_SIZE + 24; DOCARGS_5
92 # define UNDOCARGS_1 lwi r5, r1, AC_STACK_SIZE + 4;
93 # define UNDOCARGS_2 UNDOCARGS_1 lwi r6, r1, AC_STACK_SIZE + 8;
94 # define UNDOCARGS_3 UNDOCARGS_2 lwi r7, r1, AC_STACK_SIZE + 12;
95 # define UNDOCARGS_4 UNDOCARGS_3 lwi r8, r1, AC_STACK_SIZE + 16;
96 # define UNDOCARGS_5 UNDOCARGS_4 lwi r9, r1, AC_STACK_SIZE + 20;
97 # define UNDOCARGS_6 UNDOCARGS_5 lwi r10, r1, AC_STACK_SIZE + 24;
100 # define PSEUDO_JMP(sym) brlid r15, sym##@PLTPC; addk r0, r0, r0
102 # define PSEUDO_JMP(sym) brlid r15, sym; addk r0, r0, r0
105 # if IS_IN (libpthread)
106 # define CENABLE PSEUDO_JMP (__pthread_enable_asynccancel)
107 # define CDISABLE PSEUDO_JMP (__pthread_disable_asynccancel)
108 # define __local_multiple_threads __pthread_multiple_threads
110 # define CENABLE PSEUDO_JMP (__libc_enable_asynccancel)
111 # define CDISABLE PSEUDO_JMP (__libc_disable_asynccancel)
112 # define __local_multiple_threads __libc_multiple_threads
114 # define CENABLE PSEUDO_JMP (__librt_enable_asynccancel)
115 # define CDISABLE PSEUDO_JMP (__librt_disable_asynccancel)
117 # error Unsupported library
121 # if IS_IN (libpthread) || IS_IN (libc)
122 # ifndef __ASSEMBLER__
123 extern int __local_multiple_threads attribute_hidden
;
124 # define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
127 # define SINGLE_THREAD_P(reg) lwi reg, r0, __local_multiple_threads;
129 # define SINGLE_THREAD_P(reg) \
131 addik reg, reg, _GLOBAL_OFFSET_TABLE_+8; \
132 lwi reg, reg, __local_multiple_threads@GOT; \
137 # ifndef __ASSEMBLER__
138 # define SINGLE_THREAD_P \
139 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
140 header.multiple_threads) == 0, 1)
142 # define SINGLE_THREAD_P(reg) \
143 lwi reg, r0, MULTIPLE_THREADS_OFFSET(reg)
147 #elif !defined __ASSEMBLER__
149 # define SINGLE_THREAD_P (1)
150 # define NO_CANCELLATION (1)
154 #ifndef __ASSEMBLER__
155 # define RTLD_SINGLE_THREAD_P \
156 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
157 header.multiple_threads) == 0, 1)