1/* Copyright (C) 1991-2020 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, err) \
32 INTERNAL_SYSCALL (name, err, 0)
33#define __INTERNAL_SYSCALL1(name, err, a1) \
34 INTERNAL_SYSCALL (name, err, 1, a1)
35#define __INTERNAL_SYSCALL2(name, err, a1, a2) \
36 INTERNAL_SYSCALL (name, err, 2, a1, a2)
37#define __INTERNAL_SYSCALL3(name, err, a1, a2, a3) \
38 INTERNAL_SYSCALL (name, err, 3, a1, a2, a3)
39#define __INTERNAL_SYSCALL4(name, err, a1, a2, a3, a4) \
40 INTERNAL_SYSCALL (name, err, 4, a1, a2, a3, a4)
41#define __INTERNAL_SYSCALL5(name, err, a1, a2, a3, a4, a5) \
42 INTERNAL_SYSCALL (name, err, 5, a1, a2, a3, a4, a5)
43#define __INTERNAL_SYSCALL6(name, err, a1, a2, a3, a4, a5, a6) \
44 INTERNAL_SYSCALL (name, err, 6, a1, a2, a3, a4, a5, a6)
45#define __INTERNAL_SYSCALL7(name, err, a1, a2, a3, a4, a5, a6, a7) \
46 INTERNAL_SYSCALL (name, err, 7, a1, a2, a3, a4, a5, a6, a7)
47
48#define __INTERNAL_SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,o,...) o
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 __INLINE_SYSCALL0(name) \
61 INLINE_SYSCALL (name, 0)
62#define __INLINE_SYSCALL1(name, a1) \
63 INLINE_SYSCALL (name, 1, a1)
64#define __INLINE_SYSCALL2(name, a1, a2) \
65 INLINE_SYSCALL (name, 2, a1, a2)
66#define __INLINE_SYSCALL3(name, a1, a2, a3) \
67 INLINE_SYSCALL (name, 3, a1, a2, a3)
68#define __INLINE_SYSCALL4(name, a1, a2, a3, a4) \
69 INLINE_SYSCALL (name, 4, a1, a2, a3, a4)
70#define __INLINE_SYSCALL5(name, a1, a2, a3, a4, a5) \
71 INLINE_SYSCALL (name, 5, a1, a2, a3, a4, a5)
72#define __INLINE_SYSCALL6(name, a1, a2, a3, a4, a5, a6) \
73 INLINE_SYSCALL (name, 6, a1, a2, a3, a4, a5, a6)
74#define __INLINE_SYSCALL7(name, a1, a2, a3, a4, a5, a6, a7) \
75 INLINE_SYSCALL (name, 7, a1, a2, a3, a4, a5, a6, a7)
76
77#define __INLINE_SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n
78#define __INLINE_SYSCALL_NARGS(...) \
79 __INLINE_SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,)
80#define __INLINE_SYSCALL_DISP(b,...) \
81 __SYSCALL_CONCAT (b,__INLINE_SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
82
83/* Issue a syscall defined by syscall number plus any other argument
84 required. Any error will be handled using arch defined macros and errno
85 will be set accordingly.
86 It is similar to INLINE_SYSCALL macro, but without the need to pass the
87 expected argument number as second parameter. */
88#define INLINE_SYSCALL_CALL(...) \
89 __INLINE_SYSCALL_DISP (__INLINE_SYSCALL, __VA_ARGS__)
90
91#define SYSCALL_CANCEL(...) \
92 ({ \
93 long int sc_ret; \
94 if (SINGLE_THREAD_P) \
95 sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \
96 else \
97 { \
98 int sc_cancel_oldtype = LIBC_CANCEL_ASYNC (); \
99 sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \
100 LIBC_CANCEL_RESET (sc_cancel_oldtype); \
101 } \
102 sc_ret; \
103 })
104
105/* Issue a syscall defined by syscall number plus any other argument
106 required. Any error will be returned unmodified (including errno). */
107#define INTERNAL_SYSCALL_CANCEL(...) \
108 ({ \
109 long int sc_ret; \
110 if (SINGLE_THREAD_P) \
111 sc_ret = INTERNAL_SYSCALL_CALL (__VA_ARGS__); \
112 else \
113 { \
114 int sc_cancel_oldtype = LIBC_CANCEL_ASYNC (); \
115 sc_ret = INTERNAL_SYSCALL_CALL (__VA_ARGS__); \
116 LIBC_CANCEL_RESET (sc_cancel_oldtype); \
117 } \
118 sc_ret; \
119 })
120
121/* Machine-dependent sysdep.h files are expected to define the macro
122 PSEUDO (function_name, syscall_name) to emit assembly code to define the
123 C-callable function FUNCTION_NAME to do system call SYSCALL_NAME.
124 r0 and r1 are the system call outputs. MOVE(x, y) should be defined as
125 an instruction such that "MOVE(r1, r0)" works. ret should be defined
126 as the return instruction. */
127
128#ifndef SYS_ify
129#define SYS_ify(syscall_name) SYS_##syscall_name
130#endif
131
132/* Terminate a system call named SYM. This is used on some platforms
133 to generate correct debugging information. */
134#ifndef PSEUDO_END
135#define PSEUDO_END(sym)
136#endif
137#ifndef PSEUDO_END_NOERRNO
138#define PSEUDO_END_NOERRNO(sym) PSEUDO_END(sym)
139#endif
140#ifndef PSEUDO_END_ERRVAL
141#define PSEUDO_END_ERRVAL(sym) PSEUDO_END(sym)
142#endif
143
144/* Wrappers around system calls should normally inline the system call code.
145 But sometimes it is not possible or implemented and we use this code. */
146#ifndef INLINE_SYSCALL
147#define INLINE_SYSCALL(name, nr, args...) __syscall_##name (args)
148#endif
149