Merge pull request #7635 from bunnei/set-heap-size
core: hle: kernel: Updated implementation of svcSetHeapSize.
This commit is contained in:
commit
5e58271903
|
@ -120,7 +120,7 @@ static_assert(static_cast<u32>(KMemoryState::CodeOut) == 0x00402015);
|
||||||
|
|
||||||
enum class KMemoryPermission : u8 {
|
enum class KMemoryPermission : u8 {
|
||||||
None = 0,
|
None = 0,
|
||||||
Mask = static_cast<u8>(~None),
|
All = static_cast<u8>(~None),
|
||||||
|
|
||||||
Read = 1 << 0,
|
Read = 1 << 0,
|
||||||
Write = 1 << 1,
|
Write = 1 << 1,
|
||||||
|
|
|
@ -264,9 +264,9 @@ ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_
|
||||||
ASSERT(heap_last < stack_start || stack_last < heap_start);
|
ASSERT(heap_last < stack_start || stack_last < heap_start);
|
||||||
ASSERT(heap_last < kmap_start || kmap_last < heap_start);
|
ASSERT(heap_last < kmap_start || kmap_last < heap_start);
|
||||||
|
|
||||||
current_heap_addr = heap_region_start;
|
current_heap_end = heap_region_start;
|
||||||
heap_capacity = 0;
|
max_heap_size = 0;
|
||||||
physical_memory_usage = 0;
|
mapped_physical_memory_size = 0;
|
||||||
memory_pool = pool;
|
memory_pool = pool;
|
||||||
|
|
||||||
page_table_impl.Resize(address_space_width, PageBits);
|
page_table_impl.Resize(address_space_width, PageBits);
|
||||||
|
@ -306,7 +306,7 @@ ResultCode KPageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std:
|
||||||
KMemoryState state{};
|
KMemoryState state{};
|
||||||
KMemoryPermission perm{};
|
KMemoryPermission perm{};
|
||||||
CASCADE_CODE(CheckMemoryState(&state, &perm, nullptr, src_addr, size, KMemoryState::All,
|
CASCADE_CODE(CheckMemoryState(&state, &perm, nullptr, src_addr, size, KMemoryState::All,
|
||||||
KMemoryState::Normal, KMemoryPermission::Mask,
|
KMemoryState::Normal, KMemoryPermission::All,
|
||||||
KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask,
|
KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask,
|
||||||
KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
|
KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
|
@ -465,7 +465,7 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
|
||||||
|
|
||||||
MapPhysicalMemory(page_linked_list, addr, end_addr);
|
MapPhysicalMemory(page_linked_list, addr, end_addr);
|
||||||
|
|
||||||
physical_memory_usage += remaining_size;
|
mapped_physical_memory_size += remaining_size;
|
||||||
|
|
||||||
const std::size_t num_pages{size / PageSize};
|
const std::size_t num_pages{size / PageSize};
|
||||||
block_manager->Update(addr, num_pages, KMemoryState::Free, KMemoryPermission::None,
|
block_manager->Update(addr, num_pages, KMemoryState::Free, KMemoryPermission::None,
|
||||||
|
@ -507,7 +507,7 @@ ResultCode KPageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
|
||||||
|
|
||||||
auto process{system.Kernel().CurrentProcess()};
|
auto process{system.Kernel().CurrentProcess()};
|
||||||
process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size);
|
process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size);
|
||||||
physical_memory_usage -= mapped_size;
|
mapped_physical_memory_size -= mapped_size;
|
||||||
|
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
@ -554,7 +554,7 @@ ResultCode KPageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
||||||
KMemoryState src_state{};
|
KMemoryState src_state{};
|
||||||
CASCADE_CODE(CheckMemoryState(
|
CASCADE_CODE(CheckMemoryState(
|
||||||
&src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias,
|
&src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias,
|
||||||
KMemoryState::FlagCanAlias, KMemoryPermission::Mask, KMemoryPermission::ReadAndWrite,
|
KMemoryState::FlagCanAlias, KMemoryPermission::All, KMemoryPermission::ReadAndWrite,
|
||||||
KMemoryAttribute::Mask, KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
|
KMemoryAttribute::Mask, KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
if (IsRegionMapped(dst_addr, size)) {
|
if (IsRegionMapped(dst_addr, size)) {
|
||||||
|
@ -593,7 +593,7 @@ ResultCode KPageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
||||||
KMemoryState src_state{};
|
KMemoryState src_state{};
|
||||||
CASCADE_CODE(CheckMemoryState(
|
CASCADE_CODE(CheckMemoryState(
|
||||||
&src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias,
|
&src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias,
|
||||||
KMemoryState::FlagCanAlias, KMemoryPermission::Mask, KMemoryPermission::None,
|
KMemoryState::FlagCanAlias, KMemoryPermission::All, KMemoryPermission::None,
|
||||||
KMemoryAttribute::Mask, KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped));
|
KMemoryAttribute::Mask, KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
KMemoryPermission dst_perm{};
|
KMemoryPermission dst_perm{};
|
||||||
|
@ -784,7 +784,7 @@ ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemo
|
||||||
CASCADE_CODE(CheckMemoryState(
|
CASCADE_CODE(CheckMemoryState(
|
||||||
&state, nullptr, &attribute, addr, size,
|
&state, nullptr, &attribute, addr, size,
|
||||||
KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted,
|
KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted,
|
||||||
KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, KMemoryPermission::Mask,
|
KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, KMemoryPermission::All,
|
||||||
KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask, KMemoryAttribute::None,
|
KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask, KMemoryAttribute::None,
|
||||||
KMemoryAttribute::IpcAndDeviceMapped));
|
KMemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
|
@ -859,61 +859,125 @@ ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryA
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode KPageTable::SetHeapCapacity(std::size_t new_heap_capacity) {
|
ResultCode KPageTable::SetMaxHeapSize(std::size_t size) {
|
||||||
|
// Lock the table.
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
heap_capacity = new_heap_capacity;
|
|
||||||
|
// Only process page tables are allowed to set heap size.
|
||||||
|
ASSERT(!this->IsKernel());
|
||||||
|
|
||||||
|
max_heap_size = size;
|
||||||
|
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<VAddr> KPageTable::SetHeapSize(std::size_t size) {
|
ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) {
|
||||||
|
// Try to perform a reduction in heap, instead of an extension.
|
||||||
|
VAddr cur_address{};
|
||||||
|
std::size_t allocation_size{};
|
||||||
|
{
|
||||||
|
// Lock the table.
|
||||||
|
std::lock_guard lk(page_table_lock);
|
||||||
|
|
||||||
if (size > heap_region_end - heap_region_start) {
|
// Validate that setting heap size is possible at all.
|
||||||
return ResultOutOfMemory;
|
R_UNLESS(!is_kernel, ResultOutOfMemory);
|
||||||
|
R_UNLESS(size <= static_cast<std::size_t>(heap_region_end - heap_region_start),
|
||||||
|
ResultOutOfMemory);
|
||||||
|
R_UNLESS(size <= max_heap_size, ResultOutOfMemory);
|
||||||
|
|
||||||
|
if (size < GetHeapSize()) {
|
||||||
|
// The size being requested is less than the current size, so we need to free the end of
|
||||||
|
// the heap.
|
||||||
|
|
||||||
|
// Validate memory state.
|
||||||
|
std::size_t num_allocator_blocks;
|
||||||
|
R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks),
|
||||||
|
heap_region_start + size, GetHeapSize() - size,
|
||||||
|
KMemoryState::All, KMemoryState::Normal,
|
||||||
|
KMemoryPermission::All, KMemoryPermission::ReadAndWrite,
|
||||||
|
KMemoryAttribute::All, KMemoryAttribute::None));
|
||||||
|
|
||||||
|
// Unmap the end of the heap.
|
||||||
|
const auto num_pages = (GetHeapSize() - size) / PageSize;
|
||||||
|
R_TRY(Operate(heap_region_start + size, num_pages, KMemoryPermission::None,
|
||||||
|
OperationType::Unmap));
|
||||||
|
|
||||||
|
// Release the memory from the resource limit.
|
||||||
|
system.Kernel().CurrentProcess()->GetResourceLimit()->Release(
|
||||||
|
LimitableResource::PhysicalMemory, num_pages * PageSize);
|
||||||
|
|
||||||
|
// Apply the memory block update.
|
||||||
|
block_manager->Update(heap_region_start + size, num_pages, KMemoryState::Free,
|
||||||
|
KMemoryPermission::None, KMemoryAttribute::None);
|
||||||
|
|
||||||
|
// Update the current heap end.
|
||||||
|
current_heap_end = heap_region_start + size;
|
||||||
|
|
||||||
|
// Set the output.
|
||||||
|
*out = heap_region_start;
|
||||||
|
return ResultSuccess;
|
||||||
|
} else if (size == GetHeapSize()) {
|
||||||
|
// The size requested is exactly the current size.
|
||||||
|
*out = heap_region_start;
|
||||||
|
return ResultSuccess;
|
||||||
|
} else {
|
||||||
|
// We have to allocate memory. Determine how much to allocate and where while the table
|
||||||
|
// is locked.
|
||||||
|
cur_address = current_heap_end;
|
||||||
|
allocation_size = size - GetHeapSize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const u64 previous_heap_size{GetHeapSize()};
|
// Reserve memory for the heap extension.
|
||||||
|
KScopedResourceReservation memory_reservation(
|
||||||
|
system.Kernel().CurrentProcess()->GetResourceLimit(), LimitableResource::PhysicalMemory,
|
||||||
|
allocation_size);
|
||||||
|
R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
|
||||||
|
|
||||||
UNIMPLEMENTED_IF_MSG(previous_heap_size > size, "Heap shrink is unimplemented");
|
// Allocate pages for the heap extension.
|
||||||
|
KPageLinkedList page_linked_list;
|
||||||
|
R_TRY(system.Kernel().MemoryManager().Allocate(page_linked_list, allocation_size / PageSize,
|
||||||
|
memory_pool));
|
||||||
|
|
||||||
// Increase the heap size
|
// Map the pages.
|
||||||
{
|
{
|
||||||
std::lock_guard lock{page_table_lock};
|
// Lock the table.
|
||||||
|
std::lock_guard lk(page_table_lock);
|
||||||
|
|
||||||
const u64 delta{size - previous_heap_size};
|
// Ensure that the heap hasn't changed since we began executing.
|
||||||
|
ASSERT(cur_address == current_heap_end);
|
||||||
|
|
||||||
// Reserve memory for the heap extension.
|
// Check the memory state.
|
||||||
KScopedResourceReservation memory_reservation(
|
std::size_t num_allocator_blocks{};
|
||||||
system.Kernel().CurrentProcess()->GetResourceLimit(), LimitableResource::PhysicalMemory,
|
R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks), current_heap_end,
|
||||||
delta);
|
allocation_size, KMemoryState::All, KMemoryState::Free,
|
||||||
|
KMemoryPermission::None, KMemoryPermission::None,
|
||||||
|
KMemoryAttribute::None, KMemoryAttribute::None));
|
||||||
|
|
||||||
if (!memory_reservation.Succeeded()) {
|
// Map the pages.
|
||||||
LOG_ERROR(Kernel, "Could not reserve heap extension of size {:X} bytes", delta);
|
const auto num_pages = allocation_size / PageSize;
|
||||||
return ResultLimitReached;
|
R_TRY(Operate(current_heap_end, num_pages, page_linked_list, OperationType::MapGroup));
|
||||||
|
|
||||||
|
// Clear all the newly allocated pages.
|
||||||
|
for (std::size_t cur_page = 0; cur_page < num_pages; ++cur_page) {
|
||||||
|
std::memset(system.Memory().GetPointer(current_heap_end + (cur_page * PageSize)), 0,
|
||||||
|
PageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
KPageLinkedList page_linked_list;
|
// We succeeded, so commit our memory reservation.
|
||||||
const std::size_t num_pages{delta / PageSize};
|
|
||||||
|
|
||||||
CASCADE_CODE(
|
|
||||||
system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool));
|
|
||||||
|
|
||||||
if (IsRegionMapped(current_heap_addr, delta)) {
|
|
||||||
return ResultInvalidCurrentMemory;
|
|
||||||
}
|
|
||||||
|
|
||||||
CASCADE_CODE(
|
|
||||||
Operate(current_heap_addr, num_pages, page_linked_list, OperationType::MapGroup));
|
|
||||||
|
|
||||||
// Succeeded in allocation, commit the resource reservation
|
|
||||||
memory_reservation.Commit();
|
memory_reservation.Commit();
|
||||||
|
|
||||||
block_manager->Update(current_heap_addr, num_pages, KMemoryState::Normal,
|
// Apply the memory block update.
|
||||||
KMemoryPermission::ReadAndWrite);
|
block_manager->Update(current_heap_end, num_pages, KMemoryState::Normal,
|
||||||
|
KMemoryPermission::ReadAndWrite, KMemoryAttribute::None);
|
||||||
|
|
||||||
current_heap_addr = heap_region_start + size;
|
// Update the current heap end.
|
||||||
|
current_heap_end = heap_region_start + size;
|
||||||
|
|
||||||
|
// Set the output.
|
||||||
|
*out = heap_region_start;
|
||||||
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
return heap_region_start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
|
ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
|
||||||
|
@ -1005,7 +1069,7 @@ ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) {
|
||||||
|
|
||||||
if (const ResultCode result{CheckMemoryState(
|
if (const ResultCode result{CheckMemoryState(
|
||||||
nullptr, &old_perm, nullptr, addr, size, KMemoryState::FlagCanCodeMemory,
|
nullptr, &old_perm, nullptr, addr, size, KMemoryState::FlagCanCodeMemory,
|
||||||
KMemoryState::FlagCanCodeMemory, KMemoryPermission::Mask,
|
KMemoryState::FlagCanCodeMemory, KMemoryPermission::All,
|
||||||
KMemoryPermission::UserReadWrite, KMemoryAttribute::All, KMemoryAttribute::None)};
|
KMemoryPermission::UserReadWrite, KMemoryAttribute::All, KMemoryAttribute::None)};
|
||||||
result.IsError()) {
|
result.IsError()) {
|
||||||
return result;
|
return result;
|
||||||
|
@ -1058,9 +1122,8 @@ ResultCode KPageTable::InitializeMemoryLayout(VAddr start, VAddr end) {
|
||||||
|
|
||||||
bool KPageTable::IsRegionMapped(VAddr address, u64 size) {
|
bool KPageTable::IsRegionMapped(VAddr address, u64 size) {
|
||||||
return CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free,
|
return CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free,
|
||||||
KMemoryPermission::Mask, KMemoryPermission::None,
|
KMemoryPermission::All, KMemoryPermission::None, KMemoryAttribute::Mask,
|
||||||
KMemoryAttribute::Mask, KMemoryAttribute::None,
|
KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)
|
||||||
KMemoryAttribute::IpcAndDeviceMapped)
|
|
||||||
.IsError();
|
.IsError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,8 +50,8 @@ public:
|
||||||
ResultCode SetMemoryPermission(VAddr addr, std::size_t size, Svc::MemoryPermission perm);
|
ResultCode SetMemoryPermission(VAddr addr, std::size_t size, Svc::MemoryPermission perm);
|
||||||
ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask,
|
ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask,
|
||||||
KMemoryAttribute value);
|
KMemoryAttribute value);
|
||||||
ResultCode SetHeapCapacity(std::size_t new_heap_capacity);
|
ResultCode SetMaxHeapSize(std::size_t size);
|
||||||
ResultVal<VAddr> SetHeapSize(std::size_t size);
|
ResultCode SetHeapSize(VAddr* out, std::size_t size);
|
||||||
ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
|
ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
|
||||||
bool is_map_only, VAddr region_start,
|
bool is_map_only, VAddr region_start,
|
||||||
std::size_t region_num_pages, KMemoryState state,
|
std::size_t region_num_pages, KMemoryState state,
|
||||||
|
@ -183,14 +183,15 @@ public:
|
||||||
constexpr VAddr GetAliasCodeRegionSize() const {
|
constexpr VAddr GetAliasCodeRegionSize() const {
|
||||||
return alias_code_region_end - alias_code_region_start;
|
return alias_code_region_end - alias_code_region_start;
|
||||||
}
|
}
|
||||||
|
size_t GetNormalMemorySize() {
|
||||||
|
std::lock_guard lk(page_table_lock);
|
||||||
|
return GetHeapSize() + mapped_physical_memory_size;
|
||||||
|
}
|
||||||
constexpr std::size_t GetAddressSpaceWidth() const {
|
constexpr std::size_t GetAddressSpaceWidth() const {
|
||||||
return address_space_width;
|
return address_space_width;
|
||||||
}
|
}
|
||||||
constexpr std::size_t GetHeapSize() {
|
constexpr std::size_t GetHeapSize() const {
|
||||||
return current_heap_addr - heap_region_start;
|
return current_heap_end - heap_region_start;
|
||||||
}
|
|
||||||
constexpr std::size_t GetTotalHeapSize() {
|
|
||||||
return GetHeapSize() + physical_memory_usage;
|
|
||||||
}
|
}
|
||||||
constexpr bool IsInsideAddressSpace(VAddr address, std::size_t size) const {
|
constexpr bool IsInsideAddressSpace(VAddr address, std::size_t size) const {
|
||||||
return address_space_start <= address && address + size - 1 <= address_space_end - 1;
|
return address_space_start <= address && address + size - 1 <= address_space_end - 1;
|
||||||
|
@ -270,10 +271,8 @@ private:
|
||||||
VAddr code_region_end{};
|
VAddr code_region_end{};
|
||||||
VAddr alias_code_region_start{};
|
VAddr alias_code_region_start{};
|
||||||
VAddr alias_code_region_end{};
|
VAddr alias_code_region_end{};
|
||||||
VAddr current_heap_addr{};
|
|
||||||
|
|
||||||
std::size_t heap_capacity{};
|
std::size_t mapped_physical_memory_size{};
|
||||||
std::size_t physical_memory_usage{};
|
|
||||||
std::size_t max_heap_size{};
|
std::size_t max_heap_size{};
|
||||||
std::size_t max_physical_memory_size{};
|
std::size_t max_physical_memory_size{};
|
||||||
std::size_t address_space_width{};
|
std::size_t address_space_width{};
|
||||||
|
|
|
@ -172,7 +172,7 @@ void KProcess::DecrementThreadCount() {
|
||||||
|
|
||||||
u64 KProcess::GetTotalPhysicalMemoryAvailable() const {
|
u64 KProcess::GetTotalPhysicalMemoryAvailable() const {
|
||||||
const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
|
const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
|
||||||
page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
|
page_table->GetNormalMemorySize() + GetSystemResourceSize() + image_size +
|
||||||
main_thread_stack_size};
|
main_thread_stack_size};
|
||||||
if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application);
|
if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application);
|
||||||
capacity != pool_size) {
|
capacity != pool_size) {
|
||||||
|
@ -189,7 +189,7 @@ u64 KProcess::GetTotalPhysicalMemoryAvailableWithoutSystemResource() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 KProcess::GetTotalPhysicalMemoryUsed() const {
|
u64 KProcess::GetTotalPhysicalMemoryUsed() const {
|
||||||
return image_size + main_thread_stack_size + page_table->GetTotalHeapSize() +
|
return image_size + main_thread_stack_size + page_table->GetNormalMemorySize() +
|
||||||
GetSystemResourceSize();
|
GetSystemResourceSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,8 +410,8 @@ void KProcess::Run(s32 main_thread_priority, u64 stack_size) {
|
||||||
resource_limit->Reserve(LimitableResource::Threads, 1);
|
resource_limit->Reserve(LimitableResource::Threads, 1);
|
||||||
resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size);
|
resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size);
|
||||||
|
|
||||||
const std::size_t heap_capacity{memory_usage_capacity - main_thread_stack_size - image_size};
|
const std::size_t heap_capacity{memory_usage_capacity - (main_thread_stack_size + image_size)};
|
||||||
ASSERT(!page_table->SetHeapCapacity(heap_capacity).IsError());
|
ASSERT(!page_table->SetMaxHeapSize(heap_capacity).IsError());
|
||||||
|
|
||||||
ChangeStatus(ProcessStatus::Running);
|
ChangeStatus(ProcessStatus::Running);
|
||||||
|
|
||||||
|
|
|
@ -135,24 +135,15 @@ enum class ResourceLimitValueType {
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
/// Set the process heap to a given Size. It can both extend and shrink the heap.
|
/// Set the process heap to a given Size. It can both extend and shrink the heap.
|
||||||
static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_size) {
|
static ResultCode SetHeapSize(Core::System& system, VAddr* out_address, u64 size) {
|
||||||
LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size);
|
LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", size);
|
||||||
|
|
||||||
// Size must be a multiple of 0x200000 (2MB) and be equal to or less than 8GB.
|
// Validate size.
|
||||||
if ((heap_size % 0x200000) != 0) {
|
R_UNLESS(Common::IsAligned(size, HeapSizeAlignment), ResultInvalidSize);
|
||||||
LOG_ERROR(Kernel_SVC, "The heap size is not a multiple of 2MB, heap_size=0x{:016X}",
|
R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize);
|
||||||
heap_size);
|
|
||||||
return ResultInvalidSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heap_size >= 0x200000000) {
|
// Set the heap size.
|
||||||
LOG_ERROR(Kernel_SVC, "The heap size is not less than 8GB, heap_size=0x{:016X}", heap_size);
|
R_TRY(system.Kernel().CurrentProcess()->PageTable().SetHeapSize(out_address, size));
|
||||||
return ResultInvalidSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
|
|
||||||
|
|
||||||
CASCADE_RESULT(*heap_addr, page_table.SetHeapSize(heap_size));
|
|
||||||
|
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "common/literals.h"
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
using Handle = u32;
|
using Handle = u32;
|
||||||
|
@ -12,9 +13,13 @@ using Handle = u32;
|
||||||
|
|
||||||
namespace Kernel::Svc {
|
namespace Kernel::Svc {
|
||||||
|
|
||||||
|
using namespace Common::Literals;
|
||||||
|
|
||||||
constexpr s32 ArgumentHandleCountMax = 0x40;
|
constexpr s32 ArgumentHandleCountMax = 0x40;
|
||||||
constexpr u32 HandleWaitMask{1u << 30};
|
constexpr u32 HandleWaitMask{1u << 30};
|
||||||
|
|
||||||
|
constexpr inline std::size_t HeapSizeAlignment = 2_MiB;
|
||||||
|
|
||||||
constexpr inline Handle InvalidHandle = Handle(0);
|
constexpr inline Handle InvalidHandle = Handle(0);
|
||||||
|
|
||||||
enum PseudoHandle : Handle {
|
enum PseudoHandle : Handle {
|
||||||
|
|
Reference in New Issue