From e55a4bcfd4baaa497ed7dbec7c0769e42cf2e61b Mon Sep 17 00:00:00 2001 From: cuz Date: Sun, 19 Dec 2004 23:09:38 +0000 Subject: [PATCH] Changed the way, used blocks are managed git-svn-id: svn://svn.cc65.org/cc65/trunk@3340 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- asminc/_heap.inc | 13 ++++++++--- include/_heap.h | 16 +++++++++++--- libsrc/common/free.s | 28 +++++++++++++++-------- libsrc/common/malloc.s | 18 +++++++++++---- libsrc/common/realloc.c | 49 +++++++++++++++++++++++------------------ 5 files changed, 83 insertions(+), 41 deletions(-) diff --git a/asminc/_heap.inc b/asminc/_heap.inc index d3b274f9a..97165786c 100644 --- a/asminc/_heap.inc +++ b/asminc/_heap.inc @@ -13,12 +13,19 @@ ; probably not work. .struct freeblock size .word - next .word - prev .word + next .addr + prev .addr +.endstruct + +; Struct usedblock +; See notes above +.struct usedblock + size .word + start .addr .endstruct -HEAP_ADMIN_SPACE = 2 HEAP_MIN_BLOCKSIZE = .sizeof (freeblock) ; Minimum size of an allocated block +HEAP_ADMIN_SPACE = .sizeof (usedblock) ; Additional space for used bocks ; Variables .global __heaporg diff --git a/include/_heap.h b/include/_heap.h index f4019da20..8ac9064c3 100644 --- a/include/_heap.h +++ b/include/_heap.h @@ -1,7 +1,7 @@ /* * _heap.h * - * Ullrich von Bassewitz, 03.06.1998 + * Ullrich von Bassewitz, 1998-06-03, 2004-12-19 * */ @@ -12,12 +12,22 @@ +/* Structure that preceeds a user block in most cases. + * The aligned_malloc function may generate blocks where the start pointer + * and size are splitted to handle a memory hole that is needed for + * alignment. + */ +struct usedblock { + unsigned size; + struct usedblock* start; +}; + /* Space needed for administering used blocks */ -#define HEAP_ADMIN_SPACE sizeof (unsigned) +#define HEAP_ADMIN_SPACE sizeof (struct usedblock) /* The data type used to implement the free list. * Beware: Field order is significant! - */ + */ struct freeblock { unsigned size; struct freeblock* next; diff --git a/libsrc/common/free.s b/libsrc/common/free.s index 8c39bef78..fe119d9ed 100644 --- a/libsrc/common/free.s +++ b/libsrc/common/free.s @@ -72,23 +72,32 @@ _free: sta ptr2 stx ptr2+1 ; Save block -; Is the argument NULL? +; Is the argument NULL? If so, bail out. ora ptr2+1 ; Is the argument NULL? - beq @L9 ; Jump if yes + bne @L0 ; Jump if no + rts ; Bail out if yes -; Decrement the given pointer by the admin space amount, so it points to the -; real block allocated. The size of the block is stored in the admin space. +; There's a pointer below the user space that points to the real start of the +; raw block. The first word of the raw block is the total size of the block. ; Remember the block size in ptr1. - lda ptr2 - sub #HEAP_ADMIN_SPACE +@L0: lda ptr2 + sub #2 sta ptr2 bcs @L1 dec ptr2+1 -@L1: ldy #freeblock::size+1 +@L1: ldy #1 + lda (ptr2),y ; High byte of real block address + tax + dey + lda (ptr2),y + stx ptr2+1 + sta ptr2 ; Set ptr2 to start of real block + + ldy #usedblock::size+1 lda (ptr2),y ; High byte of size - sta ptr1+1 ; Save it + sta ptr1+1 ; Save it dey lda (ptr2),y sta ptr1 @@ -261,7 +270,7 @@ _free: sta ptr2 ; } ; } else { ; f->prev = 0; -; /* Special case: This is the new freelist start */ +; /* Special case: This is the new freelist start */ ; _hfirst = f; ; } ; } @@ -530,3 +539,4 @@ NoLeftMerge: + diff --git a/libsrc/common/malloc.s b/libsrc/common/malloc.s index fa1bd6e7c..c1157a223 100644 --- a/libsrc/common/malloc.s +++ b/libsrc/common/malloc.s @@ -309,17 +309,27 @@ SliceBlock: stx ptr2 sta ptr2+1 -; Fill the size into the admin space of the block and return the user pointer +; Fill the size and start address into the admin space of the block +; (struct usedblock) and return the user pointer FillSizeAndRet: - ldy #freeblock::size ; *p = size; - lda ptr1 ; Low byte of block size + ldy #usedblock::size ; p->size = size; + lda ptr1 ; Low byte of block size sta (ptr2),y - iny ; Points to freeblock::size+1 + iny ; Points to freeblock::size+1 lda ptr1+1 sta (ptr2),y RetUserPtr: + ldy #usedblock::start ; p->start = p + lda ptr2 + sta (ptr2),y + iny + lda ptr2+1 + sta (ptr2),y + +; Return the user pointer, which points behind the struct usedblock + lda ptr2 ; return ++p; ldx ptr2+1 add #HEAP_ADMIN_SPACE diff --git a/libsrc/common/realloc.c b/libsrc/common/realloc.c index baccbf8f2..f46d9a559 100644 --- a/libsrc/common/realloc.c +++ b/libsrc/common/realloc.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2002 Ullrich von Bassewitz */ +/* (C) 1998-2004 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ @@ -41,9 +41,10 @@ void* __fastcall__ realloc (void* block, size_t size) { - unsigned* b; - unsigned* newblock; + struct usedblock* b; + struct usedblock* newblock; unsigned oldsize; + unsigned newhptr; int diff; /* Check the block parameter */ @@ -56,7 +57,7 @@ void* __fastcall__ realloc (void* block, size_t size) if (size == 0) { /* Block is not NULL, but size is: free the block */ free (block); - return 0; + return 0; } /* Make the internal used size from the given size */ @@ -65,22 +66,26 @@ void* __fastcall__ realloc (void* block, size_t size) size = sizeof (struct freeblock); } - /* Get a pointer to the real block, get the old block size */ - b = (unsigned*) (((int) block) - 2); - oldsize = *b; + /* The word below the user block contains a pointer to the start of the + * raw memory block. The first word of this raw memory block is the full + * size of the block. Get a pointer to the real block, get the old block + * size. + */ + b = (((struct usedblock*) block) - 1)->start; + oldsize = b->size; /* Get the size difference as a signed quantity */ diff = size - oldsize; /* Is the block at the current heap top? */ - if (((int) b) + oldsize == ((int) _heapptr)) { + if (((unsigned) b) + oldsize == ((unsigned) _heapptr)) { /* Check if we've enough memory at the heap top */ - int newhptr; - newhptr = ((int) _heapptr) + diff; - if (newhptr <= ((int) _heapend)) { + newhptr = ((unsigned) _heapptr) + diff; + if (newhptr <= ((unsigned) _heapend)) { /* Ok, there's space enough */ _heapptr = (unsigned*) newhptr; - *b = size; + b->size = size; + b->start = b; return block; } } @@ -90,17 +95,17 @@ void* __fastcall__ realloc (void* block, size_t size) */ if (newblock = malloc (size)) { - /* Adjust the old size to the user visible portion */ - oldsize -= sizeof (unsigned); + /* Adjust the old size to the user visible portion */ + oldsize -= HEAP_ADMIN_SPACE; - /* If the new block is larger than the old one, copy the old - * data only - */ - if (size > oldsize) { - size = oldsize; - } + /* If the new block is larger than the old one, copy the old + * data only + */ + if (size > oldsize) { + size = oldsize; + } - /* Copy the block data */ + /* Copy the block data */ memcpy (newblock, block, size); free (block); } @@ -109,4 +114,4 @@ void* __fastcall__ realloc (void* block, size_t size) - +