
Hi Tomas,
On Mon, Sep 24, 2012 at 2:15 AM, Tomas Hlavacek tmshlvck@gmail.com wrote:
early_malloc for DM with support for more heaps and lightweight first heap in the same memory as an early stack.
Adaptation layer for seamless calling of early_malloc or dlmalloc from DM based on init stage added (dmmalloc() and related functions).
Signed-off-by: Tomas Hlavacek tmshlvck@gmail.com
Changelog since v5: dmmalloc() and all dm* functions has been moved to header, made static inline and preprocessor-dependent blocks are reworked. early_malloc_active() corrected and made not static. s/CONFIG_SYS_DM/CONFIG_DM/ applied.
Changelog sice v6: Check of first heap emptyness in early_brk() has been simplified.
Changelog since v7: dmcalloc() implmentation added. Comments added to header.
arch/arm/include/asm/global_data.h | 3 + arch/arm/lib/board.c | 8 ++ arch/avr32/include/asm/global_data.h | 3 + arch/avr32/lib/board.c | 9 +++ arch/blackfin/include/asm/global_data.h | 3 + arch/blackfin/lib/board.c | 8 ++ arch/m68k/include/asm/global_data.h | 3 + arch/m68k/lib/board.c | 8 ++ arch/microblaze/include/asm/global_data.h | 3 + arch/microblaze/lib/board.c | 9 +++ arch/mips/include/asm/global_data.h | 3 + arch/mips/lib/board.c | 8 ++ arch/nds32/include/asm/global_data.h | 3 + arch/nds32/lib/board.c | 8 ++ arch/nios2/include/asm/global_data.h | 3 + arch/nios2/lib/board.c | 8 ++ arch/openrisc/include/asm/global_data.h | 3 + arch/openrisc/lib/board.c | 8 ++ arch/powerpc/include/asm/global_data.h | 3 + arch/powerpc/lib/board.c | 8 ++ arch/sandbox/include/asm/global_data.h | 3 + arch/sandbox/lib/board.c | 8 ++ arch/sh/include/asm/global_data.h | 3 + arch/sh/lib/board.c | 8 ++ arch/sparc/include/asm/global_data.h | 3 + arch/sparc/lib/board.c | 8 ++ arch/x86/include/asm/global_data.h | 3 + arch/x86/lib/board.c | 18 +++++ common/Makefile | 1 + common/dmmalloc.c | 88 ++++++++++++++++++++++ include/dmmalloc.h | 117 +++++++++++++++++++++++++++++ 31 files changed, 372 insertions(+) create mode 100644 common/dmmalloc.c create mode 100644 include/dmmalloc.h
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index f8088fe..ef727b0 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -82,6 +82,9 @@ typedef struct global_data { unsigned long post_log_res; /* success of POST test */ unsigned long post_init_f_time; /* When post_init_f started */ #endif +#ifdef CONFIG_SYS_EARLY_MALLOC
void *early_heap_first; /* heap for early_malloc */
+#endif } gd_t;
#include <asm-generic/global_data_flags.h> diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index f1951e8..f73d8b2 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -53,6 +53,10 @@ #include <post.h> #include <logbuff.h>
+#ifdef CONFIG_DM +#include <dmmalloc.h> +#endif
#ifdef CONFIG_BITBANGMII #include <miiphy.h> #endif @@ -281,6 +285,10 @@ void board_init_f(ulong bootflag)
memset((void *)gd, 0, sizeof(gd_t));
+#ifdef CONFIG_SYS_EARLY_MALLOC
gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+#endif /* CONFIG_SYS_EARLY_MALLOC */
I just realised that all these initialisers can be dumped - early_brk() will be called when early_malloc() is first called
[snip]
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index 90cf7fc..a670f9e 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -40,6 +40,10 @@ #include <asm/init_helpers.h> #include <asm/init_wrappers.h>
+#ifdef CONFIG_DM +#include <dmmalloc.h> +#endif
/*
- Breath some life into the board...
@@ -85,6 +89,17 @@ typedef int (init_fnc_t) (void);
/*
- Initialize early heap (when enabled by config).
- */
+#ifdef CONFIG_SYS_EARLY_MALLOC +static void early_malloc_init(void) +{
gd->early_heap_first = early_brk(CONFIG_SYS_EARLY_HEAP_SIZE);
+} +#endif /* CONFIG_SYS_EARLY_MALLOC */
So this uglyness goes
+/*
- init_sequence_f is the list of init functions which are run when U-Boot
- is executing from Flash with a limited 'C' environment. The following
- limitations must be considered when implementing an '_f' function:
@@ -99,6 +114,9 @@ init_fnc_t *init_sequence_f[] = { cpu_init_f, board_early_init_f, env_init, +#ifdef CONFIG_SYS_EARLY_MALLOC
early_malloc_init,
+#endif /* CONFIG_SYS_EARLY_MALLOC */
And this one as well
COBJS := $(sort $(COBJS-y)) diff --git a/common/dmmalloc.c b/common/dmmalloc.c new file mode 100644 index 0000000..6dbb622 --- /dev/null +++ b/common/dmmalloc.c @@ -0,0 +1,88 @@ +/*
- (C) Copyright 2012
- Tomas Hlavacek (tmshlvck@gmail.com)
- See file CREDITS for list of people who contributed to this
- project.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- MA 02111-1307 USA
- */
+#include <common.h> /* for ROUND_UP */ +#include <asm/u-boot.h> +#include <asm/global_data.h> /* for gd_t and gd */ +#include <asm/types.h> /* for phys_addr_t and size_addt_t */
+#include <dmmalloc.h> +#include <malloc.h>
+#include <linux/compiler.h>
+DECLARE_GLOBAL_DATA_PTR;
+#ifdef CONFIG_SYS_EARLY_MALLOC +__weak struct early_heap_header *early_brk(size_t size) +{
struct early_heap_header *h =
(struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
if (gd->early_heap_first != NULL)
return NULL;
if (gd->early_heap_first != NULL) { debug("Early Heap: Failed to allocate %d byte block of early heap.\n", size); return NULL; }
h->free_space_pointer = (void *)(roundup(
(phys_addr_t)CONFIG_SYS_EARLY_HEAP_ADDR +
sizeof(struct early_heap_header),
sizeof(phys_addr_t)));
h->free_bytes = size - roundup(sizeof(struct early_heap_header),
sizeof(phys_addr_t));
h->next_early_heap = NULL;
return h;
+}
+void *early_malloc(size_t size) +{
phys_addr_t addr;
struct early_heap_header *h;
size = roundup(size, sizeof(phys_addr_t));
h = gd->early_heap_first;
while ((h->free_bytes < size) && (h->next_early_heap != NULL))
h = h->next_early_heap;
if (h->free_bytes < size) {
h->next_early_heap = early_brk(size);
if (h->next_early_heap == NULL)
debug("EH overflow. Can not early_brk. required %d B.",
size);
return NULL;
Missing brace and not using the newly allocated block
}
addr = (phys_addr_t)h->free_space_pointer;
h->free_space_pointer += size;
h->free_bytes -= size;
return (void *)addr;
+}
This is still NULL pointer exception prone, for example calling dmmalloc() before the initialisation function in board.c is called.
void *early_malloc(size_t size) { phys_addr_t addr; struct early_heap_header *h;
size = roundup(size, sizeof(phys_addr_t));
/* Initialise first block of early heap (if not already done) */ if (!gd->early_heap_first) { gd->early_heap_first = early_brk(size);
if (!gd->early_heap_first) return NULL; }
/* Find an early heap block with enough free space */ h = gd->early_heap_first;
while ((h->free_bytes < size) && (h->next_early_heap != NULL)) h = h->next_early_heap;
/* Initialise another block of early heap if neccessary */ if (h->free_bytes < size) { h->next_early_heap = early_brk(size);
if (!h->next_early_heap) return NULL;
/* Use the newly allocated block */ h = h->next_early_heap; }
addr = (phys_addr_t)h->free_space_pointer;
h->free_space_pointer += size; h->free_bytes -= size;
return (void *)addr; }
Regards,
Graeme