Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / unix / sysv / linux / aarch64 / sysdep-cancel.h
blob36e8e395c37d78f190d7c6ecea0aa78f3b1dee86
1 /* Copyright (C) 2003-2015 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 #include <sysdep.h>
20 #include <tls.h>
21 #ifndef __ASSEMBLER__
22 # include <nptl/pthreadP.h>
23 #endif
25 #if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt)
27 # undef PSEUDO
28 # define PSEUDO(name, syscall_name, args) \
29 .section ".text"; \
30 ENTRY (__##syscall_name##_nocancel); \
31 .Lpseudo_nocancel: \
32 DO_CALL (syscall_name, args); \
33 .Lpseudo_finish: \
34 cmn x0, 4095; \
35 b.cs .Lsyscall_error; \
36 .subsection 2; \
37 .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
38 ENTRY (name); \
39 SINGLE_THREAD_P(16); \
40 cbz w16, .Lpseudo_nocancel; \
41 /* Setup common stack frame no matter the number of args. \
42 Also save the first arg, since it's basically free. */ \
43 stp x30, x0, [sp, -64]!; \
44 cfi_adjust_cfa_offset (64); \
45 cfi_rel_offset (x30, 0); \
46 DOCARGS_##args; /* save syscall args around CENABLE. */ \
47 CENABLE; \
48 mov x16, x0; /* save mask around syscall. */ \
49 UNDOCARGS_##args; /* restore syscall args. */ \
50 DO_CALL (syscall_name, args); \
51 str x0, [sp, 8]; /* save result around CDISABLE. */ \
52 mov x0, x16; /* restore mask for CDISABLE. */ \
53 CDISABLE; \
54 /* Break down the stack frame, restoring result at once. */ \
55 ldp x30, x0, [sp], 64; \
56 cfi_adjust_cfa_offset (-64); \
57 cfi_restore (x30); \
58 b .Lpseudo_finish; \
59 cfi_endproc; \
60 .size name, .-name; \
61 .previous
63 # undef PSEUDO_END
64 # define PSEUDO_END(name) \
65 SYSCALL_ERROR_HANDLER; \
66 cfi_endproc
68 # define DOCARGS_0
69 # define DOCARGS_1
70 # define DOCARGS_2 str x1, [sp, 16]
71 # define DOCARGS_3 stp x1, x2, [sp, 16]
72 # define DOCARGS_4 DOCARGS_3; str x3, [sp, 32]
73 # define DOCARGS_5 DOCARGS_3; stp x3, x4, [sp, 32]
74 # define DOCARGS_6 DOCARGS_5; str x5, [sp, 48]
76 # define UNDOCARGS_0
77 # define UNDOCARGS_1 ldr x0, [sp, 8]
78 # define UNDOCARGS_2 ldp x0, x1, [sp, 8]
79 # define UNDOCARGS_3 UNDOCARGS_1; ldp x1, x2, [sp, 16]
80 # define UNDOCARGS_4 UNDOCARGS_2; ldp x2, x3, [sp, 24]
81 # define UNDOCARGS_5 UNDOCARGS_3; ldp x3, x4, [sp, 32]
82 # define UNDOCARGS_6 UNDOCARGS_4; ldp x4, x5, [sp, 40]
84 # if IS_IN (libpthread)
85 # define CENABLE bl __pthread_enable_asynccancel
86 # define CDISABLE bl __pthread_disable_asynccancel
87 # define __local_multiple_threads __pthread_multiple_threads
88 # elif IS_IN (libc)
89 # define CENABLE bl __libc_enable_asynccancel
90 # define CDISABLE bl __libc_disable_asynccancel
91 # define __local_multiple_threads __libc_multiple_threads
92 # elif IS_IN (librt)
93 # define CENABLE bl __librt_enable_asynccancel
94 # define CDISABLE bl __librt_disable_asynccancel
95 # else
96 # error Unsupported library
97 # endif
99 # if IS_IN (libpthread) || IS_IN (libc)
100 # ifndef __ASSEMBLER__
101 extern int __local_multiple_threads attribute_hidden;
102 # define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
103 # else
104 # define SINGLE_THREAD_P(R) \
105 adrp x##R, __local_multiple_threads; \
106 ldr w##R, [x##R, :lo12:__local_multiple_threads]
107 # endif
108 # else
109 /* There is no __local_multiple_threads for librt, so use the TCB. */
110 # ifndef __ASSEMBLER__
111 # define SINGLE_THREAD_P \
112 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
113 header.multiple_threads) == 0, 1)
114 # else
115 # define SINGLE_THREAD_P(R) \
116 mrs x##R, tpidr_el0; \
117 sub x##R, x##R, PTHREAD_SIZEOF; \
118 ldr w##R, [x##R, PTHREAD_MULTIPLE_THREADS_OFFSET]
119 # endif
120 # endif
122 #elif !defined __ASSEMBLER__
124 /* For rtld, et cetera. */
125 # define SINGLE_THREAD_P 1
126 # define NO_CANCELLATION 1
128 #endif
130 #ifndef __ASSEMBLER__
131 # define RTLD_SINGLE_THREAD_P \
132 __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
133 header.multiple_threads) == 0, 1)
134 #endif