MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size) : MemInfo(_addr, PAGE_4K(_size)) { void* real_addr = (void*)((u64)Memory.GetBaseAddr() + _addr); #ifdef _WIN32 mem = VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE); #else if (::mprotect(real_addr, size, PROT_READ | PROT_WRITE)) { mem = nullptr; } else { mem = real_addr; } #endif if (mem != real_addr) { LOG_ERROR(MEMORY, "Memory allocation failed (addr=0x%llx, size=0x%llx)", addr, size); Emu.Pause(); } else { Memory.RegisterPages(_addr, PAGE_4K(_size)); memset(mem, 0, size); } }
bool DynamicMemoryBlockBase::AllocFixed(u32 addr, u32 size) { assert(size); size = PAGE_4K(size + (addr & 4095)); // align size addr &= ~4095; // align start address if (!IsInMyRange(addr, size)) { assert(0); return false; } std::lock_guard<std::mutex> lock(Memory.mutex); for (u32 i = 0; i<m_allocated.size(); ++i) { if (addr >= m_allocated[i].addr && addr <= m_allocated[i].addr + m_allocated[i].size - 1) return false; } AppendMem(addr, size); return true; }
u32 DynamicMemoryBlockBase::AllocAlign(u32 size, u32 align) { assert(size && align); if (!MemoryBlock::GetStartAddr()) { LOG_ERROR(MEMORY, "DynamicMemoryBlockBase::AllocAlign(size=0x%x, align=0x%x): memory block not initialized", size, align); return 0; } size = PAGE_4K(size); u32 exsize; if (align <= 4096) { align = 0; exsize = size; } else { align &= ~4095; exsize = size + align - 1; } std::lock_guard<std::mutex> lock(Memory.mutex); for (u32 addr = MemoryBlock::GetStartAddr(); addr <= MemoryBlock::GetEndAddr() - exsize;) { bool is_good_addr = true; for (u32 i = 0; i<m_allocated.size(); ++i) { if ((addr >= m_allocated[i].addr && addr <= m_allocated[i].addr + m_allocated[i].size - 1) || (m_allocated[i].addr >= addr && m_allocated[i].addr <= addr + exsize - 1)) { is_good_addr = false; addr = m_allocated[i].addr + m_allocated[i].size; break; } } if (!is_good_addr) continue; if (align) { addr = (addr + (align - 1)) & ~(align - 1); } //LOG_NOTICE(MEMORY, "AllocAlign(size=0x%x) -> 0x%x", size, addr); AppendMem(addr, size); return addr; } return 0; }
MemoryBlock* DynamicMemoryBlockBase::SetRange(const u32 start, const u32 size) { std::lock_guard<std::mutex> lock(Memory.mutex); m_max_size = PAGE_4K(size); if (!MemoryBlock::SetRange(start, 0)) { assert(0); return nullptr; } return this; }
MemoryBlock* DynamicMemoryBlockBase::SetRange(const u64 start, const u32 size) { LV2_LOCK(0); m_max_size = PAGE_4K(size); if (!MemoryBlock::SetRange(start, 0)) { assert(0); return nullptr; } return this; }
u64 DynamicMemoryBlockBase::AllocAlign(u32 size, u32 align) { size = PAGE_4K(size); u32 exsize; if (align <= 4096) { align = 0; exsize = size; } else { align &= ~4095; exsize = size + align - 1; } LV2_LOCK(0); for (u64 addr = MemoryBlock::GetStartAddr(); addr <= MemoryBlock::GetEndAddr() - exsize;) { bool is_good_addr = true; for (u32 i = 0; i<m_allocated.size(); ++i) { if ((addr >= m_allocated[i].addr && addr < m_allocated[i].addr + m_allocated[i].size) || (m_allocated[i].addr >= addr && m_allocated[i].addr < addr + exsize)) { is_good_addr = false; addr = m_allocated[i].addr + m_allocated[i].size; break; } } if (!is_good_addr) continue; if (align) { addr = (addr + (align - 1)) & ~(align - 1); } //LOG_NOTICE(MEMORY, "AllocAlign(size=0x%x) -> 0x%llx", size, addr); AppendMem(addr, size); return addr; } return 0; }
bool DynamicMemoryBlockBase::AllocFixed(u64 addr, u32 size) { size = PAGE_4K(size + (addr & 4095)); // align size addr &= ~4095; // align start address if (!IsInMyRange(addr, size)) { assert(0); return false; } LV2_LOCK(0); for (u32 i = 0; i<m_allocated.size(); ++i) { if (addr >= m_allocated[i].addr && addr < m_allocated[i].addr + m_allocated[i].size) return false; } AppendMem(addr, size); return true; }