This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] malloc: use mbind()


From: Joern Engel <joern@purestorage.org>

This explicitly does not use libnuma.  Libnuma itself depends on malloc
and adds very little to a bare mbind().

JIRA: PURE-27597
---
 tpc/malloc2.13/arena.h  | 56 +++++++++++++++++++++++++++++++++++++++++++++----
 tpc/malloc2.13/malloc.c |  2 +-
 2 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/tpc/malloc2.13/arena.h b/tpc/malloc2.13/arena.h
index 0a269715004c..d038565f84d3 100644
--- a/tpc/malloc2.13/arena.h
+++ b/tpc/malloc2.13/arena.h
@@ -306,6 +306,37 @@ ptmalloc_init_minimal (void)
 
 static struct malloc_state *_int_new_arena(size_t size, int numa_node);
 
+static int max_node = -1;
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+
+/*
+ * Wouldn't it be nice to get this with a single syscall instead?
+ */
+static void parse_node_count(void)
+{
+	DIR *d;
+	struct dirent *de;
+
+	d = opendir("/sys/devices/system/node");
+	if (!d) {
+		max_node = 0;
+	} else {
+		while ((de = readdir(d)) != NULL) {
+			int nd;
+			if (strncmp(de->d_name, "node", 4))
+				continue;
+			nd = strtoul(de->d_name + 4, NULL, 0);
+			if (max_node < nd)
+				max_node = nd;
+		}
+		closedir(d);
+	}
+	assert(max_node < MAX_NUMA_NODES);
+}
+
 static void ptmalloc_init(void)
 {
 	const char *s;
@@ -333,7 +364,8 @@ static void ptmalloc_init(void)
 	mutex_init(&main_arena.mutex);
 	main_arena.next = &main_arena;
 	numa_arena[0] = &main_arena;
-	for (i = 1; i < MAX_NUMA_NODES; i++) {
+	parse_node_count();
+	for (i = 1; i <= max_node; i++) {
 		numa_arena[i] = _int_new_arena(0, i);
 		numa_arena[i]->local_next = numa_arena[i];
 		(void)mutex_unlock(&numa_arena[i]->mutex);
@@ -443,9 +475,24 @@ static void *mmap_for_heap(void *addr, size_t length, int *must_clear)
 	return MMAP(addr, length, prot, flags | MAP_NORESERVE);
 }
 
+#include <numaif.h>
+#ifndef MPOL_F_STATIC_NODES
+#define MPOL_F_STATIC_NODES   (1 << 15)
+#endif
+static void mbind_memory(void *mem, size_t size, int node)
+{
+	unsigned long node_mask = 1 << node;
+	int err;
+
+	assert(max_node < sizeof(unsigned long));
+	err = mbind(mem, size, MPOL_PREFERRED, &node_mask, max_node, MPOL_F_STATIC_NODES);
+	if (err)
+		assert(!err);
+}
+
 /* Create a new heap.  size is automatically rounded up to a multiple
    of the page size. */
-static heap_info *new_heap(size_t size, size_t top_pad)
+static heap_info *new_heap(size_t size, size_t top_pad, int numa_node)
 {
 	size_t page_mask = malloc_getpagesize - 1;
 	char *p1, *p2;
@@ -499,6 +546,7 @@ static heap_info *new_heap(size_t size, size_t top_pad)
 			}
 		}
 	}
+	mbind_memory(p2, HEAP_MAX_SIZE, numa_node);
 	if (must_clear)
 		memset(p2, 0, HEAP_MAX_SIZE);
 	h = (heap_info *) p2;
@@ -619,12 +667,12 @@ static struct malloc_state *_int_new_arena(size_t size, int numa_node)
 	char *ptr;
 	unsigned long misalign;
 
-	h = new_heap(size + (sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT), mp_.top_pad);
+	h = new_heap(size + (sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT), mp_.top_pad, numa_node);
 	if (!h) {
 		/* Maybe size is too large to fit in a single heap.  So, just try
 		   to create a minimally-sized arena and let _int_malloc() attempt
 		   to deal with the large request via mmap_chunk().  */
-		h = new_heap(sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT, mp_.top_pad);
+		h = new_heap(sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT, mp_.top_pad, numa_node);
 		if (!h)
 			abort();
 	}
diff --git a/tpc/malloc2.13/malloc.c b/tpc/malloc2.13/malloc.c
index b86f0c3ff65c..461621c11250 100644
--- a/tpc/malloc2.13/malloc.c
+++ b/tpc/malloc2.13/malloc.c
@@ -2859,7 +2859,7 @@ static Void_t* sYSMALLOc(INTERNAL_SIZE_T nb, struct malloc_state * av)
       set_head(old_top, (((char *)old_heap + old_heap->size) - (char *)old_top)
 	       | PREV_INUSE);
     }
-    else if ((heap = new_heap(nb + (MINSIZE + sizeof(*heap)), mp_.top_pad))) {
+    else if ((heap = new_heap(nb + (MINSIZE + sizeof(*heap)), mp_.top_pad, av->numa_node))) {
       /* Use a newly allocated heap.  */
       heap->ar_ptr = av;
       heap->prev = old_heap;
-- 
2.7.0.rc3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]