[U-Boot] [PATCH v10] Add dmmalloc module for DM.

Mateusz Zalega m.zalega at samsung.com
Tue Nov 5 16:26:25 CET 2013


On 10/29/12 00:20, Tomas Hlavacek wrote:
> Add pointer to the first early heap into GD structure.
> Implement simple early_malloc and early_free functions.
> Prepare for additional heaps and automated heap initialization.
> Add temporary early_malloc_active function (to be replaced in future by
> more coarse DM init flags).
> Add DM specific malloc calls - dmmalloc, dmfree, dmrealloc and dmcalloc.
> 
> Signed-off-by: Tomas Hlavacek <tmshlvck at gmail.com>
> ---
> Changes in v10:
>    - Change GD type to struct early_heap_header *.
>    - Move dmmalloc, dmfree, ... function from .h to dmmalloc.c .
>    - Rework early_malloc_active() to use new GD_FLG_HEAP_INIT flag.
>    - Add early_heap_active() and GD_FLG_EARLY_HEAP_DONE flag.
>    - Rework dmrealloc() and dmfree() to use new flags and support relocation.
>    - Rename early_heap_dump() to early_malloc_heap_dump().
>    - Add early_malloc_dump.
>    - Drop conditional undef CONFIG_SYS_EARLY_MALLOC in dmmalloc.h.
>    - Moved struct early_block_header and macros to dmmalloc.c.
> 
> Changes in v9:
>    - Rework early_malloc to keep track of allocated block size.
>    - Add early_free and dmfree functions.
>    - Rework dmrealloc.
> 
> Changes in v8:
>    - Add dmcalloc() implementation.
>    - Add comments to function prototypes in dmmalloc.h.
> 
> Changes in v7:
>    - Rework check of first heap in early_brk().
> 
> Changes in v6:
>    - Move dmmalloc() and all dm* functions to dmmalloc.h.
>    - Fix bool expression in early_malloc_active().
> 
>  arch/arm/include/asm/global_data.h        |    8 +
>  arch/avr32/include/asm/global_data.h      |    7 +
>  arch/blackfin/include/asm/global_data.h   |    6 +
>  arch/m68k/include/asm/global_data.h       |    8 +
>  arch/microblaze/include/asm/global_data.h |    8 +
>  arch/mips/include/asm/global_data.h       |    6 +
>  arch/nds32/include/asm/global_data.h      |    8 +
>  arch/nios2/include/asm/global_data.h      |    7 +
>  arch/openrisc/include/asm/global_data.h   |    8 +
>  arch/powerpc/include/asm/global_data.h    |    6 +
>  arch/sandbox/include/asm/global_data.h    |    7 +
>  arch/sh/include/asm/global_data.h         |    7 +
>  arch/sparc/include/asm/global_data.h      |    6 +
>  arch/x86/include/asm/global_data.h        |    8 +
>  common/Makefile                           |    1 +
>  common/dmmalloc.c                         |  297 +++++++++++++++++++++++++++++
>  include/asm-generic/global_data_flags.h   |    6 +-
>  include/dmmalloc.h                        |  132 +++++++++++++
>  18 files changed, 534 insertions(+), 2 deletions(-)
>  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 2b9af93..01075dc 100644
> --- a/arch/arm/include/asm/global_data.h
> +++ b/arch/arm/include/asm/global_data.h
> @@ -23,6 +23,11 @@
>  
>  #ifndef	__ASM_GBL_DATA_H
>  #define __ASM_GBL_DATA_H
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory which is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -82,6 +87,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
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
> index bf661e2..ba9cf0e 100644
> --- a/arch/avr32/include/asm/global_data.h
> +++ b/arch/avr32/include/asm/global_data.h
> @@ -22,6 +22,10 @@
>  #ifndef __ASM_GLOBAL_DATA_H__
>  #define __ASM_GLOBAL_DATA_H__
>  
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory wich is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -48,6 +52,9 @@ typedef	struct	global_data {
>  #endif
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h
> index d91e5a4..daeb314 100644
> --- a/arch/blackfin/include/asm/global_data.h
> +++ b/arch/blackfin/include/asm/global_data.h
> @@ -29,6 +29,9 @@
>  #define __ASM_GBL_DATA_H
>  
>  #include <asm/u-boot.h>
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>  
>  /*
>   * The following data structure is placed in some memory wich is
> @@ -57,6 +60,9 @@ typedef struct global_data {
>  
>  	void	**jt;			/* jump table */
>  	char	env_buf[32];		/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
> index 0cdb11c..dad2ba5 100644
> --- a/arch/m68k/include/asm/global_data.h
> +++ b/arch/m68k/include/asm/global_data.h
> @@ -23,6 +23,11 @@
>  
>  #ifndef	__ASM_GBL_DATA_H
>  #define __ASM_GBL_DATA_H
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory wich is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -66,6 +71,9 @@ typedef	struct	global_data {
>  #endif
>  	void		**jt;		/* Standalone app jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
> index 2111c7c..f6609b8 100644
> --- a/arch/microblaze/include/asm/global_data.h
> +++ b/arch/microblaze/include/asm/global_data.h
> @@ -24,6 +24,11 @@
>  
>  #ifndef	__ASM_GBL_DATA_H
>  #define __ASM_GBL_DATA_H
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory wich is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -46,6 +51,9 @@ typedef	struct	global_data {
>  	unsigned long	fb_base;	/* base address of frame buffer */
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
> index a735a8a..c9b76f6 100644
> --- a/arch/mips/include/asm/global_data.h
> +++ b/arch/mips/include/asm/global_data.h
> @@ -25,6 +25,9 @@
>  #define __ASM_GBL_DATA_H
>  
>  #include <asm/regdef.h>
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>  
>  /*
>   * The following data structure is placed in some memory wich is
> @@ -59,6 +62,9 @@ typedef	struct	global_data {
>  	unsigned long	env_valid;	/* Checksum of Environment valid? */
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/nds32/include/asm/global_data.h b/arch/nds32/include/asm/global_data.h
> index b1feb2c..6d972c2 100644
> --- a/arch/nds32/include/asm/global_data.h
> +++ b/arch/nds32/include/asm/global_data.h
> @@ -33,6 +33,11 @@
>  
>  #ifndef	__ASM_GBL_DATA_H
>  #define __ASM_GBL_DATA_H
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory wich is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -63,6 +68,9 @@ typedef	struct global_data {
>  
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
> index 413b485..441e566 100644
> --- a/arch/nios2/include/asm/global_data.h
> +++ b/arch/nios2/include/asm/global_data.h
> @@ -23,6 +23,10 @@
>  #ifndef	__ASM_NIOS2_GLOBALDATA_H_
>  #define __ASM_NIOS2_GLOBALDATA_H_
>  
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  typedef	struct	global_data {
>  	bd_t		*bd;
>  	unsigned long	flags;
> @@ -42,6 +46,9 @@ typedef	struct	global_data {
>  #endif
>  	void		**jt;		/* Standalone app jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/openrisc/include/asm/global_data.h b/arch/openrisc/include/asm/global_data.h
> index 96f3f1c..94fcef1 100644
> --- a/arch/openrisc/include/asm/global_data.h
> +++ b/arch/openrisc/include/asm/global_data.h
> @@ -24,6 +24,11 @@
>  
>  #ifndef __ASM_GBL_DATA_H
>  #define __ASM_GBL_DATA_H
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory wich is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -44,6 +49,9 @@ typedef struct global_data {
>  	unsigned long	fb_base;	/* base address of frame buffer */
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
> index 374fc6d..ed67bfd 100644
> --- a/arch/powerpc/include/asm/global_data.h
> +++ b/arch/powerpc/include/asm/global_data.h
> @@ -26,6 +26,9 @@
>  
>  #include "config.h"
>  #include "asm/types.h"
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>  
>  /*
>   * The following data structure is placed in some memory wich is
> @@ -182,6 +185,9 @@ typedef	struct	global_data {
>  #endif
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
> index 78a751d..0d4b4b0 100644
> --- a/arch/sandbox/include/asm/global_data.h
> +++ b/arch/sandbox/include/asm/global_data.h
> @@ -33,6 +33,10 @@
>   * up the memory controller so that we can use RAM).
>   */
>  
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  typedef	struct global_data {
>  	bd_t		*bd;
>  	unsigned long	flags;
> @@ -46,6 +50,9 @@ typedef	struct global_data {
>  	const void	*fdt_blob;	/* Our device tree, NULL if none */
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h
> index 9a2c193..acacae7 100644
> --- a/arch/sh/include/asm/global_data.h
> +++ b/arch/sh/include/asm/global_data.h
> @@ -27,6 +27,10 @@
>  #ifndef	__ASM_SH_GLOBALDATA_H_
>  #define __ASM_SH_GLOBALDATA_H_
>  
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  typedef	struct global_data
>  {
>  	bd_t		*bd;
> @@ -42,6 +46,9 @@ typedef	struct global_data
>  	unsigned long	env_valid;	/* Checksum of Environment valid */
>  	void		**jt;		/* Standalone app jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h
> index aa63b35..aad97e1 100644
> --- a/arch/sparc/include/asm/global_data.h
> +++ b/arch/sparc/include/asm/global_data.h
> @@ -28,6 +28,9 @@
>  #define __ASM_GBL_DATA_H
>  
>  #include "asm/types.h"
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
>  
>  /*
>   * The following data structure is placed in some memory wich is
> @@ -74,6 +77,9 @@ typedef struct global_data {
>  #endif
>  	void	**jt;			/* jump table */
>  	char	env_buf[32];		/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  #include <asm-generic/global_data_flags.h>
> diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
> index bce999f..9eff403 100644
> --- a/arch/x86/include/asm/global_data.h
> +++ b/arch/x86/include/asm/global_data.h
> @@ -23,6 +23,11 @@
>  
>  #ifndef	__ASM_GBL_DATA_H
>  #define __ASM_GBL_DATA_H
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +#include <dmmalloc.h>
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
>  /*
>   * The following data structure is placed in some memory wich is
>   * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
> @@ -57,6 +62,9 @@ typedef	struct global_data {
>  	unsigned long	reset_status;	/* reset status register at boot */
>  	void		**jt;		/* jump table */
>  	char		env_buf[32];	/* buffer for getenv() before reloc. */
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	struct early_heap_header *early_heap;	/* heap for early_malloc */
> +#endif
>  } gd_t;
>  
>  static inline gd_t *get_fs_gd_ptr(void)
> diff --git a/common/Makefile b/common/Makefile
> index fdfead7..bfb4d7a 100644
> --- a/common/Makefile
> +++ b/common/Makefile
> @@ -209,6 +209,7 @@ COBJS-y += dlmalloc.o
>  COBJS-y += image.o
>  COBJS-y += memsize.o
>  COBJS-y += stdio.o
> +COBJS-$(CONFIG_DM) += dmmalloc.o
>  
>  
>  COBJS	:= $(sort $(COBJS-y))
> diff --git a/common/dmmalloc.c b/common/dmmalloc.c
> new file mode 100644
> index 0000000..4a1a241
> --- /dev/null
> +++ b/common/dmmalloc.c
> @@ -0,0 +1,297 @@
> +/*
> + * (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
> +
> +struct early_block_header {
> +	size_t size;
> +};
> +
> +#define BLOCK_DATA(header) ((void *)(((struct early_block_header *)header)+1))
> +#define BLOCK_HEADER(addr) (((struct early_block_header *)addr)-1)
> +#define BLOCK_USED_FLAG 0x80000000
> +#define BLOCK_SIZE(size) (size & (~BLOCK_USED_FLAG))
> +#define BLOCK_USED(size) ((size & BLOCK_USED_FLAG) == BLOCK_USED_FLAG)
> +#define BLOCK_FREE(size) (!BLOCK_USED(size))
> +#define BLOCK_SET_FREE(size) BLOCK_SIZE(size)
> +#define BLOCK_SET_USED(size) (size | BLOCK_USED_FLAG)
> +
> +
> +__weak struct early_heap_header *early_brk(size_t size)
> +{
> +	struct early_heap_header *h;
> +	struct early_block_header *b;
> +
> +	if (gd->early_heap != NULL)
> +		return NULL;
> +
> +	h = (struct early_heap_header *)CONFIG_SYS_EARLY_HEAP_ADDR;
> +	b = (struct early_block_header *)(h + 1);
> +
> +	size = CONFIG_SYS_EARLY_HEAP_SIZE;
> +	h->size = size;
> +	h->early_heap_next = NULL;
> +	b->size = size - sizeof(struct early_heap_header) -
> +			sizeof(struct early_block_header);
> +	b->size = BLOCK_SET_FREE(b->size);
> +
> +	return h;
> +}
> +
> +static struct early_block_header *find_free_space(struct early_heap_header *h,
> +							size_t size)
> +{
> +	struct early_block_header *b;
> +
> +	b = (struct early_block_header *)(h+1);
> +	while ((phys_addr_t)b + sizeof(struct early_block_header)
> +			< (phys_addr_t)h + h->size) {
> +		if (BLOCK_FREE(b->size) && (BLOCK_SIZE(b->size) >= size))
> +			return b;
> +		b = (struct early_block_header *)((phys_addr_t)b +
> +				sizeof(struct early_block_header) +
> +				BLOCK_SIZE(b->size));
> +	}
> +
> +	return NULL;
> +}
> +
> +static struct early_block_header *split_block(struct early_block_header *b,
> +	       size_t size)
> +{
> +	struct early_block_header *nb;
> +
> +	if ((BLOCK_SIZE(b->size) < size) || (BLOCK_USED(b->size)))
> +		return NULL;
> +
> +	if (BLOCK_SIZE(b->size) <= (size + sizeof(struct early_block_header)))
> +		return b;
> +
> +	nb = (struct early_block_header *)((phys_addr_t)b +
> +		sizeof(struct early_block_header) + size);
> +	nb->size = b->size - size - sizeof(struct early_block_header);
> +	b->size = size;
> +
> +	return b;
> +}
> +
> +void *early_malloc(size_t size)
> +{
> +	struct early_heap_header *h;
> +	struct early_block_header *b;
> +
> +	size = roundup(size, sizeof(phys_addr_t));
> +	if (size == 0)
> +		return NULL;
> +
> +	if (gd->early_heap == NULL)
> +		gd->early_heap = early_brk(size);
> +
> +	if (gd->early_heap == NULL) {
> +		debug("early_brk failed to initialize heap\n");
> +		return NULL;
> +	}
> +
> +	h = gd->early_heap;
> +	while (1) {
> +		b = find_free_space(h, size);
> +		if (b != NULL)
> +			break;
> +
> +		if (h->early_heap_next != NULL)
> +			h = h->early_heap_next;
> +		else
> +			break;
> +	}
> +
> +	if (b == NULL) {
> +		h->early_heap_next = early_brk(size+
> +				sizeof(struct early_heap_header)+
> +				sizeof(struct early_block_header));
> +		h = h->early_heap_next;
> +		if (h == NULL) {
> +			debug("early_brk failed to extend heap by %d B\n",
> +					size);
> +			return NULL;
> +		}
> +
> +		b = find_free_space(h, size);
> +		if (b == NULL) {
> +			debug("early_malloc failed to extend heap by %d B\n",
> +					size);
> +			return NULL;
> +		}
> +	}
> +
> +	if (b->size != size)
> +		b = split_block(b, size);
> +	if (b == NULL) {
> +		debug("early_malloc failed to split block to %d B\n", size);
> +		return NULL;
> +	}
> +
> +	b->size = BLOCK_SET_USED(b->size);
> +
> +	return BLOCK_DATA(b);
> +}
> +
> +void early_free(void *addr)
> +{
> +	struct early_block_header *h = BLOCK_HEADER(addr);
> +	assert(BLOCK_USED(h->size));
> +	h->size = BLOCK_SET_FREE(h->size);
> +}
> +
> +void early_malloc_heap_dump(struct early_heap_header *h)
> +{
> +	struct early_block_header *b;
> +
> +	debug("heap: h=%p, h->size=%d\n", h, h->size);
> +
> +	b = (struct early_block_header *)(h+1);
> +	while ((phys_addr_t)b + sizeof(struct early_block_header)
> +			< (phys_addr_t)h + h->size) {
> +		debug("block: h=%p h->size=%d b=%p b->size=%d b->(used)=%d\n",
> +				h, h->size, b, BLOCK_SIZE(b->size),
> +				BLOCK_USED(b->size));
> +		assert(BLOCK_SIZE(b->size) > 0);
> +		b = (struct early_block_header *)((phys_addr_t)b +
> +				sizeof(struct early_block_header) +
> +				BLOCK_SIZE(b->size));
> +	}
> +	debug("--- heap dump end ---\n");
> +}
> +
> +void early_malloc_dump(void)
> +{
> +	struct early_heap_header *h = gd->early_heap;
> +	while (h != NULL) {
> +		early_malloc_heap_dump(h);
> +		h = h->early_heap_next;
> +	}
> +}
> +
> +static int early_malloc_active(void)
> +{
> +	return ((gd->flags & GD_FLG_HEAP_INIT) != GD_FLG_HEAP_INIT);
> +}
> +
> +static int early_heap_active(void)
> +{
> +	return ((gd->flags & GD_FLG_EARLY_HEAP_DONE) !=
> +			GD_FLG_EARLY_HEAP_DONE);
> +}
> +
> +static int early_address(void *ptr)
> +{
> +	struct early_heap_header *h = gd->early_heap;
> +	while (h != NULL) {
> +		if (((phys_addr_t)ptr >= (phys_addr_t)h) &&
> +				((phys_addr_t)ptr < (phys_addr_t)h + h->size))
> +			return 1;
> +
> +		h = h->early_heap_next;
> +	}
> +
> +	return 0;
> +}
> +
> +
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> +
> +void *dmmalloc(size_t size)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	if (early_malloc_active())
> +		return early_malloc(size);
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +	return malloc(size);
> +}
> +
> +void dmfree(void *ptr)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	if (early_heap_active()) {
> +		if (early_address(ptr))
> +			early_free(ptr);
> +		return;
> +	}
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +	free(ptr);
> +}
> +
> +void *dmcalloc(size_t n, size_t elem_size)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	char *addr;
> +	int size = elem_size * n;
> +
> +	if (early_malloc_active()) {
> +		addr = early_malloc(size);
> +		memset(addr, 0, size);
> +		return addr;
> +	}
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +	return calloc(n, elem_size);
> +}
> +
> +void *dmrealloc(void *oldaddr, size_t bytes)
> +{
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +	char *addr;
> +	struct early_block_header *h;
> +
> +	if (early_heap_active() && early_address(oldaddr)) {
> +		addr = dmmalloc(bytes);
> +		if (addr == NULL)
> +			return NULL;
> +
> +		h = BLOCK_HEADER(oldaddr);
> +		if (BLOCK_FREE(h->size))
> +			return NULL;
> +
> +		if (bytes > BLOCK_SIZE(h->size))
> +			bytes = BLOCK_SIZE(h->size);
> +
> +		memcpy(addr, oldaddr, bytes);
> +		dmfree(oldaddr);
> +		return addr;
> +	}
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +	return realloc(oldaddr, bytes);
> +}
> +
> diff --git a/include/asm-generic/global_data_flags.h b/include/asm-generic/global_data_flags.h
> index bb57fb6..97db2c2 100644
> --- a/include/asm-generic/global_data_flags.h
> +++ b/include/asm-generic/global_data_flags.h
> @@ -13,8 +13,8 @@
>  /*
>   * Global Data Flags
>   *
> - * Note: The low 16 bits are expected for common code.  If your arch
> - *       really needs to add your own, use the high 16bits.
> + * Note: The low 18 bits are expected for common code.  If your arch
> + *       really needs to add your own, use the high 14 bits.
>   */
>  #define GD_FLG_RELOC		0x0001	/* Code was relocated to RAM */
>  #define GD_FLG_DEVINIT		0x0002	/* Devices have been initialized */
> @@ -24,5 +24,7 @@
>  #define GD_FLG_LOGINIT		0x0020	/* Log Buffer has been initialized */
>  #define GD_FLG_DISABLE_CONSOLE	0x0040	/* Disable console (in & out) */
>  #define GD_FLG_ENV_READY	0x0080	/* Environment imported into hash table */
> +#define GD_FLG_HEAP_INIT	0x0100	/* malloc() in RAM is available */
> +#define GD_FLG_EARLY_HEAP_DONE	0x0200	/* early_malloc() heap relocated. */
>  
>  #endif
> diff --git a/include/dmmalloc.h b/include/dmmalloc.h
> new file mode 100644
> index 0000000..c99f423
> --- /dev/null
> +++ b/include/dmmalloc.h
> @@ -0,0 +1,132 @@
> +/*
> + * (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
> + */
> +
> +#ifndef __INCLUDE_DMMALLOC_H
> +#define __INCLUDE_DMMALLOC_H
> +
> +#include <config.h>
> +#include <linux/stddef.h> /* for size_t */
> +#include <malloc.h>
> +
> +#ifdef CONFIG_SYS_EARLY_MALLOC
> +
> +/**
> + * struct early_heap_header - header preceding an early heap
> + * @size - length of the heap in bytes (including the heap header).
> + * @early_heap_next - pointer to the following heap.
> + *
> + * Heaps are organized in the single direction linked list. Each heap
> + * contains own size. Pointer to the first (left-most) heap is
> + * contained in global data.
> + */
> +struct early_heap_header {
> +	size_t size;
> +	void *early_heap_next;
> +};
> +
> +/**
> + * early_brk() - obtain address of the heap
> + * @size:	Minimal size of the new early heap to be allocated.
> + *
> + * Function returns a new heap pointer.
> + *
> + * Allocate and initialize early_heap at least size bytes long.
> + * This function can be platform dependent or board dependent but sensible
> + * default is provided.
> + */
> +struct early_heap_header *early_brk(size_t size);
> +
> +/**
> + * early_malloc() - malloc operating on the early_heap(s)
> + * @size:	Size in bytes.
> + *
> + * Function returns a pointer to the allocated block.
> + */
> +void *early_malloc(size_t size);
> +
> +/**
> + * early_free() - free operating on the early_heap(s)
> + * @addr:	Pointer to the allocated block to be released.
> + */
> +void early_free(void *addr);
> +
> +/**
> + * early_malloc_heap_dump() - print blocks contained in an early_heap
> + * @h:		Address of the early heap.
> + */
> +void early_malloc_heap_dump(struct early_heap_header *h);
> +
> +/**
> + * early_malloc_dump() - print blocks contained in all early_heaps
> + */
> +void early_malloc_dump(void);
> +
> +
> +#endif /* CONFIG_SYS_EARLY_MALLOC */
> +
> +#ifdef CONFIG_DM
> +
> +/*
> + * DM versions of malloc* functions. In early init it calls early_malloc.
> + * It wraps around normal malloc* functions afterwards.
> + */
> +
> +/**
> + * dmmalloc() - malloc working seamlessly in early as well as in RAM stages
> + * @size:	Size of the block to be allocated.
> + *
> + * Function returns an address of the newly allocated block when successful
> + * or NULL otherwise.
> + */
> +void *dmmalloc(size_t size);
> +
> +/**
> + * dmfree() - free working seamlessly in early as well as in RAM stages
> + * @ptr:	Pointer to the allocated block to be released.
> + */
> +void dmfree(void *ptr);
> +
> +/**
> + * dmcalloc() - calloc working seamlessly in early as well as in RAM stages
> + * @n:		Number of elements to be allocated.
> + * @elem_size:	Size of elements to be allocated.
> + *
> + * Function returns a pointer to newly the allocated area (n*elem_size) long.
> + */
> +void *dmcalloc(size_t n, size_t elem_size);
> +
> +/**
> + * dmrealloc() - realloc working seamlessly in early as well as in RAM stages
> + * @oldaddr:	Pointer to the old memory block.
> + * @bytes:	New size to of the block to be reallocated.
> + *
> + * Function returns an address of the newly allocated block when successful
> + * or NULL otherwise.
> + *
> + * Data are copied from the block specified by oldaddr to the new block.
> + */
> +void *dmrealloc(void *oldaddr, size_t bytes);
> +
> +#endif /* CONFIG_DM */
> +#endif /* __INCLUDE_DMMALLOC_H */
> +
> 

*you may stop your scrolling now*

Hello,
does it ring a bell? I need to get it (or an equivalent solution) to
work before implementing a working DM2-I2C uclass. I don't see any
replies to the original v10 e-mail. Why wasn't it accepted into U-Boot?
Should I work on top of this patch, or start from scratch?

Regards,



More information about the U-Boot mailing list