]> git.sur5r.net Git - cc65/commitdiff
Changed the way, used blocks are managed
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 19 Dec 2004 23:09:38 +0000 (23:09 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 19 Dec 2004 23:09:38 +0000 (23:09 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@3340 b7a2c559-68d2-44c3-8de9-860c34a00d81

asminc/_heap.inc
include/_heap.h
libsrc/common/free.s
libsrc/common/malloc.s
libsrc/common/realloc.c

index d3b274f9a0f7d529464dbdde0b192aca51bd14cb..97165786c0017bdbeb6f87c29e6f68c62b743d92 100644 (file)
 ; 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
index f4019da205fb82d1820d6171a4bd11eb9c65e526..8ac9064c3dcb82050890eeb16d228b1ef3c11901 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * _heap.h
  *
- * Ullrich von Bassewitz, 03.06.1998
+ * Ullrich von Bassewitz, 1998-06-03, 2004-12-19
  *
  */
 
 
 
 
+/* 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;
index 8c39bef78812c894f9b4dce5d1e8e68ffb14e8a4..fe119d9ed9a2fd81ebf2f6b279420da82b7d8e4c 100644 (file)
 _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:
 
 
 
+
index fa1bd6e7c36143c1c762415efe7242fb893ec3b5..c1157a223d9ba9682af2a5c6026c792b1f7bd32f 100644 (file)
@@ -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
index baccbf8f2da8a31906fc5b7c62ba45f3ba15d9d7..f46d9a55967c4ae4276126e373bd75da52d52d0b 100644 (file)
@@ -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                                            */
 
 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)
 
 
 
-                 
+