u32 BlockAllocator::GetBlockStartFromAddress(u32 addr) { Block *b = GetBlockFromAddress(addr); if (b) return b->start; else return -1; }
u32 BlockAllocator::GetBlockSizeFromAddress(u32 addr) const { const Block *b = GetBlockFromAddress(addr); if (b) return b->size; else return -1; }
bool BlockAllocator::FreeExact(u32 position) { BlockAllocator::Block *b = GetBlockFromAddress(position); if (b && b->taken && b->start == position) return Free(position); else { ERROR_LOG(HLE, "BlockAllocator : invalid free %08x", position); return false; } }
bool BlockAllocator::FreeExact(u32 position) { Block *b = GetBlockFromAddress(position); if (b && b->taken && b->start == position) { b->taken = false; MergeFreeBlocks(b); return true; } else { ERROR_LOG(HLE, "BlockAllocator : invalid free %08x", position); return false; } }
u32 BlockAllocator::AllocAt(u32 position, u32 size, const char *tag) { CheckBlocks(); if (size > rangeSize_) { ERROR_LOG(HLE, "Clearly bogus size: %08x - failing allocation", size); return -1; } // Downalign the position so we're allocating full blocks. u32 alignedPosition = position; u32 alignedSize = size; if (position & (grain_ - 1)) { DEBUG_LOG(HLE, "Position %08x does not align to grain.", position); alignedPosition &= ~(grain_ - 1); // Since the position was decreased, size must increase. alignedSize += alignedPosition - position; } // Upalign size to grain. alignedSize = (alignedSize + grain_ - 1) & ~(grain_ - 1); // Tell the caller the allocated size from their requested starting position. size = alignedSize - (alignedPosition - position); Block *bp = GetBlockFromAddress(alignedPosition); if (bp != NULL) { Block &b = *bp; if (b.taken) { ERROR_LOG(HLE, "Block allocator AllocAt failed, block taken! %08x, %i", position, size); return -1; } else { // Make sure the block is big enough to split. if (b.start + b.size < alignedPosition + alignedSize) { ERROR_LOG(HLE, "Block allocator AllocAt failed, not enough contiguous space %08x, %i", position, size); return -1; } //good to go else if (b.start == alignedPosition) { InsertFreeAfter(&b, b.start + alignedSize, b.size - alignedSize); b.taken = true; b.size = alignedSize; b.SetTag(tag); CheckBlocks(); return position; } else { int size1 = alignedPosition - b.start; InsertFreeBefore(&b, b.start, size1); if (b.start + b.size > alignedPosition + alignedSize) InsertFreeAfter(&b, alignedPosition + alignedSize, b.size - (alignedSize + size1)); b.taken = true; b.start = alignedPosition; b.size = alignedSize; b.SetTag(tag); return position; } } } else { ERROR_LOG(HLE, "Block allocator AllocAt failed :( %08x, %i", position, size); } //Out of memory :( ListBlocks(); ERROR_LOG(HLE, "Block Allocator failed to allocate %i bytes of contiguous memory", alignedSize); return -1; }
const char *BlockAllocator::GetBlockTag(u32 addr) const { const Block *b = GetBlockFromAddress(addr); return b->tag; }
u32 BlockAllocator::AllocAt(u32 position, u32 size, const char *tag) { CheckBlocks(); if (size > rangeSize_) { ERROR_LOG(HLE, "Clearly bogus size: %08x - failing allocation", size); return -1; } // upalign size to grain size = (size + grain_ - 1) & ~(grain_ - 1); // check that position is aligned if (position & (grain_ - 1)) { ERROR_LOG(HLE, "Position %08x does not align to grain. Grain will be off.", position); } Block *bp = GetBlockFromAddress(position); if (bp != NULL) { Block &b = *bp; if (b.taken) { ERROR_LOG(HLE, "Block allocator AllocAt failed, block taken! %08x, %i", position, size); return -1; } else { //good to go if (b.start == position) { InsertFreeAfter(&b, b.start + size, b.size - size); b.taken = true; b.size = size; b.SetTag(tag); CheckBlocks(); return position; } else { int size1 = position - b.start; InsertFreeBefore(&b, b.start, size1); if (b.start + b.size > position + size) InsertFreeAfter(&b, position + size, b.size - (size + size1)); b.taken = true; b.start = position; b.size = size; b.SetTag(tag); return position; } } } else { ERROR_LOG(HLE, "Block allocator AllocAt failed :( %08x, %i", position, size); } //Out of memory :( ListBlocks(); ERROR_LOG(HLE, "Block Allocator failed to allocate %i bytes of contiguous memory", size); return -1; }