예제 #1
0
void
MEMDumpHeap(CommonHeap *heap)
{
   switch (heap->tag) {
   case HeapType::ExpandedHeap:
      MEMiDumpExpHeap(reinterpret_cast<ExpandedHeap*>(heap));
      break;
   case HeapType::FrameHeap:
   case HeapType::UnitHeap:
   case HeapType::UserHeap:
   case HeapType::BlockHeap:
      gLog->error("TODO: Unimplemented MEMDumpHeap type");
   }
}
예제 #2
0
void
MEMDumpHeap(CommonHeap *heap)
{
   switch (heap->tag) {
   case MEMiHeapTag::ExpandedHeap:
      MEMiDumpExpHeap(reinterpret_cast<ExpandedHeap*>(heap));
      break;
   case MEMiHeapTag::UnitHeap:
      MEMiDumpUnitHeap(reinterpret_cast<UnitHeap*>(heap));
      break;
   case MEMiHeapTag::FrameHeap:
   case MEMiHeapTag::UserHeap:
   case MEMiHeapTag::BlockHeap:
      gLog->info("Unimplemented MEMDumpHeap type");
   }
}
예제 #3
0
/**
 * Allocate aligned memory from an expanded heap
 *
 * Sets the memory block group ID to the current active group ID.
 * If alignment is negative the memory is allocated from the top of the heap.
 * If alignment is positive the memory is allocated from the bottom of the heap.
 */
void *
MEMAllocFromExpHeapEx(ExpandedHeap *heap, uint32_t size, int alignment)
{
   ScopedSpinLock lock(&heap->lock);
   virtual_ptr<ExpandedHeapBlock> freeBlock, usedBlock;
   auto direction = MEMExpHeapDirection::FromBottom;
   uint32_t base;

   if (alignment < 0) {
      alignment = -alignment;
      direction = MEMExpHeapDirection::FromTop;
   }

   // Add size for block header and alignment
   uint32_t originalSize = size;
   size += sizeof(ExpandedHeapBlock);
   size += alignment;

   if (heap->mode == MEMExpHeapMode::FirstFree) {
      if (direction == MEMExpHeapDirection::FromBottom) {
         // Find first block large enough from bottom of heap
         for (auto block = heap->freeBlockList; block; block = block->next) {
            if (block->size < size) {
               continue;
            }

            freeBlock = block;
            break;
         }
      } else {  // direction == MEMExpHeapDirection::FromTop
         // Find first block large enough from top of heap
         for (auto block = getTail(heap->freeBlockList); block; block = block->prev) {
            if (block->size < size) {
               continue;
            }

            freeBlock = block;
            break;
         }
      }
   } else if (heap->mode == MEMExpHeapMode::NearestSize) {
      uint32_t nearestSize = -1;

      if (direction == MEMExpHeapDirection::FromBottom) {
         // Find block nearest in size from bottom of heap
         for (auto block = heap->freeBlockList; block; block = block->next) {
            if (block->size < size) {
               continue;
            }

            if (block->size - size < nearestSize) {
               nearestSize = block->size - size;
               freeBlock = block;
            }
         }
      } else {  // direction == MEMExpHeapDirection::FromTop
         // Find block nearest in size from top of heap
         for (auto block = getTail(heap->freeBlockList); block; block = block->prev) {
            if (block->size < size) {
               continue;
            }

            if (block->size - size < nearestSize) {
               nearestSize = block->size - size;
               freeBlock = block;
            }
         }
      }
   }

   if (!freeBlock) {
      gLog->error("MEMAllocFromExpHeapEx failed, no free block found for size {:08x} ({:08x}+{:x}+{:x})", size, originalSize, sizeof(ExpandedHeapBlock), alignment);
      MEMiDumpExpHeap(heap);
      return nullptr;
   }

   if (direction == MEMExpHeapDirection::FromBottom) {
      // Reduce freeblock size
      base = freeBlock->addr;
      freeBlock->size -= size;

      if (freeBlock->size < sMinimumBlockSize) {
         // Absorb free block as it is too small
         size += freeBlock->size;
         eraseBlock(heap->freeBlockList, freeBlock);
      } else {
         auto freeSize = freeBlock->size;

         // Replace free block
         auto old = freeBlock;
         freeBlock = make_virtual_ptr<ExpandedHeapBlock>(base + size);
         freeBlock->addr = base + size;
         freeBlock->size = freeSize;
         replaceBlock(heap->freeBlockList, old, freeBlock);
      }
   } else {  // direction == MEMExpHeapDirection::FromTop
      // Reduce freeblock size
      freeBlock->size -= size;
      base = freeBlock->addr + freeBlock->size;

      if (freeBlock->size < sMinimumBlockSize) {
         // Absorb free block as it is too small
         size += freeBlock->size;
         eraseBlock(heap->freeBlockList, freeBlock);
      }
   }

   // Create a new used block
   auto aligned = align_up(base + static_cast<uint32_t>(sizeof(ExpandedHeapBlock)), alignment);
   usedBlock = make_virtual_ptr<ExpandedHeapBlock>(aligned - static_cast<uint32_t>(sizeof(ExpandedHeapBlock)));
   usedBlock->addr = base;
   usedBlock->size = size;
   usedBlock->group = heap->group;
   usedBlock->direction = direction;
   insertBlock(heap->usedBlockList, usedBlock);
   return make_virtual_ptr<void>(aligned);
}