[PATCH] libc: Add support for NUMA system calls.

Will Newton will.newton at gmail.com
Wed Sep 15 15:15:28 UTC 2010


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 <will.newton at imgtec.com>
---

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 <will.newton at gmail.com>
+ *
+ * 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 <will.newton at gmail.com>
+ *
+ * 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 <will.newton at gmail.com>
+ *
+ * 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 <will.newton at gmail.com>
+ *
+ * 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 <will.newton at gmail.com>
+ *
+ * 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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-libc-Add-support-for-NUMA-system-calls.patch
Type: text/x-patch
Size: 9065 bytes
Desc: not available
URL: <http://lists.busybox.net/pipermail/uclibc/attachments/20100915/67e3e7f0/attachment-0001.bin>


More information about the uClibc mailing list