This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] malloc: use mbind()
- From: Joern Engel <joern at purestorage dot com>
- To: "GNU C. Library" <libc-alpha at sourceware dot org>
- Cc: Siddhesh Poyarekar <siddhesh dot poyarekar at gmail dot com>, Joern Engel <joern at purestorage dot org>
- Date: Mon, 25 Jan 2016 16:24:57 -0800
- Subject: [PATCH] malloc: use mbind()
- Authentication-results: sourceware.org; auth=none
- References: <1453767942-19369-1-git-send-email-joern at purestorage dot com>
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