[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