diff mbox series

malloc: dlmalloc: add an ability for the malloc to be re-init/init multiple times

Message ID 20200429121605.16910-1-marek.bykowski@gmail.com
State Superseded
Headers show
Series malloc: dlmalloc: add an ability for the malloc to be re-init/init multiple times | expand

Commit Message

Marek Bykowski April 29, 2020, 12:16 p.m. UTC
From: Marek Bykowski <marek.bykowski at gmail.com>

Malloc gets initialized with a call to mem_malloc_init() with the address
the allocation starts to and its size. Currently it is not possible to
move the malloc from one memory area to another as the malloc would eventually
fail.

This patch adds in the ability to re-init the malloc with the updated
start address and the size.

One of the use cases of this feature is SPL U-Boot running from within
the static memory and calling to malloc init from within board_init_f():

	arch/arm/cpu/armv8/start.S:reset vector
	arch/arm/cpu/armv8/start.S:main()
	arch/arm/lib/crt0_64.S:board_init_f()
	board/<my_board>/common/spl.c:board_init_f()
        board/<my_board>/common/spl.c:mem_malloc_init((ulong)CONFIG_SYS_SPL_MALLOC_START,
                        CONFIG_SYS_SPL_MALLOC_SIZE);

Shortly after the DDR (main) memory is init and ready we call to malloc init
again but this time with the start address in the DDR memory and a much greater
size we can allow ourselves for moving the allocation off the static to
the DDR memory:

	board/<my_board>/common/spl.c:mem_malloc_init((ulong)CONFIG_SPL_MALLOC_OFFSET,
			CONFIG_SPL_MALLOC_SIZE);

with CONFIG_SYS_SPL_MALLOC_START and CONFIG_SPL_MALLOC_OFFSET being the start
addresses of the malloc in the static and DDR memories respectively and
SZ_16K CONFIG_SYS_SPL_MALLOC_SIZE and SZ_2M CONFIG_SPL_MALLOC_SIZE being
the sizes of the mallocs in the respective memories. Note now we have much
greater memory, from 16K to 2M, available for allocation.

There is an alternative approach already existing in U-Boot with a use of
an early (simplified) malloc and the proper (dlamalloc) malloc however
this approach necessitates managing the two mallocs whereas this one
proposes uses a single dlmalloc.

Signed-off-by: Marek Bykowski <marek.bykowski at gmail.com>
---
 Kconfig           | 14 ++++++++++++++
 common/dlmalloc.c | 41 ++++++++++++++++++++++++++++++++++++++---
 2 files changed, 52 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/Kconfig b/Kconfig
index 1f0904f704..958553c90a 100644
--- a/Kconfig
+++ b/Kconfig
@@ -209,6 +209,20 @@  if EXPERT
 	  When disabling this, please check if malloc calls, maybe
 	  should be replaced by calloc - if one expects zeroed memory.
 
+config SYS_MALLOC_DEFAULT_TO_INIT
+	bool "Default malloc to init while reserving the memory for it"
+	default n
+	help
+	  It may happen that one needs to move the dynamic allocation
+	  from one to another memory range, eg. when moving the malloc
+	  from the limited static to a potentially large dynamic (DDR)
+	  memory.
+
+	  If so then on top of setting the updated memory aside one
+	  needs to bring the malloc init.
+
+	  If such a scenario is sought choose yes.
+
 config TOOLS_DEBUG
 	bool "Enable debug information for tools"
 	help
diff --git a/common/dlmalloc.c b/common/dlmalloc.c
index 6f12a18d54..8b2796e280 100644
--- a/common/dlmalloc.c
+++ b/common/dlmalloc.c
@@ -280,6 +280,7 @@  nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 	    |             Unused space (may be 0 bytes long)                .
 	    .                                                               .
 	    .                                                               |
+
 nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     `foot:' |             Size of chunk, in bytes                           |
 	    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -574,6 +575,10 @@  static void malloc_bin_reloc(void)
 static inline void malloc_bin_reloc(void) {}
 #endif
 
+#ifdef CONFIG_SYS_MALLOC_DEFAULT_TO_INIT
+static void malloc_init(void);
+#endif
+
 ulong mem_malloc_start = 0;
 ulong mem_malloc_end = 0;
 ulong mem_malloc_brk = 0;
@@ -604,6 +609,10 @@  void mem_malloc_init(ulong start, ulong size)
 	mem_malloc_end = start + size;
 	mem_malloc_brk = start;
 
+#ifdef CONFIG_SYS_MALLOC_DEFAULT_TO_INIT
+	malloc_init();
+#endif
+
 	debug("using memory %#lx-%#lx for malloc()\n", mem_malloc_start,
 	      mem_malloc_end);
 #ifdef CONFIG_SYS_MALLOC_CLEAR_ON_INIT
@@ -708,7 +717,36 @@  static unsigned int max_n_mmaps = 0;
 static unsigned long max_mmapped_mem = 0;
 #endif
 
+#ifdef CONFIG_SYS_MALLOC_DEFAULT_TO_INIT
+static void malloc_init(void)
+{
+	int i, j;
+
+	debug("bins (av_ array) are at %p\n", (void *)av_);
+
+	av_[0] = NULL; av_[1] = NULL;
+	for (i = 2, j = 2; i < NAV * 2 + 2; i += 2, j++) {
+		av_[i] = bin_at(j - 2);
+		av_[i + 1] = bin_at(j - 2);
+
+		/* Just print the first few bins so that
+		 * we can see there are alright.
+		 */
+		if (i < 10)
+			debug("av_[%d]=%lx av_[%d]=%lx\n",
+			      i, (ulong)av_[i],
+			      i + 1, (ulong)av_[i + 1]);
+	}
 
+	/* Init the static bookkeeping as well */
+	sbrk_base = (char *)(-1);
+	max_sbrked_mem = 0;
+	max_total_mem = 0;
+#ifdef DEBUG
+	memset((void *)&current_mallinfo, 0, sizeof(struct mallinfo));
+#endif
+}
+#endif
 
 /*
   Debugging support
@@ -1051,9 +1089,6 @@  static mchunkptr mremap_chunk(p, new_size) mchunkptr p; size_t new_size;
 
 #endif /* HAVE_MMAP */
 
-
-
-
 /*
   Extend the top-most chunk by obtaining memory from system.
   Main interface to sbrk (but see also malloc_trim).