delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/05/24/15:02:50

From: "Mark E." <snowball3 AT bigfoot DOT com>
To: djgpp-workers AT delorie DOT com
Date: Thu, 24 May 2001 15:01:20 -0400
MIME-Version: 1.0
Subject: Re: ehhanced realloc test program
Message-ID: <3B0D2240.25662.FBD929@localhost>
References: <3B0BFD5F DOT 25329 DOT 475F21 AT localhost>
In-reply-to: <Pine.SUN.3.91.1010524094916.17472N-100000@is>
X-mailer: Pegasus Mail for Win32 (v3.12c)
Reply-To: djgpp-workers AT delorie DOT com

> Please post the patched realloc in its entirety (it is easier to grasp 
> that way), including its immediate subroutines that you wrote.

What I have isn't in final form yet but it works.

/* Remove block of memory from the free list.  */
static inline void
remove_freelist (BLOCK *b)
{
  int bu;
  BLOCK *bp, **bpp;

  bu = b2bucket (b);
  bpp = freelist + bu;
  for (bp = freelist[bu]; bp; bpp=&(bp->next), bp=bp->next)
  {
    if (bp == b)
    {
      *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;
}

/* 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 split_extra;

  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;

  after->bucket = -1;

  /* Is there enough leftover space to form a new block?  */
  split_extra = (after_sz - alloc_delta >= 16);

  if (after == slop)
  {
    if (split_extra)
      slop = split_block(after, alloc_delta);
    else
      slop = 0;
  }
  else
  {
    remove_freelist(after);
    if (split_extra)
    {
      BLOCK *after2 = split_block(after, alloc_delta);
      after2->bucket = -1;
      insert_freelist(after2);
    }
  }

  cur->size += after->size + 8;
  ENDSZ(cur) = cur->size;

  return cur;
}

void *
realloc(void *ptr, size_t size)
{
  BLOCK *b;
  char *newptr;
  size_t copysize;

  if (ptr == 0)
    return malloc(size);

  b = (BLOCK *)((char *)ptr-4);
  copysize = b->size & ~1;
  if (size <= copysize)
  {
#if 0
    if (copysize < 2*MIN_SAVE_EXTRA
 || (size >= copysize-512 && size >= copysize/2))
#endif
      return ptr;
    copysize = size;
  }

  /* Try to increase the size of the allocation.  */
  if (realloc_inplace (b, copysize, size))
    return ptr;

  newptr = (char *)malloc(size);
#if DEBUG
  printf("realloc %u %u/%08x %08x->%08, %u\n",
  size, b->size & ~1, b, ptr, newptr, copysize);
#endif
  if (!newptr)
    return NULL;
  memcpy(newptr, ptr, copysize);
  free(ptr);
  return newptr;
}


- Raw text -


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