|
|
|
@ -256,57 +256,50 @@ ResultCode VMManager::ReprotectRange(VAddr target, u64 size, VMAPermission new_p |
|
|
|
return RESULT_SUCCESS; |
|
|
|
} |
|
|
|
|
|
|
|
ResultVal<VAddr> VMManager::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { |
|
|
|
if (!IsWithinHeapRegion(target, size)) { |
|
|
|
return ERR_INVALID_ADDRESS; |
|
|
|
ResultVal<VAddr> VMManager::SetHeapSize(u64 size) { |
|
|
|
if (size > GetHeapRegionSize()) { |
|
|
|
return ERR_OUT_OF_MEMORY; |
|
|
|
} |
|
|
|
|
|
|
|
// No need to do any additional work if the heap is already the given size.
|
|
|
|
if (size == GetCurrentHeapSize()) { |
|
|
|
return MakeResult(heap_region_base); |
|
|
|
} |
|
|
|
|
|
|
|
if (heap_memory == nullptr) { |
|
|
|
// Initialize heap
|
|
|
|
heap_memory = std::make_shared<std::vector<u8>>(); |
|
|
|
heap_start = heap_end = target; |
|
|
|
heap_memory = std::make_shared<std::vector<u8>>(size); |
|
|
|
heap_end = heap_region_base + size; |
|
|
|
} else { |
|
|
|
UnmapRange(heap_start, heap_end - heap_start); |
|
|
|
} |
|
|
|
|
|
|
|
// If necessary, expand backing vector to cover new heap extents.
|
|
|
|
if (target < heap_start) { |
|
|
|
heap_memory->insert(begin(*heap_memory), heap_start - target, 0); |
|
|
|
heap_start = target; |
|
|
|
RefreshMemoryBlockMappings(heap_memory.get()); |
|
|
|
} |
|
|
|
if (target + size > heap_end) { |
|
|
|
heap_memory->insert(end(*heap_memory), (target + size) - heap_end, 0); |
|
|
|
heap_end = target + size; |
|
|
|
RefreshMemoryBlockMappings(heap_memory.get()); |
|
|
|
UnmapRange(heap_region_base, GetCurrentHeapSize()); |
|
|
|
} |
|
|
|
ASSERT(heap_end - heap_start == heap_memory->size()); |
|
|
|
|
|
|
|
CASCADE_RESULT(auto vma, MapMemoryBlock(target, heap_memory, target - heap_start, size, |
|
|
|
MemoryState::Heap)); |
|
|
|
Reprotect(vma, perms); |
|
|
|
// If necessary, expand backing vector to cover new heap extents in
|
|
|
|
// the case of allocating. Otherwise, shrink the backing memory,
|
|
|
|
// if a smaller heap has been requested.
|
|
|
|
const u64 old_heap_size = GetCurrentHeapSize(); |
|
|
|
if (size > old_heap_size) { |
|
|
|
const u64 alloc_size = size - old_heap_size; |
|
|
|
|
|
|
|
heap_used = size; |
|
|
|
|
|
|
|
return MakeResult<VAddr>(heap_end - size); |
|
|
|
} |
|
|
|
heap_memory->insert(heap_memory->end(), alloc_size, 0); |
|
|
|
RefreshMemoryBlockMappings(heap_memory.get()); |
|
|
|
} else if (size < old_heap_size) { |
|
|
|
heap_memory->resize(size); |
|
|
|
heap_memory->shrink_to_fit(); |
|
|
|
|
|
|
|
ResultCode VMManager::HeapFree(VAddr target, u64 size) { |
|
|
|
if (!IsWithinHeapRegion(target, size)) { |
|
|
|
return ERR_INVALID_ADDRESS; |
|
|
|
RefreshMemoryBlockMappings(heap_memory.get()); |
|
|
|
} |
|
|
|
|
|
|
|
if (size == 0) { |
|
|
|
return RESULT_SUCCESS; |
|
|
|
} |
|
|
|
heap_end = heap_region_base + size; |
|
|
|
ASSERT(GetCurrentHeapSize() == heap_memory->size()); |
|
|
|
|
|
|
|
const ResultCode result = UnmapRange(target, size); |
|
|
|
if (result.IsError()) { |
|
|
|
return result; |
|
|
|
const auto mapping_result = |
|
|
|
MapMemoryBlock(heap_region_base, heap_memory, 0, size, MemoryState::Heap); |
|
|
|
if (mapping_result.Failed()) { |
|
|
|
return mapping_result.Code(); |
|
|
|
} |
|
|
|
|
|
|
|
heap_used -= size; |
|
|
|
return RESULT_SUCCESS; |
|
|
|
return MakeResult<VAddr>(heap_region_base); |
|
|
|
} |
|
|
|
|
|
|
|
MemoryInfo VMManager::QueryMemory(VAddr address) const { |
|
|
|
@ -598,6 +591,7 @@ void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType ty |
|
|
|
|
|
|
|
heap_region_base = map_region_end; |
|
|
|
heap_region_end = heap_region_base + heap_region_size; |
|
|
|
heap_end = heap_region_base; |
|
|
|
|
|
|
|
new_map_region_base = heap_region_end; |
|
|
|
new_map_region_end = new_map_region_base + new_map_region_size; |
|
|
|
@ -692,10 +686,6 @@ u64 VMManager::GetTotalMemoryUsage() const { |
|
|
|
return 0xF8000000; |
|
|
|
} |
|
|
|
|
|
|
|
u64 VMManager::GetTotalHeapUsage() const { |
|
|
|
return heap_used; |
|
|
|
} |
|
|
|
|
|
|
|
VAddr VMManager::GetAddressSpaceBaseAddress() const { |
|
|
|
return address_space_base; |
|
|
|
} |
|
|
|
@ -778,6 +768,10 @@ u64 VMManager::GetHeapRegionSize() const { |
|
|
|
return heap_region_end - heap_region_base; |
|
|
|
} |
|
|
|
|
|
|
|
u64 VMManager::GetCurrentHeapSize() const { |
|
|
|
return heap_end - heap_region_base; |
|
|
|
} |
|
|
|
|
|
|
|
bool VMManager::IsWithinHeapRegion(VAddr address, u64 size) const { |
|
|
|
return IsInsideAddressRange(address, size, GetHeapRegionBaseAddress(), |
|
|
|
GetHeapRegionEndAddress()); |
|
|
|
|