Add support for get_mempolicy(2), mbind(2), migrate_pages(2), move_pages(2) and set_mempolicy(2).
These system calls can be used to manipulate the CPU and memory allocation strategies of a process when used with a NUMA enabled kernel. NUMA is used by a number of embedded SoCs to allow processes to make use of low-latency on-chip memories. The numaif.h header has been taken from the numactl/libnuma package. Signed-off-by: Will Newton <[email protected]> --- libnuma doesn't work well with uClibc because it uses symbol versioning which isn't supported by uClibc ldso. It's also a rather heavyweight solution for the embedded space where typically that level of complexity is not required. This patch adds the system calls and header from libnuma as a lightweight alternative. Makefile.in | 4 ++ extra/Configs/Config.in | 13 ++++++++ include/numaif.h | 48 +++++++++++++++++++++++++++++ libc/sysdeps/linux/common/Makefile.in | 5 +++ libc/sysdeps/linux/common/get_mempolicy.c | 21 ++++++++++++ libc/sysdeps/linux/common/mbind.c | 23 ++++++++++++++ libc/sysdeps/linux/common/migrate_pages.c | 22 +++++++++++++ libc/sysdeps/linux/common/move_pages.c | 23 ++++++++++++++ libc/sysdeps/linux/common/set_mempolicy.c | 21 ++++++++++++ 9 files changed, 180 insertions(+), 0 deletions(-) create mode 100644 include/numaif.h create mode 100644 libc/sysdeps/linux/common/get_mempolicy.c create mode 100644 libc/sysdeps/linux/common/mbind.c create mode 100644 libc/sysdeps/linux/common/migrate_pages.c create mode 100644 libc/sysdeps/linux/common/move_pages.c create mode 100644 libc/sysdeps/linux/common/set_mempolicy.c diff --git a/Makefile.in b/Makefile.in index 348bc0c..af37032 100644 --- a/Makefile.in +++ b/Makefile.in @@ -376,6 +376,10 @@ ifeq ($(UCLIBC_FORMAT_SHARED_FLAT),y) fi; \ done endif +ifneq ($(UCLIBC_HAS_NUMA),y) + # Remove numaif.h since NUMA was disabled upon request + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/numaif.h +endif # Installs run-time libraries install_runtime: all | $(PREFIX)$(RUNTIME_PREFIX)$(MULTILIB_DIR) diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index e8d522d..7518caf 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -1137,6 +1137,19 @@ config UCLIBC_HAS_CRYPT_STUB config UCLIBC_HAS_CRYPT def_bool y depends on UCLIBC_HAS_CRYPT_IMPL || UCLIBC_HAS_CRYPT_STUB + +config UCLIBC_HAS_NUMA + bool "NUMA support" + default n + help + These functions allow tasks and memory to be moved between + different NUMA nodes. NUMA support must be enabled in the kernel + and the hardware must have more than one NUMA node for this + option to be useful. + + get_mempolicy(), mbind(), migrate_pages(), move_pages(), + set_mempolicy() + endmenu menuconfig UCLIBC_HAS_NETWORK_SUPPORT diff --git a/include/numaif.h b/include/numaif.h new file mode 100644 index 0000000..6aef7d5 --- /dev/null +++ b/include/numaif.h @@ -0,0 +1,48 @@ +#ifndef NUMAIF_H +#define NUMAIF_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Kernel interface for NUMA API */ + +/* System calls */ +extern long get_mempolicy(int *policy, const unsigned long *nmask, + unsigned long maxnode, void *addr, int flags); +extern long mbind(void *start, unsigned long len, int mode, + const unsigned long *nmask, unsigned long maxnode, unsigned flags); +extern long set_mempolicy(int mode, const unsigned long *nmask, + unsigned long maxnode); +extern long migrate_pages(int pid, unsigned long maxnode, + const unsigned long *frommask, + const unsigned long *tomask); + +extern long move_pages(int pid, unsigned long count, + void **pages, const int *nodes, int *status, int flags); + +/* Policies */ +#define MPOL_DEFAULT 0 +#define MPOL_PREFERRED 1 +#define MPOL_BIND 2 +#define MPOL_INTERLEAVE 3 + +#define MPOL_MAX MPOL_INTERLEAVE + +/* Flags for get_mem_policy */ +#define MPOL_F_NODE (1<<0) /* return next il node or node of address */ + /* Warning: MPOL_F_NODE is unsupported and + subject to change. Don't use. */ +#define MPOL_F_ADDR (1<<1) /* look up vma using address */ +#define MPOL_F_MEMS_ALLOWED (1<<2) /* query nodes allowed in cpuset */ + +/* Flags for mbind */ +#define MPOL_MF_STRICT (1<<0) /* Verify existing pages in the mapping */ +#define MPOL_MF_MOVE (1<<1) /* Move pages owned by this process to conform to mapping */ +#define MPOL_MF_MOVE_ALL (1<<2) /* Move every page to conform to mapping */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/sysdeps/linux/common/Makefile.in b/libc/sysdeps/linux/common/Makefile.in index 1711e80..f0f2b99 100644 --- a/libc/sysdeps/linux/common/Makefile.in +++ b/libc/sysdeps/linux/common/Makefile.in @@ -102,6 +102,11 @@ endif CSRC := $(filter-out $(libc_a_CSRC) $(notdir $(libpthread_libc_OBJS:.o=.c)),$(CSRC)) SSRC := $(filter-out $(libc_a_SSRC) $(notdir $(libpthread_libc_OBJS:.o=.S)),$(SSRC)) +ifneq ($(UCLIBC_HAS_NUMA),y) +CSRC := $(filter-out get_mempolicy.c mbind.c migrate_pages.c move_pages.c \ + set_mempolicy.c,$(CSRC)) +endif + # fails for some reason ifneq ($(strip $(ARCH_OBJS)),) CSRC := $(filter-out $(notdir $(ARCH_OBJS:.o=.c)) $(ARCH_OBJ_FILTEROUT),$(CSRC)) diff --git a/libc/sysdeps/linux/common/get_mempolicy.c b/libc/sysdeps/linux/common/get_mempolicy.c new file mode 100644 index 0000000..c0d2be5 --- /dev/null +++ b/libc/sysdeps/linux/common/get_mempolicy.c @@ -0,0 +1,21 @@ +/* + * get_mempolicy() for uClibc + * + * Copyright (C) 2010 Will Newton <[email protected]> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <sys/syscall.h> + +#ifdef __NR_get_mempolicy +_syscall5(long, get_mempolicy, int *, __policy, const unsigned long *, __nmask, + unsigned long, __maxnode, void *, __addr, int, __flags) +#else +long get_mempolicy(int *__policy, const unsigned long *__nmask, + unsigned long __maxnode, void *__addr, int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/mbind.c b/libc/sysdeps/linux/common/mbind.c new file mode 100644 index 0000000..2e77698 --- /dev/null +++ b/libc/sysdeps/linux/common/mbind.c @@ -0,0 +1,23 @@ +/* + * mbind() for uClibc + * + * Copyright (C) 2010 Will Newton <[email protected]> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <sys/syscall.h> + +#ifdef __NR_mbind +_syscall6(long, mbind, void *, __start, unsigned long, __len, + int, __mode, const unsigned long *, __nmask, + unsigned long, __maxnode, unsigned int, __flags) +#else +long mbind(void * __start, unsigned long __len, int __mode, + const unsigned long * __nmask, unsigned long __maxnode, + unsigned int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/migrate_pages.c b/libc/sysdeps/linux/common/migrate_pages.c new file mode 100644 index 0000000..cf3aa0d --- /dev/null +++ b/libc/sysdeps/linux/common/migrate_pages.c @@ -0,0 +1,22 @@ +/* + * migrate_pages() for uClibc + * + * Copyright (C) 2010 Will Newton <[email protected]> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <sys/syscall.h> + +#ifdef __NR_migrate_pages +_syscall4(long, migrate_pages, int, __pid, unsigned long, __maxnode, + const unsigned long *, __frommask, const unsigned long *, __tomask) +#else +long migrate_pages(int __pid, unsigned long __maxnode, + const unsigned long * __frommask, + const unsigned long * __tomask) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/move_pages.c b/libc/sysdeps/linux/common/move_pages.c new file mode 100644 index 0000000..e8d99b0 --- /dev/null +++ b/libc/sysdeps/linux/common/move_pages.c @@ -0,0 +1,23 @@ +/* + * move_pages() for uClibc + * + * Copyright (C) 2010 Will Newton <[email protected]> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <sys/syscall.h> + +#ifdef __NR_move_pages +_syscall6(long, move_pages, int, __pid, unsigned long, __count, + void **, __pages, const int *, __nodes, int *, __status, + int, __flags) +#else +long move_pages(int __pid, unsigned long __count, + void ** __pages, const int * __nodes, int * __status, + int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/set_mempolicy.c b/libc/sysdeps/linux/common/set_mempolicy.c new file mode 100644 index 0000000..c625041 --- /dev/null +++ b/libc/sysdeps/linux/common/set_mempolicy.c @@ -0,0 +1,21 @@ +/* + * set_mempolicy() for uClibc + * + * Copyright (C) 2010 Will Newton <[email protected]> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <sys/syscall.h> + +#ifdef __NR_set_mempolicy +_syscall3(long, set_mempolicy, int , __mode, const unsigned long *, __nmask, + unsigned long, __maxnode) +#else +long set_mempolicy(int __mode, const unsigned long *__nmask, + unsigned long __maxnode) +{ + __set_errno(ENOSYS); + return -1; +} +#endif -- 1.7.2.2
From a01ad2b4b003b37504ff7e029e9169f0aca41079 Mon Sep 17 00:00:00 2001 From: Will Newton <[email protected]> Date: Wed, 15 Sep 2010 16:06:20 +0100 Subject: [PATCH] libc: Add support for NUMA system calls. Add support for get_mempolicy(2), mbind(2), migrate_pages(2), move_pages(2) and set_mempolicy(2). These system calls can be used to manipulate the CPU and memory allocation strategies of a process when used with a NUMA enabled kernel. NUMA is used by a number of embedded SoCs to allow processes to make use of low-latency on-chip memories. The numaif.h header has been taken from the numactl/libnuma package. Signed-off-by: Will Newton <[email protected]> --- Makefile.in | 4 ++ extra/Configs/Config.in | 13 ++++++++ include/numaif.h | 48 +++++++++++++++++++++++++++++ libc/sysdeps/linux/common/Makefile.in | 5 +++ libc/sysdeps/linux/common/get_mempolicy.c | 21 ++++++++++++ libc/sysdeps/linux/common/mbind.c | 23 ++++++++++++++ libc/sysdeps/linux/common/migrate_pages.c | 22 +++++++++++++ libc/sysdeps/linux/common/move_pages.c | 23 ++++++++++++++ libc/sysdeps/linux/common/set_mempolicy.c | 21 ++++++++++++ 9 files changed, 180 insertions(+), 0 deletions(-) create mode 100644 include/numaif.h create mode 100644 libc/sysdeps/linux/common/get_mempolicy.c create mode 100644 libc/sysdeps/linux/common/mbind.c create mode 100644 libc/sysdeps/linux/common/migrate_pages.c create mode 100644 libc/sysdeps/linux/common/move_pages.c create mode 100644 libc/sysdeps/linux/common/set_mempolicy.c diff --git a/Makefile.in b/Makefile.in index 348bc0c..af37032 100644 --- a/Makefile.in +++ b/Makefile.in @@ -376,6 +376,10 @@ ifeq ($(UCLIBC_FORMAT_SHARED_FLAT),y) fi; \ done endif +ifneq ($(UCLIBC_HAS_NUMA),y) + # Remove numaif.h since NUMA was disabled upon request + $(RM) $(PREFIX)$(DEVEL_PREFIX)include/numaif.h +endif # Installs run-time libraries install_runtime: all | $(PREFIX)$(RUNTIME_PREFIX)$(MULTILIB_DIR) diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index e8d522d..7518caf 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -1137,6 +1137,19 @@ config UCLIBC_HAS_CRYPT_STUB config UCLIBC_HAS_CRYPT def_bool y depends on UCLIBC_HAS_CRYPT_IMPL || UCLIBC_HAS_CRYPT_STUB + +config UCLIBC_HAS_NUMA + bool "NUMA support" + default n + help + These functions allow tasks and memory to be moved between + different NUMA nodes. NUMA support must be enabled in the kernel + and the hardware must have more than one NUMA node for this + option to be useful. + + get_mempolicy(), mbind(), migrate_pages(), move_pages(), + set_mempolicy() + endmenu menuconfig UCLIBC_HAS_NETWORK_SUPPORT diff --git a/include/numaif.h b/include/numaif.h new file mode 100644 index 0000000..6aef7d5 --- /dev/null +++ b/include/numaif.h @@ -0,0 +1,48 @@ +#ifndef NUMAIF_H +#define NUMAIF_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Kernel interface for NUMA API */ + +/* System calls */ +extern long get_mempolicy(int *policy, const unsigned long *nmask, + unsigned long maxnode, void *addr, int flags); +extern long mbind(void *start, unsigned long len, int mode, + const unsigned long *nmask, unsigned long maxnode, unsigned flags); +extern long set_mempolicy(int mode, const unsigned long *nmask, + unsigned long maxnode); +extern long migrate_pages(int pid, unsigned long maxnode, + const unsigned long *frommask, + const unsigned long *tomask); + +extern long move_pages(int pid, unsigned long count, + void **pages, const int *nodes, int *status, int flags); + +/* Policies */ +#define MPOL_DEFAULT 0 +#define MPOL_PREFERRED 1 +#define MPOL_BIND 2 +#define MPOL_INTERLEAVE 3 + +#define MPOL_MAX MPOL_INTERLEAVE + +/* Flags for get_mem_policy */ +#define MPOL_F_NODE (1<<0) /* return next il node or node of address */ + /* Warning: MPOL_F_NODE is unsupported and + subject to change. Don't use. */ +#define MPOL_F_ADDR (1<<1) /* look up vma using address */ +#define MPOL_F_MEMS_ALLOWED (1<<2) /* query nodes allowed in cpuset */ + +/* Flags for mbind */ +#define MPOL_MF_STRICT (1<<0) /* Verify existing pages in the mapping */ +#define MPOL_MF_MOVE (1<<1) /* Move pages owned by this process to conform to mapping */ +#define MPOL_MF_MOVE_ALL (1<<2) /* Move every page to conform to mapping */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/sysdeps/linux/common/Makefile.in b/libc/sysdeps/linux/common/Makefile.in index 1711e80..f0f2b99 100644 --- a/libc/sysdeps/linux/common/Makefile.in +++ b/libc/sysdeps/linux/common/Makefile.in @@ -102,6 +102,11 @@ endif CSRC := $(filter-out $(libc_a_CSRC) $(notdir $(libpthread_libc_OBJS:.o=.c)),$(CSRC)) SSRC := $(filter-out $(libc_a_SSRC) $(notdir $(libpthread_libc_OBJS:.o=.S)),$(SSRC)) +ifneq ($(UCLIBC_HAS_NUMA),y) +CSRC := $(filter-out get_mempolicy.c mbind.c migrate_pages.c move_pages.c \ + set_mempolicy.c,$(CSRC)) +endif + # fails for some reason ifneq ($(strip $(ARCH_OBJS)),) CSRC := $(filter-out $(notdir $(ARCH_OBJS:.o=.c)) $(ARCH_OBJ_FILTEROUT),$(CSRC)) diff --git a/libc/sysdeps/linux/common/get_mempolicy.c b/libc/sysdeps/linux/common/get_mempolicy.c new file mode 100644 index 0000000..c0d2be5 --- /dev/null +++ b/libc/sysdeps/linux/common/get_mempolicy.c @@ -0,0 +1,21 @@ +/* + * get_mempolicy() for uClibc + * + * Copyright (C) 2010 Will Newton <[email protected]> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <sys/syscall.h> + +#ifdef __NR_get_mempolicy +_syscall5(long, get_mempolicy, int *, __policy, const unsigned long *, __nmask, + unsigned long, __maxnode, void *, __addr, int, __flags) +#else +long get_mempolicy(int *__policy, const unsigned long *__nmask, + unsigned long __maxnode, void *__addr, int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/mbind.c b/libc/sysdeps/linux/common/mbind.c new file mode 100644 index 0000000..2e77698 --- /dev/null +++ b/libc/sysdeps/linux/common/mbind.c @@ -0,0 +1,23 @@ +/* + * mbind() for uClibc + * + * Copyright (C) 2010 Will Newton <[email protected]> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <sys/syscall.h> + +#ifdef __NR_mbind +_syscall6(long, mbind, void *, __start, unsigned long, __len, + int, __mode, const unsigned long *, __nmask, + unsigned long, __maxnode, unsigned int, __flags) +#else +long mbind(void * __start, unsigned long __len, int __mode, + const unsigned long * __nmask, unsigned long __maxnode, + unsigned int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/migrate_pages.c b/libc/sysdeps/linux/common/migrate_pages.c new file mode 100644 index 0000000..cf3aa0d --- /dev/null +++ b/libc/sysdeps/linux/common/migrate_pages.c @@ -0,0 +1,22 @@ +/* + * migrate_pages() for uClibc + * + * Copyright (C) 2010 Will Newton <[email protected]> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <sys/syscall.h> + +#ifdef __NR_migrate_pages +_syscall4(long, migrate_pages, int, __pid, unsigned long, __maxnode, + const unsigned long *, __frommask, const unsigned long *, __tomask) +#else +long migrate_pages(int __pid, unsigned long __maxnode, + const unsigned long * __frommask, + const unsigned long * __tomask) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/move_pages.c b/libc/sysdeps/linux/common/move_pages.c new file mode 100644 index 0000000..e8d99b0 --- /dev/null +++ b/libc/sysdeps/linux/common/move_pages.c @@ -0,0 +1,23 @@ +/* + * move_pages() for uClibc + * + * Copyright (C) 2010 Will Newton <[email protected]> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <sys/syscall.h> + +#ifdef __NR_move_pages +_syscall6(long, move_pages, int, __pid, unsigned long, __count, + void **, __pages, const int *, __nodes, int *, __status, + int, __flags) +#else +long move_pages(int __pid, unsigned long __count, + void ** __pages, const int * __nodes, int * __status, + int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/libc/sysdeps/linux/common/set_mempolicy.c b/libc/sysdeps/linux/common/set_mempolicy.c new file mode 100644 index 0000000..c625041 --- /dev/null +++ b/libc/sysdeps/linux/common/set_mempolicy.c @@ -0,0 +1,21 @@ +/* + * set_mempolicy() for uClibc + * + * Copyright (C) 2010 Will Newton <[email protected]> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <sys/syscall.h> + +#ifdef __NR_set_mempolicy +_syscall3(long, set_mempolicy, int , __mode, const unsigned long *, __nmask, + unsigned long, __maxnode) +#else +long set_mempolicy(int __mode, const unsigned long *__nmask, + unsigned long __maxnode) +{ + __set_errno(ENOSYS); + return -1; +} +#endif -- 1.7.2.2
_______________________________________________ uClibc mailing list [email protected] http://lists.busybox.net/mailman/listinfo/uclibc
