Changed the way, used blocks are managed
git-svn-id: svn://svn.cc65.org/cc65/trunk@3340 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -13,12 +13,19 @@
|
|||||||
; probably not work.
|
; probably not work.
|
||||||
.struct freeblock
|
.struct freeblock
|
||||||
size .word
|
size .word
|
||||||
next .word
|
next .addr
|
||||||
prev .word
|
prev .addr
|
||||||
|
.endstruct
|
||||||
|
|
||||||
|
; Struct usedblock
|
||||||
|
; See notes above
|
||||||
|
.struct usedblock
|
||||||
|
size .word
|
||||||
|
start .addr
|
||||||
.endstruct
|
.endstruct
|
||||||
|
|
||||||
HEAP_ADMIN_SPACE = 2
|
|
||||||
HEAP_MIN_BLOCKSIZE = .sizeof (freeblock) ; Minimum size of an allocated block
|
HEAP_MIN_BLOCKSIZE = .sizeof (freeblock) ; Minimum size of an allocated block
|
||||||
|
HEAP_ADMIN_SPACE = .sizeof (usedblock) ; Additional space for used bocks
|
||||||
|
|
||||||
; Variables
|
; Variables
|
||||||
.global __heaporg
|
.global __heaporg
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* _heap.h
|
* _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 */
|
/* 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.
|
/* The data type used to implement the free list.
|
||||||
* Beware: Field order is significant!
|
* Beware: Field order is significant!
|
||||||
*/
|
*/
|
||||||
struct freeblock {
|
struct freeblock {
|
||||||
unsigned size;
|
unsigned size;
|
||||||
struct freeblock* next;
|
struct freeblock* next;
|
||||||
|
|||||||
@@ -72,23 +72,32 @@
|
|||||||
_free: sta ptr2
|
_free: sta ptr2
|
||||||
stx ptr2+1 ; Save block
|
stx ptr2+1 ; Save block
|
||||||
|
|
||||||
; Is the argument NULL?
|
; Is the argument NULL? If so, bail out.
|
||||||
|
|
||||||
ora ptr2+1 ; Is the argument NULL?
|
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
|
; There's a pointer below the user space that points to the real start of the
|
||||||
; real block allocated. The size of the block is stored in the admin space.
|
; raw block. The first word of the raw block is the total size of the block.
|
||||||
; Remember the block size in ptr1.
|
; Remember the block size in ptr1.
|
||||||
|
|
||||||
lda ptr2
|
@L0: lda ptr2
|
||||||
sub #HEAP_ADMIN_SPACE
|
sub #2
|
||||||
sta ptr2
|
sta ptr2
|
||||||
bcs @L1
|
bcs @L1
|
||||||
dec ptr2+1
|
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
|
lda (ptr2),y ; High byte of size
|
||||||
sta ptr1+1 ; Save it
|
sta ptr1+1 ; Save it
|
||||||
dey
|
dey
|
||||||
lda (ptr2),y
|
lda (ptr2),y
|
||||||
sta ptr1
|
sta ptr1
|
||||||
@@ -261,7 +270,7 @@ _free: sta ptr2
|
|||||||
; }
|
; }
|
||||||
; } else {
|
; } else {
|
||||||
; f->prev = 0;
|
; f->prev = 0;
|
||||||
; /* Special case: This is the new freelist start */
|
; /* Special case: This is the new freelist start */
|
||||||
; _hfirst = f;
|
; _hfirst = f;
|
||||||
; }
|
; }
|
||||||
; }
|
; }
|
||||||
@@ -530,3 +539,4 @@ NoLeftMerge:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -309,17 +309,27 @@ SliceBlock:
|
|||||||
stx ptr2
|
stx ptr2
|
||||||
sta ptr2+1
|
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:
|
FillSizeAndRet:
|
||||||
ldy #freeblock::size ; *p = size;
|
ldy #usedblock::size ; p->size = size;
|
||||||
lda ptr1 ; Low byte of block size
|
lda ptr1 ; Low byte of block size
|
||||||
sta (ptr2),y
|
sta (ptr2),y
|
||||||
iny ; Points to freeblock::size+1
|
iny ; Points to freeblock::size+1
|
||||||
lda ptr1+1
|
lda ptr1+1
|
||||||
sta (ptr2),y
|
sta (ptr2),y
|
||||||
|
|
||||||
RetUserPtr:
|
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;
|
lda ptr2 ; return ++p;
|
||||||
ldx ptr2+1
|
ldx ptr2+1
|
||||||
add #HEAP_ADMIN_SPACE
|
add #HEAP_ADMIN_SPACE
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2002 Ullrich von Bassewitz */
|
/* (C) 1998-2004 Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Wacholderweg 14 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70597 Stuttgart */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@musoftware.de */
|
||||||
@@ -41,9 +41,10 @@
|
|||||||
|
|
||||||
void* __fastcall__ realloc (void* block, size_t size)
|
void* __fastcall__ realloc (void* block, size_t size)
|
||||||
{
|
{
|
||||||
unsigned* b;
|
struct usedblock* b;
|
||||||
unsigned* newblock;
|
struct usedblock* newblock;
|
||||||
unsigned oldsize;
|
unsigned oldsize;
|
||||||
|
unsigned newhptr;
|
||||||
int diff;
|
int diff;
|
||||||
|
|
||||||
/* Check the block parameter */
|
/* Check the block parameter */
|
||||||
@@ -56,7 +57,7 @@ void* __fastcall__ realloc (void* block, size_t size)
|
|||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
/* Block is not NULL, but size is: free the block */
|
/* Block is not NULL, but size is: free the block */
|
||||||
free (block);
|
free (block);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make the internal used size from the given size */
|
/* 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);
|
size = sizeof (struct freeblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a pointer to the real block, get the old block size */
|
/* The word below the user block contains a pointer to the start of the
|
||||||
b = (unsigned*) (((int) block) - 2);
|
* raw memory block. The first word of this raw memory block is the full
|
||||||
oldsize = *b;
|
* 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 */
|
/* Get the size difference as a signed quantity */
|
||||||
diff = size - oldsize;
|
diff = size - oldsize;
|
||||||
|
|
||||||
/* Is the block at the current heap top? */
|
/* 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 */
|
/* Check if we've enough memory at the heap top */
|
||||||
int newhptr;
|
newhptr = ((unsigned) _heapptr) + diff;
|
||||||
newhptr = ((int) _heapptr) + diff;
|
if (newhptr <= ((unsigned) _heapend)) {
|
||||||
if (newhptr <= ((int) _heapend)) {
|
|
||||||
/* Ok, there's space enough */
|
/* Ok, there's space enough */
|
||||||
_heapptr = (unsigned*) newhptr;
|
_heapptr = (unsigned*) newhptr;
|
||||||
*b = size;
|
b->size = size;
|
||||||
|
b->start = b;
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,17 +95,17 @@ void* __fastcall__ realloc (void* block, size_t size)
|
|||||||
*/
|
*/
|
||||||
if (newblock = malloc (size)) {
|
if (newblock = malloc (size)) {
|
||||||
|
|
||||||
/* Adjust the old size to the user visible portion */
|
/* Adjust the old size to the user visible portion */
|
||||||
oldsize -= sizeof (unsigned);
|
oldsize -= HEAP_ADMIN_SPACE;
|
||||||
|
|
||||||
/* If the new block is larger than the old one, copy the old
|
/* If the new block is larger than the old one, copy the old
|
||||||
* data only
|
* data only
|
||||||
*/
|
*/
|
||||||
if (size > oldsize) {
|
if (size > oldsize) {
|
||||||
size = oldsize;
|
size = oldsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the block data */
|
/* Copy the block data */
|
||||||
memcpy (newblock, block, size);
|
memcpy (newblock, block, size);
|
||||||
free (block);
|
free (block);
|
||||||
}
|
}
|
||||||
@@ -109,4 +114,4 @@ void* __fastcall__ realloc (void* block, size_t size)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user