[PATCH] malloc: allow recursion from ptmalloc_init to malloc
Joern Engel
joern@purestorage.com
Tue Jan 26 00:32:00 GMT 2016
numa_node_count() works by essentially counting subdirectories in
/sys/devices/system/node. Completely insane, compared to
_SC_NPROCESSORS_CONF, but apparently that is our interface for now.
On some machines, opendir() allocates memory and recurses back into
malloc. Solve that by initially using main_arena for every node and
allowing the initializing thread to bypass initialization if it
recurses. We do one allocation from main_arena, everything thereafter
should come from numa-local arenas.
JIRA: PURE-35526
---
tpc/malloc2.13/arena.h | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/tpc/malloc2.13/arena.h b/tpc/malloc2.13/arena.h
index 3e6107fbc4a4..7de7436a30ba 100644
--- a/tpc/malloc2.13/arena.h
+++ b/tpc/malloc2.13/arena.h
@@ -302,6 +302,7 @@ static int num_nodes = 0;
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
+#include <sys/syscall.h>
/*
* Wouldn't it be nice to get this with a single syscall instead?
@@ -328,13 +329,26 @@ static int numa_node_count(void)
return ret;
}
+static inline pid_t gettid(void)
+{
+ return syscall(SYS_gettid);
+}
+
static void ptmalloc_init(void)
{
const char *s;
int i, secure = 0;
+ static pid_t init_tid;
if (!__sync_bool_compare_and_swap(&__malloc_initialized, -1, 0)) {
do {
+ if (init_tid == gettid()) {
+ /* We have recursed back into malloc()
+ from ptmalloc_init. At this point
+ we can survive by using the main_arena,
+ so just return. */
+ return;
+ }
sched_yield();
} while (__malloc_initialized <= 0);
return;
@@ -356,7 +370,15 @@ static void ptmalloc_init(void)
#endif /* !defined NO_THREADS */
mutex_init(&main_arena.mutex);
main_arena.next = &main_arena;
+ main_arena.local_next = &main_arena;
main_arena.numa_node = -1;
+
+ /* numa_node_count() can recurse into malloc(). Use main_arena
+ for all numa nodes and set init_tid to allow recursion. */
+ for (i = 0; i < MAX_NUMA_NODES; i++) {
+ numa_arena[i] = &main_arena;
+ }
+ init_tid = gettid();
num_nodes = numa_node_count();
for (i = 0; i < num_nodes; i++) {
numa_arena[i] = _int_new_arena(0, i);
@@ -779,7 +801,6 @@ static struct malloc_state *arena_get2(struct malloc_state *a_tsd, size_t size)
* Calling getcpu() for every allocation is too expensive - but we can turn
* the syscall into a pointer dereference to a kernel shared memory page.
*/
-#include <sys/syscall.h>
static inline int getnode(void)
{
int node, ret;
--
2.7.0.rc3
More information about the Libc-alpha
mailing list