rpcs3/rpcs3/Emu/Memory/DynamicMemoryBlockBase.h
2014-07-12 20:38:37 +04:00

213 lines
4.2 KiB
C++

#pragma once
//DynamicMemoryBlockBase
template<typename PT>
DynamicMemoryBlockBase<PT>::DynamicMemoryBlockBase()
: PT()
, m_max_size(0)
{
}
template<typename PT>
const u32 DynamicMemoryBlockBase<PT>::GetUsedSize() const
{
std::lock_guard<std::mutex> lock(m_lock);
u32 size = 0;
for (u32 i = 0; i<m_allocated.size(); ++i)
{
size += m_allocated[i].size;
}
return size;
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::IsInMyRange(const u64 addr)
{
return addr >= MemoryBlock::GetStartAddr() && addr < MemoryBlock::GetStartAddr() + GetSize();
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::IsInMyRange(const u64 addr, const u32 size)
{
return IsInMyRange(addr) && IsInMyRange(addr + size - 1);
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::IsMyAddress(const u64 addr)
{
return IsInMyRange(addr);
}
template<typename PT>
MemoryBlock* DynamicMemoryBlockBase<PT>::SetRange(const u64 start, const u32 size)
{
std::lock_guard<std::mutex> lock(m_lock);
m_max_size = PAGE_4K(size);
if (!MemoryBlock::SetRange(start, 0))
{
assert(0);
return nullptr;
}
return this;
}
template<typename PT>
void DynamicMemoryBlockBase<PT>::Delete()
{
std::lock_guard<std::mutex> lock(m_lock);
m_allocated.clear();
m_max_size = 0;
MemoryBlock::Delete();
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::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;
}
std::lock_guard<std::mutex> lock(m_lock);
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;
}
template<typename PT>
void DynamicMemoryBlockBase<PT>::AppendMem(u64 addr, u32 size) /* private */
{
m_allocated.emplace_back(addr, size);
}
template<typename PT>
u64 DynamicMemoryBlockBase<PT>::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;
}
std::lock_guard<std::mutex> lock(m_lock);
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;
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::Alloc()
{
return AllocAlign(GetSize() - GetUsedSize()) != 0;
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::Free(u64 addr)
{
std::lock_guard<std::mutex> lock(m_lock);
for (u32 num = 0; num < m_allocated.size(); num++)
{
if (addr == m_allocated[num].addr)
{
//LOG_NOTICE(MEMORY, "Free(0x%llx)", addr);
m_allocated.erase(m_allocated.begin() + num);
return true;
}
}
LOG_ERROR(MEMORY, "DynamicMemoryBlock::Free(addr=0x%llx): failed", addr);
for (u32 i = 0; i < m_allocated.size(); i++)
{
LOG_NOTICE(MEMORY, "*** Memory Block: addr = 0x%llx, size = 0x%x", m_allocated[i].addr, m_allocated[i].size);
}
assert(0);
return false;
}
template<typename PT>
u8* DynamicMemoryBlockBase<PT>::GetMem(u64 addr) const
{
return MemoryBlock::GetMem(addr);
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::IsLocked(u64 addr)
{
// TODO
LOG_ERROR(MEMORY, "IsLocked(0x%llx) not implemented", addr);
assert(0);
return false;
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::Lock(u64 addr, u32 size)
{
// TODO
LOG_ERROR(MEMORY, "Lock(0x%llx, 0x%x) not implemented", addr, size);
assert(0);
return false;
}
template<typename PT>
bool DynamicMemoryBlockBase<PT>::Unlock(u64 addr, u32 size)
{
// TODO
LOG_ERROR(MEMORY, "Unlock(0x%llx, 0x%x) not implemented", addr, size);
assert(0);
return false;
}