delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/05/27/18:24:27.1

From: "Mark E." <snowball3 AT bigfoot DOT com>
To: djgpp-workers AT delorie DOT com
Date: Sun, 27 May 2001 18:24:11 -0400
MIME-Version: 1.0
Subject: realloc patch
Message-ID: <3B11464B.28287.D7FE4@localhost>
X-mailer: Pegasus Mail for Win32 (v3.12c)
Reply-To: djgpp-workers AT delorie DOT com

This patch should be done barring any problems discovered during this review.

Index: malloc.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdlib/malloc.c,v
retrieving revision 1.8
diff -c -p -r1.8 malloc.c
*** malloc.c	2001/01/20 04:09:57	1.8
--- malloc.c	2001/05/27 22:12:12
*************** malloc(size_t size)
*** 217,228 ****
    RET(rv);
  }
  
! static inline BLOCK *
! merge(BLOCK *a, BLOCK *b, BLOCK *c)
  {
    int bu;
    BLOCK *bp, **bpp;
  
  #if DEBUG
    printf("  merge %u/%08x + %u/%08x = %u\n",
  	 a->size, a, b->size, b, a->size+b->size+8);
--- 217,262 ----
    RET(rv);
  }
  
! /* Remove block of memory from the free list.  */
! static inline void
! simple_snip_freelist (BLOCK *b)
  {
    int bu;
    BLOCK *bp, **bpp;
  
+   bu = b2bucket(b);
+ #if DEBUG
+   printf("bucket for %u/%08x is %d\n", b->size, b, bu);
+ #endif
+   bpp = freelist + bu;
+   for (bp = freelist[bu]; bp; bpp=&(bp->next), bp=bp->next)
+   {
+ #if DEBUG
+     printf("  %08x", bp);
+ #endif
+     if (bp == b)
+     {
+ #if DEBUG
+       printf("\n  snipping %u/%08x from freelist[%d]\n", bp->size, bp, bu);
+ #endif
+       *bpp = bp->next;
+       break;
+     }
+   }
+ }
+ 
+ /* Insert block of memory into free list.  */
+ static inline void
+ insert_freelist(BLOCK *block)
+ {
+   int bu = b2bucket(block);
+   block->next = freelist[bu];
+   freelist[bu] = block;
+ }
+ 
+ static inline BLOCK *
+ merge(BLOCK *a, BLOCK *b, BLOCK *c)
+ {
  #if DEBUG
    printf("  merge %u/%08x + %u/%08x = %u\n",
  	 a->size, a, b->size, b, a->size+b->size+8);
*************** merge(BLOCK *a, BLOCK *b, BLOCK *c)
*** 238,262 ****
  #endif
      slop = 0;
    }
!   bu = b2bucket(c);
! #if DEBUG
!   printf("bucket for %u/%08x is %d\n", c->size, c, bu);
! #endif
!   bpp = freelist+bu;
!   for (bp=freelist[bu]; bp; bpp=&(bp->next), bp=bp->next)
!   {
! #if DEBUG
!     printf("  %08x", bp);
! #endif
!     if (bp == c)
!     {
! #if DEBUG
!       printf("\n  snipping %u/%08x from freelist[%d]\n", bp->size, bp, bu);
! #endif
!       *bpp = bp->next;
!       break;
!     }
!   }
    CHECK(c);
  
    a->size += b->size + 8;
--- 272,279 ----
  #endif
      slop = 0;
    }
!   else
!     simple_snip_freelist(c);
    CHECK(c);
  
    a->size += b->size + 8;
*************** merge(BLOCK *a, BLOCK *b, BLOCK *c)
*** 270,276 ****
  void
  free(void *ptr)
  {
-   int b;
    BLOCK *block;
    if (ptr == 0)
      return;
--- 287,292 ----
*************** free(void *ptr)
*** 309,321 ****
      block = merge(block, AFTER(block), AFTER(block));
    }
    CHECK(block);
!   
!   b = b2bucket(block);
!   block->next = freelist[b];
!   freelist[b] = block;
    CHECK(block);
  }
  
  void *
  realloc(void *ptr, size_t size)
  {
--- 325,397 ----
      block = merge(block, AFTER(block), AFTER(block));
    }
    CHECK(block);
! 
!   insert_freelist(block);
    CHECK(block);
  }
  
+ /* Try to increase the size of the allocated block. */
+ static BLOCK *
+ realloc_inplace(BLOCK *cur, size_t old_size, size_t new_size)
+ {
+   BLOCK *after;
+   size_t after_sz, alloc_delta;
+   int extra_space;
+   char is_slop_ptr;
+   
+   after = AFTER(cur);
+   after_sz = after->size;
+   new_size = (new_size + (ALIGN-1)) & ~(ALIGN-1);
+ 
+   /* Fail if the block following the one being extended is in use.  */
+   if (after_sz & 1)
+     return NULL;
+ 
+   /* Size of block increase.  */
+   alloc_delta = new_size - old_size;
+ 
+   /* Fail if the free block is not large enough.  */
+   if (alloc_delta > after_sz)
+     return NULL;
+ 
+   extra_space = (after_sz - alloc_delta);
+   is_slop_ptr = (after == slop);
+ 
+   if (!is_slop_ptr)
+   {
+     /* Remove the block from free list.  */
+     after->bucket = -1;
+     simple_snip_freelist(after);
+   }
+ 
+   /* Expand the block by shrinking or mergin
+      with the free block that follows it.  */
+   if (extra_space > 8)
+   {
+     /* Take part of the free block (or slop) and
+        give to the block being expanded.  */
+     BLOCK *after2 = (BLOCK *)((char *)after + alloc_delta);
+     after2->size = after_sz - alloc_delta;
+     after2->bucket = -1;
+     ENDSZ(after2) = after2->size;
+     cur->size += alloc_delta;
+     ENDSZ(cur) = cur->size;
+     if (is_slop_ptr)
+       slop = after2;
+     else
+       insert_freelist(after2);
+   }
+   else
+   {
+     /* Merge the entire free block with the block being expanded.  */
+     cur->size += after_sz + 8;
+     ENDSZ(cur) = cur->size;
+     if (is_slop_ptr)
+       slop = 0;
+   }
+   return cur;
+ }
+ 
  void *
  realloc(void *ptr, size_t size)
  {
*************** realloc(void *ptr, size_t size)
*** 337,342 ****
--- 413,422 ----
        return ptr;
      copysize = size;
    }
+ 
+   /* Try to increase the size of the allocation by extending the block.  */
+   if (realloc_inplace(b, copysize, size))
+     return ptr;
  
    newptr = (char *)malloc(size);
  #if DEBUG

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019