[syslinux:elflink] elflink: move realloc() to core/mem/malloc.c

syslinux-bot for Feng Tang feng.tang at intel.com
Thu Aug 12 21:03:24 PDT 2010


Commit-ID:  79459f631546eea83d4158f535c20ebd4ac18987
Gitweb:     http://syslinux.zytor.com/commit/79459f631546eea83d4158f535c20ebd4ac18987
Author:     Feng Tang <feng.tang at intel.com>
AuthorDate: Thu, 24 Jun 2010 15:10:56 +0800
Committer:  Feng Tang <feng.tang at intel.com>
CommitDate: Tue, 20 Jul 2010 11:10:04 +0800

elflink: move realloc() to core/mem/malloc.c

* remove most of the functinal codes from com32 malloc/realloc code
* next step will be remove those codes from com32
* one left item is posix memalign problem and memory tag problem
  which is usded by elf module load code


---
 com32/lib/free.c    |    2 +-
 com32/lib/malloc.c  |    2 +-
 com32/lib/realloc.c |    2 +
 core/mem/init.c     |   42 +++++++++++++-----
 core/mem/malloc.c   |  113 ++++++++++++++++++++++++++++++++++++++++++++++++---
 core/mem/malloc.h   |   40 +++++++++---------
 6 files changed, 161 insertions(+), 40 deletions(-)

diff --git a/com32/lib/free.c b/com32/lib/free.c
index f58e981..564b70e 100644
--- a/com32/lib/free.c
+++ b/com32/lib/free.c
@@ -9,6 +9,7 @@
 
 #include <stdio.h>
 
+#if 0
 static struct free_arena_header *__free_block(struct free_arena_header *ah)
 {
     struct free_arena_header *pah, *nah;
@@ -64,7 +65,6 @@ static struct free_arena_header *__free_block(struct free_arena_header *ah)
  * free list.  Only the a.size field of the arena header is assumed
  * to be valid.
  */
-#if 0
 void __inject_free_block(struct free_arena_header *ah)
 {
     struct free_arena_header *nah;
diff --git a/com32/lib/malloc.c b/com32/lib/malloc.c
index c78d210..4a86f64 100644
--- a/com32/lib/malloc.c
+++ b/com32/lib/malloc.c
@@ -14,6 +14,7 @@
 
 #include <stdio.h>
 
+#if 0
 struct free_arena_header __malloc_head = {
     {
      ARENA_TYPE_HEAD,
@@ -147,7 +148,6 @@ static void *__malloc_from_block(struct free_arena_header *fp, size_t size)
     return (void *)(&fp->a + 1);
 }
 
-#if 0
 void *malloc(size_t size)
 {
     struct free_arena_header *fp;
diff --git a/com32/lib/realloc.c b/com32/lib/realloc.c
index 2969e31..3d3c10f 100644
--- a/com32/lib/realloc.c
+++ b/com32/lib/realloc.c
@@ -8,6 +8,7 @@
 
 #include "malloc.h"
 
+#if 0
 void *realloc(void *ptr, size_t size)
 {
     struct free_arena_header *ah, *nah;
@@ -96,3 +97,4 @@ void *realloc(void *ptr, size_t size)
 	}
     }
 }
+#endif
diff --git a/core/mem/init.c b/core/mem/init.c
index 4e08d10..be4f312 100644
--- a/core/mem/init.c
+++ b/core/mem/init.c
@@ -9,8 +9,6 @@
 struct free_arena_header __core_malloc_head[NHEAP];
 
 static __hugebss char main_heap[128 << 10];
-/* change it to 32M */
-//static __hugebss char main_heap[32 << 20];
 extern char __lowmem_heap[];
 extern char free_high_memory[];
 
@@ -20,14 +18,16 @@ int scan_highmem_area(void *data, addr_t start, addr_t len, bool is_ram)
 	struct free_arena_header *fp;
 	addr_t end;
 
-	mp("start = %x, len = %x, is_ram = %d\n", start, len, is_ram);
+	mp("start = %x, len = %x, is_ram = %d", start, len, is_ram);
 
 	if (start < 0x100000 || start > E820_MEM_MAX
 			     || !is_ram)
 		return 0;
 
-	if (start < __com32.cs_memsize)
+	if (start < __com32.cs_memsize) {
+		len -= __com32.cs_memsize - start;
 		start = __com32.cs_memsize;
+	}
 	if (len > E820_MEM_MAX - start)
 		len = E820_MEM_MAX - start;
 	end = start + len;
@@ -44,6 +44,26 @@ int scan_highmem_area(void *data, addr_t start, addr_t len, bool is_ram)
 	return 0;
 }
 
+static void mpool_dump(enum heap heap)
+{
+	struct free_arena_header *head = &__core_malloc_head[heap];
+	struct free_arena_header *fp;
+	void *p = NULL;
+	int size, type, i = 0;
+	addr_t start, end;
+
+	fp = head->next_free;
+	while (fp != head) {
+		size = ARENA_SIZE_GET(fp->a.attrs);
+		type = ARENA_TYPE_GET(fp->a.attrs);
+		start = (addr_t)fp;
+		end = start + size;
+		printf("area[%d]: start = 0x%08x, end = 0x%08x, type = %d\n",
+			i++, start, end, type);
+		fp = fp->next_free;
+	}
+}
+
 void mem_init(void)
 {
 	struct free_arena_header *fp;
@@ -61,7 +81,10 @@ void mem_init(void)
 	fp++;
 	}
 
-	//mp("__lowmem_heap = 0x%p bios_free = 0x%p", __lowmem_heap, *bios_free_mem);
+	/*
+	mp("__lowmem_heap = 0x%p bios_free = 0x%p",
+		__lowmem_heap, *bios_free_mem);
+	*/
 	/* Initialize the lowmem heap */
 	fp = (struct free_arena_header *)__lowmem_heap;
 	fp->a.attrs = ARENA_TYPE_USED | (HEAP_LOWMEM << ARENA_HEAP_POS);
@@ -69,13 +92,8 @@ void mem_init(void)
 	__inject_free_block(fp);
 
 	/* Initialize the main heap */
-	/*
-	fp = (struct free_arena_header *)main_heap;
-	fp->a.attrs = ARENA_TYPE_USED | (HEAP_MAIN << ARENA_HEAP_POS);
-	ARENA_SIZE_SET(fp->a.attrs, sizeof main_heap);
-	__inject_free_block(fp);
-	*/
-
 	__com32.cs_memsize = free_high_memory;
 	syslinux_scan_memory(scan_highmem_area, NULL);
+
+	//mpool_dump(HEAP_MAIN);
 }
diff --git a/core/mem/malloc.c b/core/mem/malloc.c
index 0f41960..c1c9296 100644
--- a/core/mem/malloc.c
+++ b/core/mem/malloc.c
@@ -4,13 +4,14 @@
  * Very simple linked-list based malloc()/free().
  */
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
 #include <dprintf.h>
-#include "malloc.h"
+#include <minmax.h>
 
-#include <stdio.h>
+#include "malloc.h"
 
 static void *__malloc_from_block(struct free_arena_header *fp,
 				 size_t size, malloc_tag_t tag)
@@ -64,10 +65,10 @@ static void *_malloc(size_t size, enum heap heap, malloc_tag_t tag)
     struct free_arena_header *fp;
     struct free_arena_header *head = &__core_malloc_head[heap];
     void *p = NULL;
+    static once = 0;
 
-    //mp("_malloc(%zu, %u, %u) @ %p = ",
     dprintf("_malloc(%zu, %u, %u) @ %p = ",
-	    size, heap, tag, __builtin_return_address(0));
+	size, heap, tag, __builtin_return_address(0));
 
     if (size) {
 	/* Add the obligatory arena header, and round up */
@@ -82,8 +83,7 @@ static void *_malloc(size_t size, enum heap heap, malloc_tag_t tag)
         }
     }
 
-    //dprintf("%p\n", p);
-    //printf("%p\n", p);
+    dprintf("%p\n", p);
     return p;
 }
 
@@ -106,3 +106,104 @@ void *pmapi_lmalloc(size_t size)
 {
     return _malloc(size, HEAP_LOWMEM, MALLOC_MODULE);
 }
+
+void *realloc(void *ptr, size_t size)
+{
+    struct free_arena_header *ah, *nah;
+    struct free_arena_header *head;
+	
+    void *newptr;
+    size_t newsize, oldsize, xsize;
+
+    if (!ptr)
+	return malloc(size);
+
+    if (size == 0) {
+	free(ptr);
+	return NULL;
+    }
+
+    ah = (struct free_arena_header *)
+	((struct arena_header *)ptr - 1);
+
+	head = &__core_malloc_head[ARENA_HEAP_GET(ah->a.attrs)];
+
+    /* Actual size of the old block */
+    //oldsize = ah->a.size;
+    oldsize = ARENA_SIZE_GET(ah->a.attrs);
+
+    /* Add the obligatory arena header, and round up */
+    newsize = (size + 2 * sizeof(struct arena_header) - 1) & ARENA_SIZE_MASK;
+
+    if (oldsize >= newsize && newsize >= (oldsize >> 2) &&
+	oldsize - newsize < 4096) {
+	/* This allocation is close enough already. */
+	return ptr;
+    } else {
+	xsize = oldsize;
+
+	nah = ah->a.next;
+	if ((char *)nah == (char *)ah + ARENA_SIZE_GET(ah->a.attrs) &&
+		ARENA_TYPE_GET(nah->a.attrs) == ARENA_TYPE_FREE &&
+		ARENA_SIZE_GET(nah->a.attrs) + oldsize >= newsize) {
+	    //nah->a.type == ARENA_TYPE_FREE &&
+	    //oldsize + nah->a.size >= newsize) {
+	    /* Merge in subsequent free block */
+	    ah->a.next = nah->a.next;
+	    ah->a.next->a.prev = ah;
+	    nah->next_free->prev_free = nah->prev_free;
+	    nah->prev_free->next_free = nah->next_free;
+	    ARENA_SIZE_SET(ah->a.attrs, ARENA_SIZE_GET(nah->a.attrs));
+	    xsize = ARENA_SIZE_GET(ah->a.attrs);
+	    //xsize = (ah->a.size += nah->a.size);
+	}
+
+	if (xsize >= newsize) {
+	    /* We can reallocate in place */
+	    if (xsize >= newsize + 2 * sizeof(struct arena_header)) {
+		/* Residual free block at end */
+		nah = (struct free_arena_header *)((char *)ah + newsize);
+		ARENA_TYPE_SET(nah->a.attrs, ARENA_TYPE_FREE);
+		ARENA_SIZE_SET(nah->a.attrs, xsize - newsize);
+		ARENA_SIZE_SET(ah->a.attrs, newsize);
+		//nah->a.type = ARENA_TYPE_FREE;
+		//nah->a.size = xsize - newsize;
+		//ah->a.size = newsize;
+
+		/* Insert into block list */
+		nah->a.next = ah->a.next;
+		ah->a.next = nah;
+		nah->a.next->a.prev = nah;
+		nah->a.prev = ah;
+
+		/* Insert into free list */
+		if (newsize > oldsize) {
+		    /* Hack: this free block is in the path of a memory object
+		       which has already been grown at least once.  As such, put
+		       it at the *end* of the freelist instead of the beginning;
+		       trying to save it for future realloc()s of the same block. */
+		    nah->prev_free = head->prev_free;
+		    nah->next_free = head;
+		    head->prev_free = nah;
+		    nah->prev_free->next_free = nah;
+		} else {
+		    nah->next_free = head->next_free;
+		    nah->prev_free = head;
+		    head->next_free = nah;
+		    nah->next_free->prev_free = nah;
+		}
+   	    }
+	    /* otherwise, use up the whole block */
+	    return ptr;
+	} else {
+	    /* Last resort: need to allocate a new block and copy */
+	    oldsize -= sizeof(struct arena_header);
+	    newptr = malloc(size);
+	    if (newptr) {
+		memcpy(newptr, ptr, min(size, oldsize));
+		free(ptr);
+	    }
+	    return newptr;
+	}
+    }
+}
diff --git a/core/mem/malloc.h b/core/mem/malloc.h
index 8791349..3291cc2 100644
--- a/core/mem/malloc.h
+++ b/core/mem/malloc.h
@@ -20,6 +20,18 @@ enum malloc_owner {
     MALLOC_MODULE,
 };
 
+enum arena_type {
+    ARENA_TYPE_USED = 0,
+    ARENA_TYPE_FREE = 1,
+    ARENA_TYPE_HEAD = 2,
+    ARENA_TYPE_DEAD = 3,
+};
+enum heap {
+    HEAP_MAIN,
+    HEAP_LOWMEM,
+    NHEAP
+};
+
 struct free_arena_header;
 
 /*
@@ -34,16 +46,14 @@ struct arena_header {
     struct free_arena_header *next, *prev;
 };
 
-enum arena_type {
-    ARENA_TYPE_USED = 0,
-    ARENA_TYPE_FREE = 1,
-    ARENA_TYPE_HEAD = 2,
-    ARENA_TYPE_DEAD = 3,
-};
-enum heap {
-    HEAP_MAIN,
-    HEAP_LOWMEM,
-    NHEAP
+/*
+ * This structure should be no more than twice the size of the
+ * previous structure.
+ */
+struct free_arena_header {
+    struct arena_header a;
+    struct free_arena_header *next_free, *prev_free;
+    size_t _pad[2];		/* Pad to 2*sizeof(struct arena_header) */
 };
 
 #define ARENA_SIZE_MASK (~(uintptr_t)(sizeof(struct arena_header)-1))
@@ -68,15 +78,5 @@ enum heap {
 	((attrs) = ((attrs) & ~ARENA_TYPE_MASK) | \
 	 ((type) & ARENA_TYPE_MASK))
 
-/*
- * This structure should be no more than twice the size of the
- * previous structure.
- */
-struct free_arena_header {
-    struct arena_header a;
-    struct free_arena_header *next_free, *prev_free;
-    size_t _pad[2];		/* Pad to 2*sizeof(struct arena_header) */
-};
-
 extern struct free_arena_header __core_malloc_head[NHEAP];
 void __inject_free_block(struct free_arena_header *ah);



More information about the Syslinux-commits mailing list