Back to index

numactl  2.0.8~rc4
syscall.c
Go to the documentation of this file.
00001 /* Copyright (C) 2003,2004 Andi Kleen, SuSE Labs.
00002 
00003    libnuma is free software; you can redistribute it and/or
00004    modify it under the terms of the GNU Lesser General Public
00005    License as published by the Free Software Foundation; version
00006    2.1.
00007 
00008    libnuma is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Lesser General Public License for more details.
00012 
00013    You should find a copy of v2.1 of the GNU Lesser General Public License
00014    somewhere on your Linux system; if not, write to the Free Software
00015    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
00016 #include <unistd.h>
00017 #include <sys/types.h>
00018 #include <asm/unistd.h>
00019 #include <errno.h>
00020 #include "numa.h"
00021 #include "numaif.h"
00022 #include "numaint.h"
00023 
00024 #define WEAK __attribute__((weak))
00025 
00026 #if !defined(__NR_mbind) || !defined(__NR_set_mempolicy) || \
00027     !defined(__NR_get_mempolicy) || !defined(__NR_migrate_pages) || \
00028     !defined(__NR_move_pages)
00029 
00030 #if defined(__x86_64__)
00031 
00032 #define __NR_sched_setaffinity    203
00033 #define __NR_sched_getaffinity     204
00034 
00035 /* Official allocation */
00036 
00037 #define __NR_mbind 237
00038 #define __NR_set_mempolicy 238
00039 #define __NR_get_mempolicy 239
00040 #define __NR_migrate_pages 256
00041 #define __NR_move_pages 279
00042 
00043 #elif defined(__ia64__)
00044 #define __NR_sched_setaffinity    1231
00045 #define __NR_sched_getaffinity    1232
00046 #define __NR_migrate_pages  1280
00047 #define __NR_move_pages 1276
00048 
00049 /* Official allocation */
00050 
00051 #define __NR_mbind 1259
00052 #define __NR_get_mempolicy 1260
00053 #define __NR_set_mempolicy 1261
00054 
00055 #elif defined(__i386__)
00056 
00057 #define __NR_mbind 274
00058 #define __NR_get_mempolicy 275
00059 #define __NR_set_mempolicy 276
00060 #define __NR_migrate_pages 294
00061 #define __NR_move_pages 317
00062 
00063 #elif defined(__powerpc__)
00064 
00065 #define __NR_mbind 259
00066 #define __NR_get_mempolicy 260
00067 #define __NR_set_mempolicy 261
00068 #define __NR_migrate_pages 258
00069 /* FIXME: powerpc is missing move pages!!!
00070 #define __NR_move_pages xxx
00071 */
00072 
00073 #elif defined(__mips__)
00074 
00075 #if _MIPS_SIM == _ABIO32
00076 /*
00077  * Linux o32 style syscalls are in the range from 4000 to 4999.
00078  */
00079 #define __NR_Linux 4000
00080 #define __NR_mbind (__NR_Linux + 268)
00081 #define __NR_get_mempolicy (__NR_Linux + 269)
00082 #define __NR_set_mempolicy (__NR_Linux + 270)
00083 #define __NR_migrate_pages (__NR_Linux + 287)
00084 #endif
00085 
00086 #if _MIPS_SIM == _ABI64
00087 /*
00088  * Linux 64-bit syscalls are in the range from 5000 to 5999.
00089  */
00090 #define __NR_Linux 5000
00091 #define __NR_mbind (__NR_Linux + 227)
00092 #define __NR_get_mempolicy (__NR_Linux + 228)
00093 #define __NR_set_mempolicy (__NR_Linux + 229)
00094 #define __NR_migrate_pages (__NR_Linux + 246)
00095 #endif
00096 
00097 #if _MIPS_SIM == _ABIN32
00098 /*
00099  * Linux N32 syscalls are in the range from 6000 to 6999.
00100  */
00101 #define __NR_Linux 6000
00102 #define __NR_mbind (__NR_Linux + 231)
00103 #define __NR_get_mempolicy (__NR_Linux + 232)
00104 #define __NR_set_mempolicy (__NR_Linux + 233)
00105 #define __NR_migrate_pages (__NR_Linux + 250)
00106 #endif
00107 
00108 #elif defined(__hppa__)
00109 
00110 #define __NR_migrate_pages  272
00111 
00112 #elif !defined(DEPS_RUN)
00113 #error "Add syscalls for your architecture or update kernel headers"
00114 #endif
00115 
00116 #endif
00117 
00118 #if defined(__GLIBC__) && __GLIBC_PREREQ(2, 11)
00119 
00120 /* glibc 2.11 seems to have working 6 argument sycall. Use the
00121    glibc supplied syscall in this case.
00122    The version cut-off is rather arbitary and could be probably
00123    earlier. */
00124 
00125 #define syscall6 syscall
00126 #elif defined(__x86_64__)
00127 /* 6 argument calls on x86-64 are often buggy in both glibc and
00128    asm/unistd.h. Add a working version here. */
00129 long syscall6(long call, long a, long b, long c, long d, long e, long f)
00130 {
00131        long res;
00132        asm volatile ("movq %[d],%%r10 ; movq %[e],%%r8 ; movq %[f],%%r9 ; syscall"
00133                    : "=a" (res)
00134                    : "0" (call),"D" (a),"S" (b), "d" (c),
00135                      [d] "g" (d), [e] "g" (e), [f] "g" (f) :
00136                    "r11","rcx","r8","r10","r9","memory" );
00137        if (res < 0) {
00138               errno = -res;
00139               res = -1;
00140        }
00141        return res;
00142 }
00143 #elif defined(__i386__)
00144 
00145 /* i386 has buggy syscall6 in glibc too. This is tricky to do
00146    in inline assembly because it clobbers so many registers. Do it
00147    out of line. */
00148 asm(
00149 "__syscall6:\n"
00150 "      pushl %ebp\n"
00151 "      pushl %edi\n"
00152 "      pushl %esi\n"
00153 "      pushl %ebx\n"
00154 "      movl  (0+5)*4(%esp),%eax\n"
00155 "      movl  (1+5)*4(%esp),%ebx\n"
00156 "      movl  (2+5)*4(%esp),%ecx\n"
00157 "      movl  (3+5)*4(%esp),%edx\n"
00158 "      movl  (4+5)*4(%esp),%esi\n"
00159 "      movl  (5+5)*4(%esp),%edi\n"
00160 "      movl  (6+5)*4(%esp),%ebp\n"
00161 "      int $0x80\n"
00162 "      popl %ebx\n"
00163 "      popl %esi\n"
00164 "      popl %edi\n"
00165 "      popl %ebp\n"
00166 "      ret"
00167 );
00168 extern long __syscall6(long n, long a, long b, long c, long d, long e, long f);
00169 
00170 long syscall6(long call, long a, long b, long c, long d, long e, long f)
00171 {
00172        long res = __syscall6(call,a,b,c,d,e,f);
00173        if (res < 0) {
00174               errno = -res;
00175               res = -1;
00176        }
00177        return res;
00178 }
00179 
00180 #else
00181 #define syscall6 syscall
00182 #endif
00183 
00184 long WEAK get_mempolicy(int *policy, const unsigned long *nmask,
00185                             unsigned long maxnode, void *addr, int flags)
00186 {
00187        return syscall(__NR_get_mempolicy, policy, nmask,
00188                                    maxnode, addr, flags);
00189 }
00190 
00191 long WEAK mbind(void *start, unsigned long len, int mode,
00192        const unsigned long *nmask, unsigned long maxnode, unsigned flags)
00193 {
00194        return syscall6(__NR_mbind, (long)start, len, mode, (long)nmask,
00195                             maxnode, flags);
00196 }
00197 
00198 long WEAK set_mempolicy(int mode, const unsigned long *nmask,
00199                                    unsigned long maxnode)
00200 {
00201        long i;
00202        i = syscall(__NR_set_mempolicy,mode,nmask,maxnode);
00203        return i;
00204 }
00205 
00206 long WEAK migrate_pages(int pid, unsigned long maxnode,
00207        const unsigned long *frommask, const unsigned long *tomask)
00208 {
00209        return syscall(__NR_migrate_pages, pid, maxnode, frommask, tomask);
00210 }
00211 
00212 long WEAK move_pages(int pid, unsigned long count,
00213        void **pages, const int *nodes, int *status, int flags)
00214 {
00215        return syscall(__NR_move_pages, pid, count, pages, nodes, status, flags);
00216 }
00217 
00218 /* SLES8 glibc doesn't define those */
00219 int numa_sched_setaffinity_v1(pid_t pid, unsigned len, const unsigned long *mask)
00220 {
00221        return syscall(__NR_sched_setaffinity,pid,len,mask);
00222 }
00223 __asm__(".symver numa_sched_setaffinity_v1,numa_sched_setaffinity@libnuma_1.1");
00224 
00225 int numa_sched_setaffinity_v2(pid_t pid, struct bitmask *mask)
00226 {
00227        return syscall(__NR_sched_setaffinity, pid, numa_bitmask_nbytes(mask),
00228                                                         mask->maskp);
00229 }
00230 __asm__(".symver numa_sched_setaffinity_v2,numa_sched_setaffinity@@libnuma_1.2");
00231 
00232 int numa_sched_getaffinity_v1(pid_t pid, unsigned len, const unsigned long *mask)
00233 {
00234        return syscall(__NR_sched_getaffinity,pid,len,mask);
00235 
00236 }
00237 __asm__(".symver numa_sched_getaffinity_v1,numa_sched_getaffinity@libnuma_1.1");
00238 
00239 int numa_sched_getaffinity_v2(pid_t pid, struct bitmask *mask)
00240 {
00241        /* len is length in bytes */
00242        return syscall(__NR_sched_getaffinity, pid, numa_bitmask_nbytes(mask),
00243                                                         mask->maskp);
00244        /* sched_getaffinity returns sizeof(cpumask_t) */
00245 
00246 }
00247 __asm__(".symver numa_sched_getaffinity_v2,numa_sched_getaffinity@@libnuma_1.2");
00248 
00249 make_internal_alias(numa_sched_getaffinity_v1);
00250 make_internal_alias(numa_sched_getaffinity_v2);
00251 make_internal_alias(numa_sched_setaffinity_v1);
00252 make_internal_alias(numa_sched_setaffinity_v2);