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; }
/** * 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; }
/** * 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); }