static void *AcquireBlock(size_t size)
{
  register size_t
    i;

  register void
    *block;

  /*
    Find free block.
  */
  size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
  i=AllocationPolicy(size);
  block=memory_pool.blocks[i];
  while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
    block=NextBlockInList(block);
  if (block == (void *) NULL)
    {
      i++;
      while (memory_pool.blocks[i] == (void *) NULL)
        i++;
      block=memory_pool.blocks[i];
      if (i >= MaxBlocks)
        return((void *) NULL);
    }
  assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
  assert(SizeOfBlock(block) >= size);
  RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
  if (SizeOfBlock(block) > size)
    {
      size_t
        blocksize;

      void
        *next;

      /*
        Split block.
      */
      next=(char *) block+size;
      blocksize=SizeOfBlock(block)-size;
      *BlockHeader(next)=blocksize;
      *BlockFooter(next,blocksize)=blocksize;
      InsertFreeBlock(next,AllocationPolicy(blocksize));
      *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
    }
  assert(size == SizeOfBlock(block));
  *BlockHeader(NextBlock(block))|=PreviousBlockBit;
  memory_pool.allocation+=size;
  return(block);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   E x p a n d H e a p                                                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ExpandHeap() get more memory from the system.  It returns MagickTrue on
%  success otherwise MagickFalse.
%
%  The format of the ExpandHeap method is:
%
%      MagickBooleanType ExpandHeap(size_t size)
%
%  A description of each parameter follows:
%
%    o size: the size of the memory in bytes we require.
%
*/
static MagickBooleanType ExpandHeap(size_t size)
{
  DataSegmentInfo
    *segment_info;

  MagickBooleanType
    mapped;

  register ssize_t
    i;

  register void
    *block;

  size_t
    blocksize;

  void
    *segment;

  blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
  assert(memory_pool.number_segments < MaxSegments);
  segment=MapBlob(-1,IOMode,0,blocksize);
  mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
  if (segment == (void *) NULL)
    segment=(void *) memory_methods.acquire_memory_handler(blocksize);
  if (segment == (void *) NULL)
    return(MagickFalse);
  segment_info=(DataSegmentInfo *) free_segments;
  free_segments=segment_info->next;
  segment_info->mapped=mapped;
  segment_info->length=blocksize;
  segment_info->allocation=segment;
  segment_info->bound=(char *) segment+blocksize;
  i=(ssize_t) memory_pool.number_segments-1;
  for ( ; (i >= 0) && (memory_pool.segments[i]->allocation > segment); i--)
    memory_pool.segments[i+1]=memory_pool.segments[i];
  memory_pool.segments[i+1]=segment_info;
  memory_pool.number_segments++;
  size=blocksize-12*sizeof(size_t);
  block=(char *) segment_info->allocation+4*sizeof(size_t);
  *BlockHeader(block)=size | PreviousBlockBit;
  *BlockFooter(block,size)=size;
  InsertFreeBlock(block,AllocationPolicy(size));
  block=NextBlock(block);
  assert(block < segment_info->bound);
  *BlockHeader(block)=2*sizeof(size_t);
  *BlockHeader(NextBlock(block))=PreviousBlockBit;
  return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e l i n q u i s h M a g i c k M e m o r y                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
%  or AcquireQuantumMemory() for reuse.
%
%  The format of the RelinquishMagickMemory method is:
%
%      void *RelinquishMagickMemory(void *memory)
%
%  A description of each parameter follows:
%
%    o memory: A pointer to a block of memory to free for reuse.
%
*/
MagickExport void *RelinquishMagickMemory(void *memory)
{
  if (memory == (void *) NULL)
    return((void *) NULL);
#if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
  memory_methods.destroy_memory_handler(memory);
#else
  LockSemaphoreInfo(memory_semaphore);
  assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
  assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
  if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
    {
      void
        *previous;

      /*
        Coalesce with previous adjacent block.
      */
      previous=PreviousBlock(memory);
      RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
      *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
        (*BlockHeader(previous) & ~SizeMask);
      memory=previous;
    }
  if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
    {
      void
        *next;

      /*
        Coalesce with next adjacent block.
      */
      next=NextBlock(memory);
      RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
      *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
        (*BlockHeader(memory) & ~SizeMask);
    }
  *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
  *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
  InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
  UnlockSemaphoreInfo(memory_semaphore);
#endif
  return((void *) NULL);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e l i n q u i s h M a g i c k M e m o r y                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  RelinquishMagickMemory() zeros memory that has been allocated, frees it for
%  reuse.
%
%  The format of the RelinquishMagickMemory method is:
%
%      void *RelinquishMagickMemory(void *memory)
%
%  A description of each parameter follows:
%
%    o memory: A pointer to a block of memory to free for reuse.
%
*/
MagickExport void *RelinquishMagickMemory(void *memory)
{
  if (memory == (void *) NULL)
    return((void *) NULL);
#if !defined(UseEmbeddableMagick)
  free(memory);
#else
  assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
  assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
  AcquireSemaphoreInfo(&memory_semaphore);
  if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
    {
      void
        *previous;

      /*
        Coalesce with previous adjacent block.
      */
      previous=PreviousBlock(memory);
      RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
      *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
        (*BlockHeader(previous) & ~SizeMask);
      memory=previous;
    }
  if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
    {
      void
        *next;

      /*
        Coalesce with next adjacent block.
      */
      next=NextBlock(memory);
      RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
      *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
        (*BlockHeader(memory) & ~SizeMask);
    }
  *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
  *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
  InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
  RelinquishSemaphoreInfo(memory_semaphore);
#endif
  return((void *) NULL);
}
Exemple #5
0
void xHeap::FreeMedium(void * p)
{
  ASSERT("Trying to free NULL pointer" && p);
  ASSERT("Heap corrupted!" && mediumStats.allocCount >
      mediumStats.freeCount);

#ifdef DEBUG_APP_HEAP
  p = (uint8*)p - sizeof(int);
  ASSERT("Heap corrupted!" && *(int*)p == DUMMY_MEDIUM_USED_ID_PRE);
  // *(int*)p = DUMMY_MEDIUM_FREE_ID_PRE;
#endif

  Block * block = ((Block*)p) - 1;
  ASSERT("Double deallocation!" && !block->isFree);

#ifdef DEBUG_APP_HEAP
  {
    ASSERT("Heap corrupted!"
        && *((int*)((uint8*)p + block->DataSize() + sizeof(int)))
        == DUMMY_MEDIUM_USED_ID_POST);
    // *check_p = DUMMY_MEDIUM_FREE_ID_POST;
  }
#endif

  mediumStats.RegisterFree(block->size, block->DataSize());

  Block * prev = block->prev;
  if(prev->isFree && prev->page == block->page)
  {
    ASSERT("Heap corrupted!"
        && ((uint8*)prev) + prev->size == (uint8*)block);
    prev->size += block->size;

    ((FreeBlock*)prev)->RemoveFreeLink();
    block->RemoveLink();

    block = prev;
    mediumStats.mergeCount++;
  }
  Block * next = block->next;
  if(next->isFree && next->page == block->page)
  {
    ASSERT("Heap corrupted!"
        && ((uint8*)block) + block->size == (uint8*)next);
    block->size += next->size;
    
    ((FreeBlock*)next)->RemoveFreeLink();
    next->RemoveLink();

    mediumStats.mergeCount++;
  }
  block->isFree = true;

#ifdef DEBUG_APP_HEAP
  *(int*)(block+1) = DUMMY_MEDIUM_FREE_ID_PRE;
  *(int*)((uint8*)(block+1) + block->DataSize() + sizeof(int)) = DUMMY_MEDIUM_FREE_ID_POST;
#endif

  InsertFreeBlock((FreeBlock*)block);

#if defined(DEBUG_APP_HEAP) && defined(AEE_SIMULATOR)
  // CheckMemory();
#endif
}
Exemple #6
0
void * xHeap::AllocMedium(uint32 size, const char * filename, int line)
{
#else
void * xHeap::AllocMedium(uint32 size)
{
#endif

#ifdef DEBUG_APP_HEAP
  // static int step = 0;
  // step++;
#endif

  uint32 saveSize = size;
  size = (size + ALIGN - 1 + sizeof(Block) + DUMMY_ID_SIZE) & ~(ALIGN - 1);
  Block * block = dummyFree.nextFree;
  if(block->size < size) // block == &dummyFree => dummyFree.size == 0
  {
    if(size > pageSize / 2)
    {
#ifdef DEBUG_APP_HEAP
      return AllocLarge(saveSize, filename, line);
#else
      return AllocLarge(saveSize);
#endif
    }
    block = (Block*)MALLOC(pageSize);
    if(!block)
    {
      return NULL;
    }
#ifdef DEBUG_APP_HEAP
    block->filename = filename;
    block->line = line;
#endif
    block->page = nextPage++;
    block->size = pageSize;
    block->isFree = true;
    block->InsertBefore(dummyBlock.next);
    ((FreeBlock*)block)->InsertBeforeFreeLink(dummyFree.nextFree);

    mediumStats.allocSize += block->size;
  }
  else
  {
    mediumStats.hitCount++;
#ifdef FIND_BEST_FREE_BLOCK
    for(FreeBlock * next = ((FreeBlock*)block)->nextFree; next->size >= size; )
    {
      block = next;
      next = ((FreeBlock*)block)->nextFree;
    }
#endif
  }

  block->size -= size;
  if(block->size < MAX_SMALL_SIZE && (block->size < MAX_SMALL_SIZE/2 || block->next->page != block->page))
  {
#ifdef DEBUG_APP_HEAP
    block->filename = filename;
    block->line = line;
#endif
    block->size += size;
    ((FreeBlock*)block)->RemoveFreeLink();
  }
  else
  {
#ifdef DEBUG_APP_HEAP
    *(int*)(block+1) = DUMMY_MEDIUM_FREE_ID_PRE;
    *(int*)((uint8*)(block+1) + block->DataSize() + sizeof(int)) = DUMMY_MEDIUM_FREE_ID_POST;
#endif

    if(block->size < ((FreeBlock*)block)->nextFree->size)
    {
      ((FreeBlock*)block)->RemoveFreeLink();
      InsertFreeBlock((FreeBlock*)block);
    }
    ASSERT("Heap corrupted!" && (block->size & 3) == 0);
    Block * newBlock = (Block*)(((uint8*)block) + block->size);
#ifdef DEBUG_APP_HEAP
    newBlock->filename = filename;
    newBlock->line = line;
#endif
    newBlock->page = block->page;
    newBlock->size = size;
    newBlock->InsertAfter(block);    
    block = newBlock;
  }
  block->isFree = false;

  uint32 dataSize = block->DataSize();
  mediumStats.RegisterAlloc(block->size, dataSize);

  uint8 * p = (uint8*)(block+1);
  p[-1] = BT_MEDIUM;

#ifdef DEBUG_APP_HEAP
  *(int*)p = DUMMY_MEDIUM_USED_ID_PRE;
  p += sizeof(int);
  *(int*)(p + dataSize) = DUMMY_MEDIUM_USED_ID_POST;
#endif

  MEMSET(p, 0, dataSize);

#if defined(DEBUG_APP_HEAP) && defined(AEE_SIMULATOR)
  // CheckMemory();
#endif

  return p;
}