1 /* Copyright (C) 1991-2022 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    <https://www.gnu.org/licenses/>.  */
17 
18 #include <sysdeps/generic/sysdep.h>
19 #include <single-thread.h>
20 #include <sys/syscall.h>
21 #define	HAVE_SYSCALLS
22 
23 /* Note that using a `PASTE' macro loses.  */
24 #define	SYSCALL__(name, args)	PSEUDO (__##name, name, args)
25 #define	SYSCALL(name, args)	PSEUDO (name, name, args)
26 
27 #define __SYSCALL_CONCAT_X(a,b)     a##b
28 #define __SYSCALL_CONCAT(a,b)       __SYSCALL_CONCAT_X (a, b)
29 
30 
31 #define __INTERNAL_SYSCALL0(name) \
32   INTERNAL_SYSCALL (name, 0)
33 #define __INTERNAL_SYSCALL1(name, a1) \
34   INTERNAL_SYSCALL (name, 1, a1)
35 #define __INTERNAL_SYSCALL2(name, a1, a2) \
36   INTERNAL_SYSCALL (name, 2, a1, a2)
37 #define __INTERNAL_SYSCALL3(name, a1, a2, a3) \
38   INTERNAL_SYSCALL (name, 3, a1, a2, a3)
39 #define __INTERNAL_SYSCALL4(name, a1, a2, a3, a4) \
40   INTERNAL_SYSCALL (name, 4, a1, a2, a3, a4)
41 #define __INTERNAL_SYSCALL5(name, a1, a2, a3, a4, a5) \
42   INTERNAL_SYSCALL (name, 5, a1, a2, a3, a4, a5)
43 #define __INTERNAL_SYSCALL6(name, a1, a2, a3, a4, a5, a6) \
44   INTERNAL_SYSCALL (name, 6, a1, a2, a3, a4, a5, a6)
45 #define __INTERNAL_SYSCALL7(name, a1, a2, a3, a4, a5, a6, a7) \
46   INTERNAL_SYSCALL (name, 7, a1, a2, a3, a4, a5, a6, a7)
47 
48 #define __INTERNAL_SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n
49 #define __INTERNAL_SYSCALL_NARGS(...) \
50   __INTERNAL_SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,)
51 #define __INTERNAL_SYSCALL_DISP(b,...) \
52   __SYSCALL_CONCAT (b,__INTERNAL_SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
53 
54 /* Issue a syscall defined by syscall number plus any other argument required.
55    It is similar to INTERNAL_SYSCALL macro, but without the need to pass the
56    expected argument number as second parameter.  */
57 #define INTERNAL_SYSCALL_CALL(...) \
58   __INTERNAL_SYSCALL_DISP (__INTERNAL_SYSCALL, __VA_ARGS__)
59 
60 #define __INTERNAL_SYSCALL_NCS0(name) \
61   INTERNAL_SYSCALL_NCS (name, 0)
62 #define __INTERNAL_SYSCALL_NCS1(name, a1) \
63   INTERNAL_SYSCALL_NCS (name, 1, a1)
64 #define __INTERNAL_SYSCALL_NCS2(name, a1, a2) \
65   INTERNAL_SYSCALL_NCS (name, 2, a1, a2)
66 #define __INTERNAL_SYSCALL_NCS3(name, a1, a2, a3) \
67   INTERNAL_SYSCALL_NCS (name, 3, a1, a2, a3)
68 #define __INTERNAL_SYSCALL_NCS4(name, a1, a2, a3, a4) \
69   INTERNAL_SYSCALL_NCS (name, 4, a1, a2, a3, a4)
70 #define __INTERNAL_SYSCALL_NCS5(name, a1, a2, a3, a4, a5) \
71   INTERNAL_SYSCALL_NCS (name, 5, a1, a2, a3, a4, a5)
72 #define __INTERNAL_SYSCALL_NCS6(name, a1, a2, a3, a4, a5, a6) \
73   INTERNAL_SYSCALL_NCS (name, 6, a1, a2, a3, a4, a5, a6)
74 #define __INTERNAL_SYSCALL_NCS7(name, a1, a2, a3, a4, a5, a6, a7) \
75   INTERNAL_SYSCALL_NCS (name, 7, a1, a2, a3, a4, a5, a6, a7)
76 
77 #define INTERNAL_SYSCALL_NCS_CALL(...) \
78   __INTERNAL_SYSCALL_DISP (__INTERNAL_SYSCALL_NCS, __VA_ARGS__)
79 
80 #define __INLINE_SYSCALL0(name) \
81   INLINE_SYSCALL (name, 0)
82 #define __INLINE_SYSCALL1(name, a1) \
83   INLINE_SYSCALL (name, 1, a1)
84 #define __INLINE_SYSCALL2(name, a1, a2) \
85   INLINE_SYSCALL (name, 2, a1, a2)
86 #define __INLINE_SYSCALL3(name, a1, a2, a3) \
87   INLINE_SYSCALL (name, 3, a1, a2, a3)
88 #define __INLINE_SYSCALL4(name, a1, a2, a3, a4) \
89   INLINE_SYSCALL (name, 4, a1, a2, a3, a4)
90 #define __INLINE_SYSCALL5(name, a1, a2, a3, a4, a5) \
91   INLINE_SYSCALL (name, 5, a1, a2, a3, a4, a5)
92 #define __INLINE_SYSCALL6(name, a1, a2, a3, a4, a5, a6) \
93   INLINE_SYSCALL (name, 6, a1, a2, a3, a4, a5, a6)
94 #define __INLINE_SYSCALL7(name, a1, a2, a3, a4, a5, a6, a7) \
95   INLINE_SYSCALL (name, 7, a1, a2, a3, a4, a5, a6, a7)
96 
97 #define __INLINE_SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n
98 #define __INLINE_SYSCALL_NARGS(...) \
99   __INLINE_SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,)
100 #define __INLINE_SYSCALL_DISP(b,...) \
101   __SYSCALL_CONCAT (b,__INLINE_SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
102 
103 /* Issue a syscall defined by syscall number plus any other argument
104    required.  Any error will be handled using arch defined macros and errno
105    will be set accordingly.
106    It is similar to INLINE_SYSCALL macro, but without the need to pass the
107    expected argument number as second parameter.  */
108 #define INLINE_SYSCALL_CALL(...) \
109   __INLINE_SYSCALL_DISP (__INLINE_SYSCALL, __VA_ARGS__)
110 
111 #if IS_IN (rtld)
112 /* All cancellation points are compiled out in the dynamic loader.  */
113 # define NO_SYSCALL_CANCEL_CHECKING 1
114 #else
115 # define NO_SYSCALL_CANCEL_CHECKING SINGLE_THREAD_P
116 #endif
117 
118 #define SYSCALL_CANCEL(...) \
119   ({									     \
120     long int sc_ret;							     \
121     if (NO_SYSCALL_CANCEL_CHECKING)					     \
122       sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); 			     \
123     else								     \
124       {									     \
125 	int sc_cancel_oldtype = LIBC_CANCEL_ASYNC ();			     \
126 	sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__);			     \
127         LIBC_CANCEL_RESET (sc_cancel_oldtype);				     \
128       }									     \
129     sc_ret;								     \
130   })
131 
132 /* Issue a syscall defined by syscall number plus any other argument
133    required.  Any error will be returned unmodified (including errno).  */
134 #define INTERNAL_SYSCALL_CANCEL(...) \
135   ({									     \
136     long int sc_ret;							     \
137     if (NO_SYSCALL_CANCEL_CHECKING) 					     \
138       sc_ret = INTERNAL_SYSCALL_CALL (__VA_ARGS__); 			     \
139     else								     \
140       {									     \
141 	int sc_cancel_oldtype = LIBC_CANCEL_ASYNC ();			     \
142 	sc_ret = INTERNAL_SYSCALL_CALL (__VA_ARGS__);			     \
143         LIBC_CANCEL_RESET (sc_cancel_oldtype);				     \
144       }									     \
145     sc_ret;								     \
146   })
147 
148 /* Machine-dependent sysdep.h files are expected to define the macro
149    PSEUDO (function_name, syscall_name) to emit assembly code to define the
150    C-callable function FUNCTION_NAME to do system call SYSCALL_NAME.
151    r0 and r1 are the system call outputs.  MOVE(x, y) should be defined as
152    an instruction such that "MOVE(r1, r0)" works.  ret should be defined
153    as the return instruction.  */
154 
155 #ifndef SYS_ify
156 #define SYS_ify(syscall_name) SYS_##syscall_name
157 #endif
158 
159 /* Terminate a system call named SYM.  This is used on some platforms
160    to generate correct debugging information.  */
161 #ifndef PSEUDO_END
162 #define PSEUDO_END(sym)
163 #endif
164 #ifndef PSEUDO_END_NOERRNO
165 #define PSEUDO_END_NOERRNO(sym)	PSEUDO_END(sym)
166 #endif
167 #ifndef PSEUDO_END_ERRVAL
168 #define PSEUDO_END_ERRVAL(sym)	PSEUDO_END(sym)
169 #endif
170 
171 /* Wrappers around system calls should normally inline the system call code.
172    But sometimes it is not possible or implemented and we use this code.  */
173 #ifndef INLINE_SYSCALL
174 #define INLINE_SYSCALL(name, nr, args...) __syscall_##name (args)
175 #endif
176