Coverage Report

Created: 2025-08-26 06:27

/src/numactl/syscall.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2003,2004 Andi Kleen, SuSE Labs.
2
3
   libnuma is free software; you can redistribute it and/or
4
   modify it under the terms of the GNU Lesser General Public
5
   License as published by the Free Software Foundation; version
6
   2.1.
7
8
   libnuma is distributed in the hope that it will be useful,
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
   Lesser General Public License for more details.
12
13
   You should find a copy of v2.1 of the GNU Lesser General Public License
14
   somewhere on your Linux system; if not, write to the Free Software
15
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#define _GNU_SOURCE
17
#include <unistd.h>
18
#include <sys/types.h>
19
#include <asm/unistd.h>
20
#include <errno.h>
21
#include "numa.h"
22
#include "numaif.h"
23
#include "numaint.h"
24
#include "config.h"
25
#include "util.h"
26
27
#define WEAK __attribute__((weak))
28
29
#if !defined(__NR_mbind) || !defined(__NR_set_mempolicy) || \
30
    !defined(__NR_get_mempolicy) || !defined(__NR_migrate_pages) || \
31
    !defined(__NR_move_pages)
32
33
#if defined(__x86_64__)
34
35
#define __NR_sched_setaffinity    203
36
#define __NR_sched_getaffinity     204
37
38
/* Official allocation */
39
40
#define __NR_mbind 237
41
#define __NR_set_mempolicy 238
42
#define __NR_get_mempolicy 239
43
#define __NR_migrate_pages 256
44
#define __NR_move_pages 279
45
46
#elif defined(__ia64__)
47
#define __NR_sched_setaffinity    1231
48
#define __NR_sched_getaffinity    1232
49
#define __NR_migrate_pages  1280
50
#define __NR_move_pages 1276
51
52
/* Official allocation */
53
54
#define __NR_mbind 1259
55
#define __NR_get_mempolicy 1260
56
#define __NR_set_mempolicy 1261
57
58
#elif defined(__i386__)
59
60
#define __NR_mbind 274
61
#define __NR_get_mempolicy 275
62
#define __NR_set_mempolicy 276
63
#define __NR_migrate_pages 294
64
#define __NR_move_pages 317
65
66
#elif defined(__powerpc__)
67
68
#define __NR_mbind 259
69
#define __NR_get_mempolicy 260
70
#define __NR_set_mempolicy 261
71
#define __NR_migrate_pages 258
72
/* FIXME: powerpc is missing move pages!!!
73
#define __NR_move_pages xxx
74
*/
75
76
#elif defined(__loongarch__)
77
78
//reference to /usr/include/asm-generic/unistd.h
79
80
#define __NR_mbind 235
81
#define __NR_get_mempolicy 236
82
#define __NR_set_mempolicy 237
83
#define __NR_migrate_pages 238
84
#define __NR_move_pages 239
85
86
#elif defined(__mips__)
87
88
#if _MIPS_SIM == _ABIO32
89
/*
90
 * Linux o32 style syscalls are in the range from 4000 to 4999.
91
 */
92
#define __NR_Linux 4000
93
#define __NR_mbind (__NR_Linux + 268)
94
#define __NR_get_mempolicy (__NR_Linux + 269)
95
#define __NR_set_mempolicy (__NR_Linux + 270)
96
#define __NR_migrate_pages (__NR_Linux + 287)
97
#endif
98
99
#if _MIPS_SIM == _ABI64
100
/*
101
 * Linux 64-bit syscalls are in the range from 5000 to 5999.
102
 */
103
#define __NR_Linux 5000
104
#define __NR_mbind (__NR_Linux + 227)
105
#define __NR_get_mempolicy (__NR_Linux + 228)
106
#define __NR_set_mempolicy (__NR_Linux + 229)
107
#define __NR_migrate_pages (__NR_Linux + 246)
108
#endif
109
110
#if _MIPS_SIM == _ABIN32
111
/*
112
 * Linux N32 syscalls are in the range from 6000 to 6999.
113
 */
114
#define __NR_Linux 6000
115
#define __NR_mbind (__NR_Linux + 231)
116
#define __NR_get_mempolicy (__NR_Linux + 232)
117
#define __NR_set_mempolicy (__NR_Linux + 233)
118
#define __NR_migrate_pages (__NR_Linux + 250)
119
#endif
120
121
#elif defined(__hppa__)
122
123
#define __NR_migrate_pages  272
124
125
#elif defined(__arm__)
126
/* https://bugs.debian.org/796802 */
127
#warning "ARM does not implement the migrate_pages() syscall"
128
129
#elif defined(__s390x__)
130
131
#define __NR_mbind 268
132
#define __NR_get_mempolicy 269
133
#define __NR_set_mempolicy 270
134
#define __NR_migrate_pages 287
135
#define __NR_move_pages    310
136
137
#elif !defined(DEPS_RUN)
138
#error "Add syscalls for your architecture or update kernel headers"
139
#endif
140
141
#endif
142
143
#if !defined(__NR_set_mempolicy_home_node)
144
145
#if defined(__x86_64__) || defined(__aarch64__) || defined(__i386__) || defined(__powerpc__) || defined(__mips__) || defined(__s390x__)
146
0
#define __NR_set_mempolicy_home_node 450
147
#else
148
#warning "Add syscalls for your architecture or update kernel headers"
149
#endif
150
151
#endif
152
153
#ifndef __GLIBC_PREREQ
154
# define __GLIBC_PREREQ(x,y) 0
155
#endif
156
157
#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 11)
158
159
/* glibc 2.11 seems to have working 6 argument sycall. Use the
160
   glibc supplied syscall in this case.
161
   The version cut-off is rather arbitrary and could be probably
162
   earlier. */
163
164
0
#define syscall6 syscall
165
#elif defined(__x86_64__)
166
/* 6 argument calls on x86-64 are often buggy in both glibc and
167
   asm/unistd.h. Add a working version here. */
168
long syscall6(long call, long a, long b, long c, long d, long e, long f)
169
{
170
       long res;
171
       asm volatile ("movq %[d],%%r10 ; movq %[e],%%r8 ; movq %[f],%%r9 ; syscall"
172
         : "=a" (res)
173
         : "0" (call),"D" (a),"S" (b), "d" (c),
174
           [d] "g" (d), [e] "g" (e), [f] "g" (f) :
175
         "r11","rcx","r8","r10","r9","memory" );
176
       if (res < 0) {
177
         errno = -res;
178
         res = -1;
179
       }
180
       return res;
181
}
182
#elif defined(__i386__)
183
184
/* i386 has buggy syscall6 in glibc too. This is tricky to do
185
   in inline assembly because it clobbers so many registers. Do it
186
   out of line. */
187
asm(
188
"__syscall6:\n"
189
" pushl %ebp\n"
190
" pushl %edi\n"
191
" pushl %esi\n"
192
" pushl %ebx\n"
193
" movl  (0+5)*4(%esp),%eax\n"
194
" movl  (1+5)*4(%esp),%ebx\n"
195
" movl  (2+5)*4(%esp),%ecx\n"
196
" movl  (3+5)*4(%esp),%edx\n"
197
" movl  (4+5)*4(%esp),%esi\n"
198
" movl  (5+5)*4(%esp),%edi\n"
199
" movl  (6+5)*4(%esp),%ebp\n"
200
" int $0x80\n"
201
" popl %ebx\n"
202
" popl %esi\n"
203
" popl %edi\n"
204
" popl %ebp\n"
205
" ret"
206
);
207
extern long __syscall6(long n, long a, long b, long c, long d, long e, long f);
208
209
long syscall6(long call, long a, long b, long c, long d, long e, long f)
210
{
211
       long res = __syscall6(call,a,b,c,d,e,f);
212
       if (res < 0) {
213
         errno = -res;
214
         res = -1;
215
       }
216
       return res;
217
}
218
219
#else
220
#define syscall6 syscall
221
#endif
222
223
long WEAK get_mempolicy(int *policy, unsigned long *nmask,
224
        unsigned long maxnode, void *addr,
225
        unsigned flags)
226
0
{
227
0
  return syscall(__NR_get_mempolicy, policy, nmask,
228
0
          maxnode, addr, flags);
229
0
}
230
231
long WEAK mbind(void *start, unsigned long len, int mode,
232
  const unsigned long *nmask, unsigned long maxnode, unsigned flags)
233
0
{
234
0
  return syscall6(__NR_mbind, (long)start, len, mode, (long)nmask,
235
0
        maxnode, flags);
236
0
}
237
238
long WEAK set_mempolicy(int mode, const unsigned long *nmask,
239
                                   unsigned long maxnode)
240
0
{
241
0
  long i;
242
0
  i = syscall(__NR_set_mempolicy,mode,nmask,maxnode);
243
0
  return i;
244
0
}
245
246
long WEAK migrate_pages(int pid, unsigned long maxnode,
247
  const unsigned long *frommask, const unsigned long *tomask)
248
0
{
249
0
#if defined(__NR_migrate_pages)
250
0
  return syscall(__NR_migrate_pages, pid, maxnode, frommask, tomask);
251
#else
252
    errno = ENOSYS;
253
    return -1;
254
#endif
255
0
}
256
257
long WEAK move_pages(int pid, unsigned long count,
258
  void **pages, const int *nodes, int *status, int flags)
259
0
{
260
0
  return syscall(__NR_move_pages, pid, count, pages, nodes, status, flags);
261
0
}
262
263
int WEAK set_mempolicy_home_node(void *start, unsigned long len, int home_node, int flags)
264
0
{
265
#ifndef __NR_set_mempolicy_home_node
266
   errno = ENOSYS;
267
   return -1;
268
#else
269
0
   return syscall(__NR_set_mempolicy_home_node, start, len, home_node, flags);
270
0
#endif
271
0
}
272
273
/* SLES8 glibc doesn't define those */
274
SYMVER("numa_sched_setaffinity_v1", "numa_sched_setaffinity@libnuma_1.1")
275
int numa_sched_setaffinity_v1(pid_t pid, unsigned len, const unsigned long *mask)
276
0
{
277
0
  return syscall(__NR_sched_setaffinity,pid,len,mask);
278
0
}
279
280
SYMVER("numa_sched_setaffinity_v2", "numa_sched_setaffinity@@libnuma_1.2")
281
int numa_sched_setaffinity_v2(pid_t pid, struct bitmask *mask)
282
0
{
283
0
  return syscall(__NR_sched_setaffinity, pid, numa_bitmask_nbytes(mask),
284
0
                mask->maskp);
285
0
}
286
287
SYMVER("numa_sched_getaffinity_v1", "numa_sched_getaffinity@libnuma_1.1")
288
int numa_sched_getaffinity_v1(pid_t pid, unsigned len, const unsigned long *mask)
289
0
{
290
0
  return syscall(__NR_sched_getaffinity,pid,len,mask);
291
0
}
292
293
SYMVER("numa_sched_getaffinity_v2", "numa_sched_getaffinity@@libnuma_1.2")
294
int numa_sched_getaffinity_v2(pid_t pid, struct bitmask *mask)
295
2
{
296
  /* len is length in bytes */
297
2
  return syscall(__NR_sched_getaffinity, pid, numa_bitmask_nbytes(mask),
298
2
                mask->maskp);
299
  /* sched_getaffinity returns sizeof(cpumask_t) */
300
2
}
301
302
make_internal_alias(numa_sched_getaffinity_v1);
303
make_internal_alias(numa_sched_getaffinity_v2);
304
make_internal_alias(numa_sched_setaffinity_v1);
305
make_internal_alias(numa_sched_setaffinity_v2);