
Hi Tomas,
None of my example code is compile tested...
Regards,
Graeme
On Mon, Aug 27, 2012 at 10:42 PM, Tomas Hlavacek tmshlvck@gmail.com wrote:
Modular early_malloc for DM with support for more heaps and lightweight first heap on stack.
(Not intended for merging!)
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index c3ff789..8563d49 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -84,6 +84,7 @@ 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
void *early_heap_first; /* early heap for early_malloc */
} gd_t;
Probably want to put an #ifdef CONFIG_SYS_EARLY_MALLOC around it. Also, it is a struct early_heap_header *
/* diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index 500e216..ad124c6 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -52,6 +52,7 @@ #include <fdtdec.h> #include <post.h> #include <logbuff.h> +#include <earlymalloc.h>
#ifdef CONFIG_BITBANGMII #include <miiphy.h> @@ -273,6 +274,10 @@ void board_init_f(ulong bootflag)
memset((void *)gd, 0, sizeof(gd_t));
/* Initialize early_malloc */
DECLARE_EARLY_HEAP_ON_STACK;
early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
I'm not a fan of burying the initialiser in a #define, and we already have a precedent of providing a hard-coded address for the chunk of memory (CONFIG_PRE_CON_BUF_ADDR)
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index 5f0b62c..5ff4f42 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -220,6 +220,10 @@ void board_init_f(ulong boot_flags) { gd->flags = boot_flags;
/* Initialize early_malloc */
DECLARE_EARLY_HEAP_ON_STACK;
early_heap_init(gd->early_heap_first, CONFIG_SYS_EARLY_HEAP_SIZE);
do_init_loop(init_sequence_f); /*
early_heap_init() should be called via do_init_loop() - i.e. added to the top of the list and added in init_helpers.c
diff --git a/common/Makefile b/common/Makefile index 2a31c62..744beb8 100644 --- a/common/Makefile +++ b/common/Makefile @@ -188,6 +188,7 @@ COBJS-y += console.o COBJS-y += dlmalloc.o COBJS-y += memsize.o COBJS-y += stdio.o +COBJS-y += earlymalloc.o
Add the CONFIG_SYS_EARLY_MALLOC check here as well
COBJS := $(sort $(COBJS-y)) diff --git a/common/earlymalloc.c b/common/earlymalloc.c new file mode 100644 index 0000000..044b222 --- /dev/null +++ b/common/earlymalloc.c @@ -0,0 +1,91 @@ +/*
- (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 <earlymalloc.h>
+DECLARE_GLOBAL_DATA_PTR;
+void early_heap_init(void *heap, size_t size) +{
struct early_heap_header *h = heap;
h->free_space_pointer = (void *)(roundup((phys_addr_t)heap +
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;
+}
No need for this - see below for my prefered solution...
+void *early_malloc(size_t size) +{
phys_addr_t addr;
struct early_heap_header *h;
/* Align size. */
size = roundup(size, sizeof(phys_addr_t));
/* Choose early_heap with enough space. */
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) {
debug("Early heap overflow. Heap %08lX, free %d, required %d.",
h, h->free_bytes, size);
return NULL;
}
/* Choose block beginning address and mark next free space. */
addr = h->free_space_pointer;
h->free_space_pointer += size;
h->free_bytes -= size;
return (void *)addr;
+}
static struct early_heap_header *def_early_brk(size_t bytes) { struct early_heap_header *h;
if(gd->early_heap_first) return NULL;
/* The default implementation allocates all of the reserved space */ bytes = CONFIG_SYS_EARLY_HEAP_SIZE; gd->early_heap_first = bytes;
h = gd->early_heap_first;
h->free_space_pointer = (void *)(roundup((phys_addr_t)h + sizeof(struct early_heap_header), sizeof(phys_addr_t))); h->free_bytes = bytes - roundup(sizeof(struct early_heap_header), sizeof(phys_addr_t)); h->next_early_heap = NULL;
return h; } struct early_brk *early_brk(size_t bytes) __attribute__((weak, alias("def_early_brk")));
void *early_malloc(size_t size) { phys_addr_t addr; struct early_heap_header *h;
/* Align size. */ size = roundup(size, sizeof(phys_addr_t));
/* Find an early heap chunk with enough space. */ h = gd->early_heap_first; while (h && (h->free_bytes < size)) h = h->next_early_heap;
/* Initialise a new early heap chunk if required*/ if(!h) { h = early_brk(bytes);
if(!h) { debug("Out of early heap\n"); return NULL; } }
/* Choose block beginning address and mark next free space. */ addr = h->free_space_pointer;
h->free_space_pointer += size; h->free_bytes -= size;
return (void *)addr; }
+int early_malloc_isaddress(void *addr) +{
if ((phys_addr_t)addr < (phys_addr_t)gd->early_heap_first)
return 0;
if ((phys_addr_t)addr >= (phys_addr_t)gd->early_heap_first +
CONFIG_SYS_EARLY_HEAP_SIZE)
return 0;
return 1;
+}
I asked about this function before - it does not seem to serve any useful purpose. And even if it did, it does not scan through the chain of early malloc chunks
+int early_malloc_finished(void) +{
return gd->flags & GD_FLG_RELOC;
+}
Again, is this needed? It's not used yet, if it is needed, add it when it is and we can asses if this is the right approach then
diff --git a/include/earlymalloc.h b/include/earlymalloc.h new file mode 100644 index 0000000..3b1fac2 --- /dev/null +++ b/include/earlymalloc.h @@ -0,0 +1,49 @@ +/*
- (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
- */
+#ifndef __INCLUDE_EARLYMALLOC_H +#define __INCLUDE_EARLYMALLOC_H
+#include <linux/stddef.h> /* for size_t */
+struct early_heap_header {
void *free_space_pointer;
size_t free_bytes;
void *next_early_heap;
+};
+void early_heap_init(void *heap, size_t size); +void *early_malloc(size_t size); +int early_malloc_isaddress(void *addr); +int early_malloc_finished(void);
+#ifndef CONFIG_SYS_EARLY_HEAP_SIZE +#define CONFIG_SYS_EARLY_HEAP_SIZE 256 +#endif /* CONFIG_SYS_EARLY_HEAP_SIZE */
+#define DECLARE_EARLY_HEAP_ON_STACK char \
__early_heap[CONFIG_SYS_EARLY_HEAP_SIZE]; \
gd->early_heap_first = (void *)__early_heap
+#endif /* __INCLUDE_EARLYMALLOC_H */
-- 1.7.10.4