[U-Boot] [PATCH v8] [RFC] early_malloc for DM added.
Graeme Russ
graeme.russ at gmail.com
Mon Sep 24 02:00:17 CEST 2012
Hi Tomas,
On Mon, Sep 24, 2012 at 2:15 AM, Tomas Hlavacek <tmshlvck at 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 at 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 at 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
More information about the U-Boot
mailing list