int main()
{
    char *str = malloc(100);
    printf("\nEnter the reference string\n");
    scanf("%100s", str); // no need to accept chars after space

    printf("\n%s\n", str);

    int len = strlen(str);

    int c_size = 0;
    printf("\nEnter size of cache\n");
    scanf("%d", &c_size);

    if (c_size < len)
    {
        int faultCnt = 0;
        char *aux = malloc(c_size);
        initializeAux(aux, c_size);

        int i;
        for (i = 0; i < len; ++i)
        {
            replaceBlock(aux, str[i], c_size, &faultCnt);
            printAux(aux, c_size);
        }

        printf("\npage fault count = %d\n", faultCnt);
    }
    return 0;
}
Пример #2
0
/**
 * Resize an allocated memory block.
 */
uint32_t
MEMResizeForMBlockExpHeap(ExpandedHeap *heap, uint8_t *mblock, uint32_t size)
{
   ScopedSpinLock lock(&heap->lock);

   // Get the block header
   auto address = mem::untranslate(mblock);
   auto base = address - static_cast<uint32_t>(sizeof(ExpandedHeapBlock));

   auto block = make_virtual_ptr<ExpandedHeapBlock>(base);
   auto nextAddr = block->addr + block->size;

   auto freeBlock = findBlock(heap->freeBlockList, nextAddr);
   auto freeBlockSize = 0u;

   auto dataSize = (block->addr + block->size) - address;
   auto difSize = static_cast<int32_t>(size) - static_cast<int32_t>(dataSize);
   auto newSize = block->size + difSize;

   if (difSize == 0) {
      // No difference, return current size
      return size;
   } else if (difSize > 0) {
      if (!freeBlock) {
         // No free block to expand into, return fail
         return 0;
      } else if (freeBlock->size < static_cast<uint32_t>(difSize)) {
         // Free block is too small, return fail
         return 0;
      } else {
         if (freeBlock->size - difSize < sMinimumBlockSize) {
            // The free block will be smaller than minimum size, so just absorb it completely
            freeBlockSize = 0;
            newSize = freeBlock->size;
         } else {
            // Free block is large enough, we just reduce its size
            freeBlockSize = freeBlock->size - difSize;
         }
      }
   } else if (difSize < 0) {
      if (freeBlock) {
         // Increase size of free block
         freeBlockSize = freeBlock->size - difSize;
      } else if (difSize < sMinimumBlockSize) {
         // We can't fit a new free block in the gap, so return current size
         return block->size;
      } else {
         // Create a new free block in the gap
         freeBlockSize = -difSize;
      }
   }

   // Update free block
   if (freeBlockSize) {
      auto old = freeBlock;
      freeBlock = make_virtual_ptr<ExpandedHeapBlock>(block->addr + newSize);
      freeBlock->addr = block->addr + newSize;
      freeBlock->size = freeBlockSize;
      replaceBlock(heap->freeBlockList, old, freeBlock);
   } else {
      // We have totally consumed the free block
      eraseBlock(heap->freeBlockList, freeBlock);
   }

   // Resize block
   block->size = newSize;
   return size;
}
Пример #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);
}