From 3be1a565f895d5399a6c1f6d0997dc528537fe86 Mon Sep 17 00:00:00 2001 From: Chloe Marcec Date: Sat, 30 Jan 2021 20:40:49 +1100 Subject: [PATCH 1/8] kernel: Rewrite resource limit to be more accurate Matches closer to hardware --- src/core/CMakeLists.txt | 5 +- .../hle/kernel/k_light_condition_variable.h | 60 +++++++ src/core/hle/kernel/k_resource_limit.cpp | 155 ++++++++++++++++++ src/core/hle/kernel/k_resource_limit.h | 80 +++++++++ src/core/hle/kernel/k_thread.cpp | 4 +- src/core/hle/kernel/kernel.cpp | 30 ++-- src/core/hle/kernel/kernel.h | 4 +- src/core/hle/kernel/memory/page_table.cpp | 13 +- src/core/hle/kernel/process.cpp | 24 +-- src/core/hle/kernel/process.h | 6 +- src/core/hle/kernel/resource_limit.cpp | 73 --------- src/core/hle/kernel/resource_limit.h | 106 ------------ src/core/hle/kernel/svc.cpp | 28 ++-- 13 files changed, 357 insertions(+), 231 deletions(-) create mode 100644 src/core/hle/kernel/k_light_condition_variable.h create mode 100644 src/core/hle/kernel/k_resource_limit.cpp create mode 100644 src/core/hle/kernel/k_resource_limit.h delete mode 100644 src/core/hle/kernel/resource_limit.cpp delete mode 100644 src/core/hle/kernel/resource_limit.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 397cc028f..0ee02c81d 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -160,9 +160,12 @@ add_library(core STATIC hle/kernel/k_affinity_mask.h hle/kernel/k_condition_variable.cpp hle/kernel/k_condition_variable.h + hle/kernel/k_light_condition_variable.h hle/kernel/k_light_lock.cpp hle/kernel/k_light_lock.h hle/kernel/k_priority_queue.h + hle/kernel/k_resource_limit.cpp + hle/kernel/k_resource_limit.h hle/kernel/k_scheduler.cpp hle/kernel/k_scheduler.h hle/kernel/k_scheduler_lock.h @@ -203,8 +206,6 @@ add_library(core STATIC hle/kernel/process_capability.h hle/kernel/readable_event.cpp hle/kernel/readable_event.h - hle/kernel/resource_limit.cpp - hle/kernel/resource_limit.h hle/kernel/server_port.cpp hle/kernel/server_port.h hle/kernel/server_session.cpp diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h new file mode 100644 index 000000000..26573a239 --- /dev/null +++ b/src/core/hle/kernel/k_light_condition_variable.h @@ -0,0 +1,60 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +// This file references various implementation details from Atmosphere, an open-source firmware for +// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. + +#pragma once + +#include "common/common_types.h" +#include "core/hle/kernel/k_scheduler.h" +#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" +#include "core/hle/kernel/k_thread_queue.h" +#include "core/hle/kernel/time_manager.h" + +namespace Kernel { +class KernelCore; + +class KLightConditionVariable { +private: + KThreadQueue m_thread_queue; + +public: + KLightConditionVariable(KernelCore& kernel) : m_thread_queue(kernel), kernel(kernel) {} + + void Wait(KLightLock* lock, s64 timeout = -1ll) { + WaitImpl(lock, timeout); + lock->Lock(); + } + + void Broadcast() { + KScopedSchedulerLock lk{kernel}; + while (m_thread_queue.WakeupFrontThread() != nullptr) { + /* We want to signal all threads, and so should continue waking up until there's nothing + * to wake. */ + } + } + +private: + void WaitImpl(KLightLock* lock, s64 timeout) { + KThread* owner = GetCurrentThreadPointer(kernel); + // KHardwareTimer* timer; + + /* Sleep the thread. */ + { + KScopedSchedulerLockAndSleep lk(kernel, owner, timeout); + lock->Unlock(); + + if (!m_thread_queue.SleepThread(owner)) { + lk.CancelSleep(); + return; + } + } + + /* Cancel the task that the sleep setup. */ + kernel.TimeManager().UnscheduleTimeEvent(owner); + } + KernelCore& kernel; +}; +} // namespace Kernel diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp new file mode 100644 index 000000000..f943d6562 --- /dev/null +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -0,0 +1,155 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +// This file references various implementation details from Atmosphere, an open-source firmware for +// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. + +#include "common/assert.h" +#include "core/core.h" +#include "core/core_timing.h" +#include "core/core_timing_util.h" +#include "core/hle/kernel/k_resource_limit.h" +#include "core/hle/kernel/svc_results.h" + +namespace Kernel { +namespace { +static const s64 DefaultTimeout = + Core::Timing::msToCycles(std::chrono::milliseconds{10000}); // 10 seconds +} + +KResourceLimit::KResourceLimit(KernelCore& kernel, Core::System& system) + : Object{kernel}, m_lock{kernel}, cond_var{kernel}, kernel{kernel}, system(system) {} +KResourceLimit::~KResourceLimit() = default; + +s64 KResourceLimit::GetLimitValue(LimitableResource which) const { + const auto index = static_cast(which); + s64 value{}; + { + KScopedLightLock lk{m_lock}; + value = limit_values[index]; + ASSERT(value >= 0); + ASSERT(current_values[index] <= limit_values[index]); + ASSERT(current_hints[index] <= current_values[index]); + } + return value; +} + +s64 KResourceLimit::GetCurrentValue(LimitableResource which) const { + const auto index = static_cast(which); + s64 value{}; + { + KScopedLightLock lk{m_lock}; + value = current_values[index]; + ASSERT(value >= 0); + ASSERT(current_values[index] <= limit_values[index]); + ASSERT(current_hints[index] <= current_values[index]); + } + return value; +} + +s64 KResourceLimit::GetPeakValue(LimitableResource which) const { + const auto index = static_cast(which); + s64 value{}; + { + KScopedLightLock lk{m_lock}; + value = peak_values[index]; + ASSERT(value >= 0); + ASSERT(current_values[index] <= limit_values[index]); + ASSERT(current_hints[index] <= current_values[index]); + } + return value; +} + +s64 KResourceLimit::GetFreeValue(LimitableResource which) const { + const auto index = static_cast(which); + s64 value{}; + { + KScopedLightLock lk(m_lock); + ASSERT(current_values[index] >= 0); + ASSERT(current_values[index] <= limit_values[index]); + ASSERT(current_hints[index] <= current_values[index]); + value = limit_values[index] - current_values[index]; + } + + return value; +} + +ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { + const auto index = static_cast(which); + KScopedLightLock lk(m_lock); + R_UNLESS(current_values[index] <= value, Svc::ResultInvalidState); + + limit_values[index] = value; + + return RESULT_SUCCESS; +} + +bool KResourceLimit::Reserve(LimitableResource which, s64 value) { + return Reserve(which, value, system.CoreTiming().GetClockTicks() + DefaultTimeout); +} + +bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { + ASSERT(value >= 0); + const auto index = static_cast(which); + KScopedLightLock lk(m_lock); + + ASSERT(current_hints[index] <= current_values[index]); + if (current_hints[index] >= limit_values[index]) { + return false; + } + + /* Loop until we reserve or run out of time. */ + while (true) { + ASSERT(current_values[index] <= limit_values[index]); + ASSERT(current_hints[index] <= current_values[index]); + + /* If we would overflow, don't allow to succeed. */ + if (current_values[index] + value <= current_values[index]) { + break; + } + + if (current_values[index] + value <= limit_values[index]) { + current_values[index] += value; + current_hints[index] += value; + peak_values[index] = std::max(peak_values[index], current_values[index]); + return true; + } + + if (current_hints[index] + value <= limit_values[index] && + (timeout < 0 || system.CoreTiming().GetClockTicks() < static_cast(timeout))) { + waiter_count++; + cond_var.Wait(&m_lock, timeout); + waiter_count--; + } else { + break; + } + } + + return false; +} + +void KResourceLimit::Release(LimitableResource which, s64 value) { + Release(which, value, value); +} + +void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) { + ASSERT(value >= 0); + ASSERT(hint >= 0); + + const auto index = static_cast(which); + KScopedLightLock lk(m_lock); + ASSERT(current_values[index] <= limit_values[index]); + ASSERT(current_hints[index] <= current_values[index]); + ASSERT(value <= current_values[index]); + ASSERT(hint <= current_hints[index]); + + current_values[index] -= value; + current_hints[index] -= hint; + + if (waiter_count != 0) { + cond_var.Broadcast(); + } +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h new file mode 100644 index 000000000..84c59177c --- /dev/null +++ b/src/core/hle/kernel/k_resource_limit.h @@ -0,0 +1,80 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +// This file references various implementation details from Atmosphere, an open-source firmware for +// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. + +#pragma once + +#include +#include "common/common_types.h" +#include "core/hle/kernel/k_light_condition_variable.h" +#include "core/hle/kernel/k_light_lock.h" +#include "core/hle/kernel/object.h" + +union ResultCode; + +namespace Core { +class System; +} + +namespace Kernel { +class KernelCore; +enum class LimitableResource : u32 { + PhysicalMemoryMax = 0, + ThreadCountMax = 1, + EventCountMax = 2, + TransferMemoryCountMax = 3, + SessionCountMax = 4, + + Count, +}; + +constexpr bool IsValidResourceType(LimitableResource type) { + return type < LimitableResource::Count; +} + +class KResourceLimit final : public Object { +public: + KResourceLimit(KernelCore& kernel, Core::System& system); + ~KResourceLimit(); + + s64 GetLimitValue(LimitableResource which) const; + s64 GetCurrentValue(LimitableResource which) const; + s64 GetPeakValue(LimitableResource which) const; + s64 GetFreeValue(LimitableResource which) const; + + ResultCode SetLimitValue(LimitableResource which, s64 value); + + bool Reserve(LimitableResource which, s64 value); + bool Reserve(LimitableResource which, s64 value, s64 timeout); + void Release(LimitableResource which, s64 value); + void Release(LimitableResource which, s64 value, s64 hint); + + std::string GetTypeName() const override { + return "KResourceLimit"; + } + std::string GetName() const override { + return GetTypeName(); + } + + static constexpr HandleType HANDLE_TYPE = HandleType::ResourceLimit; + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } + + virtual void Finalize() override {} + +private: + std::array(LimitableResource::Count)> limit_values{}; + std::array(LimitableResource::Count)> current_values{}; + std::array(LimitableResource::Count)> current_hints{}; + std::array(LimitableResource::Count)> peak_values{}; + mutable KLightLock m_lock; + s32 waiter_count{}; + KLightConditionVariable cond_var; + KernelCore& kernel; + Core::System& system; +}; +} // namespace Kernel diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index aa100e139..38fd8e500 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -21,6 +21,7 @@ #include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/k_condition_variable.h" +#include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" #include "core/hle/kernel/k_thread.h" @@ -29,7 +30,6 @@ #include "core/hle/kernel/memory/memory_layout.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/process.h" -#include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/svc_results.h" #include "core/hle/kernel/time_manager.h" #include "core/hle/result.h" @@ -247,7 +247,7 @@ void KThread::Finalize() { // Decrement the parent process's thread count. if (parent != nullptr) { parent->DecrementThreadCount(); - parent->GetResourceLimit()->Release(ResourceType::Threads, 1); + parent->GetResourceLimit()->Release(LimitableResource::ThreadCountMax, 1); } } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index df309d523..c66a993c2 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -28,6 +28,7 @@ #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" +#include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/kernel.h" @@ -36,7 +37,6 @@ #include "core/hle/kernel/memory/slab_heap.h" #include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/process.h" -#include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/service_thread.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/time_manager.h" @@ -66,7 +66,7 @@ struct KernelCore::Impl { is_phantom_mode_for_singlecore = false; InitializePhysicalCores(); - InitializeSystemResourceLimit(kernel); + InitializeSystemResourceLimit(kernel, system); InitializeMemoryLayout(); InitializePreemption(kernel); InitializeSchedulers(); @@ -131,19 +131,23 @@ struct KernelCore::Impl { } // Creates the default system resource limit - void InitializeSystemResourceLimit(KernelCore& kernel) { - system_resource_limit = ResourceLimit::Create(kernel); + void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) { + system_resource_limit = std::make_shared(kernel, system); // If setting the default system values fails, then something seriously wrong has occurred. - ASSERT(system_resource_limit->SetLimitValue(ResourceType::PhysicalMemory, 0x100000000) + ASSERT( + system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemoryMax, 0x100000000) + .IsSuccess()); + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 800) + .IsSuccess()); + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::EventCountMax, 700) + .IsSuccess()); + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 200) + .IsSuccess()); + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 900) .IsSuccess()); - ASSERT(system_resource_limit->SetLimitValue(ResourceType::Threads, 800).IsSuccess()); - ASSERT(system_resource_limit->SetLimitValue(ResourceType::Events, 700).IsSuccess()); - ASSERT(system_resource_limit->SetLimitValue(ResourceType::TransferMemory, 200).IsSuccess()); - ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess()); - if (!system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0) || - !system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0x60000)) { + if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, 0x60000)) { UNREACHABLE(); } } @@ -320,7 +324,7 @@ struct KernelCore::Impl { std::unique_ptr global_scheduler_context; Kernel::TimeManager time_manager; - std::shared_ptr system_resource_limit; + std::shared_ptr system_resource_limit; std::shared_ptr preemption_event; @@ -390,7 +394,7 @@ void KernelCore::Shutdown() { impl->Shutdown(); } -std::shared_ptr KernelCore::GetSystemResourceLimit() const { +std::shared_ptr KernelCore::GetSystemResourceLimit() const { return impl->system_resource_limit; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index e7c77727b..806a0d986 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -38,7 +38,7 @@ class GlobalSchedulerContext; class HandleTable; class PhysicalCore; class Process; -class ResourceLimit; +class KResourceLimit; class KScheduler; class SharedMemory; class ServiceThread; @@ -85,7 +85,7 @@ public: void Shutdown(); /// Retrieves a shared pointer to the system resource limit instance. - std::shared_ptr GetSystemResourceLimit() const; + std::shared_ptr GetSystemResourceLimit() const; /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. std::shared_ptr RetrieveThreadFromGlobalHandleTable(Handle handle) const; diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp index 080886554..d8c7d980a 100644 --- a/src/core/hle/kernel/memory/page_table.cpp +++ b/src/core/hle/kernel/memory/page_table.cpp @@ -7,6 +7,7 @@ #include "common/scope_exit.h" #include "core/core.h" #include "core/hle/kernel/errors.h" +#include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/memory/address_space_info.h" #include "core/hle/kernel/memory/memory_block.h" @@ -15,7 +16,6 @@ #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/memory/system_control.h" #include "core/hle/kernel/process.h" -#include "core/hle/kernel/resource_limit.h" #include "core/memory.h" namespace Kernel::Memory { @@ -413,8 +413,8 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { const std::size_t remaining_size{size - mapped_size}; const std::size_t remaining_pages{remaining_size / PageSize}; - if (process->GetResourceLimit() && - !process->GetResourceLimit()->Reserve(ResourceType::PhysicalMemory, remaining_size)) { + if (process->GetResourceLimit() && !process->GetResourceLimit()->Reserve( + LimitableResource::PhysicalMemoryMax, remaining_size)) { return ERR_RESOURCE_LIMIT_EXCEEDED; } @@ -422,7 +422,8 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { { auto block_guard = detail::ScopeExit([&] { system.Kernel().MemoryManager().Free(page_linked_list, remaining_pages, memory_pool); - process->GetResourceLimit()->Release(ResourceType::PhysicalMemory, remaining_size); + process->GetResourceLimit()->Release(LimitableResource::PhysicalMemoryMax, + remaining_size); }); CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, @@ -474,7 +475,7 @@ ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) { CASCADE_CODE(UnmapMemory(addr, size)); auto process{system.Kernel().CurrentProcess()}; - process->GetResourceLimit()->Release(ResourceType::PhysicalMemory, mapped_size); + process->GetResourceLimit()->Release(LimitableResource::PhysicalMemoryMax, mapped_size); physical_memory_usage -= mapped_size; return RESULT_SUCCESS; @@ -783,7 +784,7 @@ ResultVal PageTable::SetHeapSize(std::size_t size) { auto process{system.Kernel().CurrentProcess()}; if (process->GetResourceLimit() && delta != 0 && - !process->GetResourceLimit()->Reserve(ResourceType::PhysicalMemory, delta)) { + !process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemoryMax, delta)) { return ERR_RESOURCE_LIMIT_EXCEEDED; } diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 0edbfc4cc..6b63a32c5 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -15,6 +15,7 @@ #include "core/file_sys/program_metadata.h" #include "core/hle/kernel/code_set.h" #include "core/hle/kernel/errors.h" +#include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/kernel.h" @@ -22,7 +23,6 @@ #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/memory/slab_heap.h" #include "core/hle/kernel/process.h" -#include "core/hle/kernel/resource_limit.h" #include "core/hle/lock.h" #include "core/memory.h" #include "core/settings.h" @@ -116,7 +116,7 @@ std::shared_ptr Process::Create(Core::System& system, std::string name, std::shared_ptr process = std::make_shared(system); process->name = std::move(name); - process->resource_limit = ResourceLimit::Create(kernel); + process->resource_limit = std::make_shared(kernel, system); process->status = ProcessStatus::Created; process->program_id = 0; process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() @@ -132,7 +132,7 @@ std::shared_ptr Process::Create(Core::System& system, std::string name, return process; } -std::shared_ptr Process::GetResourceLimit() const { +std::shared_ptr Process::GetResourceLimit() const { return resource_limit; } @@ -154,7 +154,7 @@ void Process::DecrementThreadCount() { } u64 Process::GetTotalPhysicalMemoryAvailable() const { - const u64 capacity{resource_limit->GetCurrentResourceValue(ResourceType::PhysicalMemory) + + const u64 capacity{resource_limit->GetCurrentValue(LimitableResource::PhysicalMemoryMax) + page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + main_thread_stack_size}; @@ -308,13 +308,13 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, // Set initial resource limits resource_limit->SetLimitValue( - ResourceType::PhysicalMemory, + LimitableResource::PhysicalMemoryMax, kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application)); - resource_limit->SetLimitValue(ResourceType::Threads, 608); - resource_limit->SetLimitValue(ResourceType::Events, 700); - resource_limit->SetLimitValue(ResourceType::TransferMemory, 128); - resource_limit->SetLimitValue(ResourceType::Sessions, 894); - ASSERT(resource_limit->Reserve(ResourceType::PhysicalMemory, code_size)); + resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 608); + resource_limit->SetLimitValue(LimitableResource::EventCountMax, 700); + resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 128); + resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 894); + ASSERT(resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, code_size)); // Create TLS region tls_region_address = CreateTLSRegion(); @@ -331,8 +331,8 @@ void Process::Run(s32 main_thread_priority, u64 stack_size) { ChangeStatus(ProcessStatus::Running); SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top); - resource_limit->Reserve(ResourceType::Threads, 1); - resource_limit->Reserve(ResourceType::PhysicalMemory, main_thread_stack_size); + resource_limit->Reserve(LimitableResource::ThreadCountMax, 1); + resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, main_thread_stack_size); } void Process::PrepareForTermination() { diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 26e647743..c8af76ce8 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -29,7 +29,7 @@ class ProgramMetadata; namespace Kernel { class KernelCore; -class ResourceLimit; +class KResourceLimit; class KThread; class TLSPage; @@ -170,7 +170,7 @@ public: } /// Gets the resource limit descriptor for this process - std::shared_ptr GetResourceLimit() const; + std::shared_ptr GetResourceLimit() const; /// Gets the ideal CPU core ID for this process u8 GetIdealCoreId() const { @@ -402,7 +402,7 @@ private: u32 system_resource_size = 0; /// Resource limit descriptor for this process - std::shared_ptr resource_limit; + std::shared_ptr resource_limit; /// The ideal CPU core for this process, threads are scheduled on this core by default. u8 ideal_core = 0; diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp deleted file mode 100644 index 7bf50339d..000000000 --- a/src/core/hle/kernel/resource_limit.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/kernel/errors.h" -#include "core/hle/kernel/resource_limit.h" -#include "core/hle/result.h" - -namespace Kernel { -namespace { -constexpr std::size_t ResourceTypeToIndex(ResourceType type) { - return static_cast(type); -} -} // Anonymous namespace - -ResourceLimit::ResourceLimit(KernelCore& kernel) : Object{kernel} {} -ResourceLimit::~ResourceLimit() = default; - -bool ResourceLimit::Reserve(ResourceType resource, s64 amount) { - return Reserve(resource, amount, 10000000000); -} - -bool ResourceLimit::Reserve(ResourceType resource, s64 amount, u64 timeout) { - const std::size_t index{ResourceTypeToIndex(resource)}; - - s64 new_value = current[index] + amount; - if (new_value > limit[index] && available[index] + amount <= limit[index]) { - // TODO(bunnei): This is wrong for multicore, we should wait the calling thread for timeout - new_value = current[index] + amount; - } - - if (new_value <= limit[index]) { - current[index] = new_value; - return true; - } - return false; -} - -void ResourceLimit::Release(ResourceType resource, u64 amount) { - Release(resource, amount, amount); -} - -void ResourceLimit::Release(ResourceType resource, u64 used_amount, u64 available_amount) { - const std::size_t index{ResourceTypeToIndex(resource)}; - - current[index] -= used_amount; - available[index] -= available_amount; -} - -std::shared_ptr ResourceLimit::Create(KernelCore& kernel) { - return std::make_shared(kernel); -} - -s64 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const { - return limit.at(ResourceTypeToIndex(resource)) - current.at(ResourceTypeToIndex(resource)); -} - -s64 ResourceLimit::GetMaxResourceValue(ResourceType resource) const { - return limit.at(ResourceTypeToIndex(resource)); -} - -ResultCode ResourceLimit::SetLimitValue(ResourceType resource, s64 value) { - const std::size_t index{ResourceTypeToIndex(resource)}; - if (current[index] <= value) { - limit[index] = value; - return RESULT_SUCCESS; - } else { - LOG_ERROR(Kernel, "Limit value is too large! resource={}, value={}, index={}", resource, - value, index); - return ERR_INVALID_STATE; - } -} -} // namespace Kernel diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h deleted file mode 100644 index 464d4f2a6..000000000 --- a/src/core/hle/kernel/resource_limit.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include - -#include "common/common_types.h" -#include "core/hle/kernel/object.h" - -union ResultCode; - -namespace Kernel { - -class KernelCore; - -enum class ResourceType : u32 { - PhysicalMemory, - Threads, - Events, - TransferMemory, - Sessions, - - // Used as a count, not an actual type. - ResourceTypeCount -}; - -constexpr bool IsValidResourceType(ResourceType type) { - return type < ResourceType::ResourceTypeCount; -} - -class ResourceLimit final : public Object { -public: - explicit ResourceLimit(KernelCore& kernel); - ~ResourceLimit() override; - - /// Creates a resource limit object. - static std::shared_ptr Create(KernelCore& kernel); - - std::string GetTypeName() const override { - return "ResourceLimit"; - } - std::string GetName() const override { - return GetTypeName(); - } - - static constexpr HandleType HANDLE_TYPE = HandleType::ResourceLimit; - HandleType GetHandleType() const override { - return HANDLE_TYPE; - } - - bool Reserve(ResourceType resource, s64 amount); - bool Reserve(ResourceType resource, s64 amount, u64 timeout); - void Release(ResourceType resource, u64 amount); - void Release(ResourceType resource, u64 used_amount, u64 available_amount); - - /** - * Gets the current value for the specified resource. - * @param resource Requested resource type - * @returns The current value of the resource type - */ - s64 GetCurrentResourceValue(ResourceType resource) const; - - /** - * Gets the max value for the specified resource. - * @param resource Requested resource type - * @returns The max value of the resource type - */ - s64 GetMaxResourceValue(ResourceType resource) const; - - /** - * Sets the limit value for a given resource type. - * - * @param resource The resource type to apply the limit to. - * @param value The limit to apply to the given resource type. - * - * @return A result code indicating if setting the limit value - * was successful or not. - * - * @note The supplied limit value *must* be greater than or equal to - * the current resource value for the given resource type, - * otherwise ERR_INVALID_STATE will be returned. - */ - ResultCode SetLimitValue(ResourceType resource, s64 value); - - void Finalize() override {} - -private: - // TODO(Subv): Increment resource limit current values in their respective Kernel::T::Create - // functions - // - // Currently we have no way of distinguishing if a Create was called by the running application, - // or by a service module. Approach this once we have separated the service modules into their - // own processes - - using ResourceArray = - std::array(ResourceType::ResourceTypeCount)>; - - ResourceArray limit{}; - ResourceArray current{}; - ResourceArray available{}; -}; - -} // namespace Kernel diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 7fd514e9d..4bae37d10 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -26,6 +26,7 @@ #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/k_address_arbiter.h" #include "core/hle/kernel/k_condition_variable.h" +#include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" #include "core/hle/kernel/k_synchronization_object.h" @@ -37,7 +38,6 @@ #include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/readable_event.h" -#include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/svc.h" #include "core/hle/kernel/svc_results.h" @@ -141,7 +141,7 @@ enum class ResourceLimitValueType { ResultVal RetrieveResourceLimitValue(Core::System& system, Handle resource_limit, u32 resource_type, ResourceLimitValueType value_type) { std::lock_guard lock{HLE::g_hle_lock}; - const auto type = static_cast(resource_type); + const auto type = static_cast(resource_type); if (!IsValidResourceType(type)) { LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); return ERR_INVALID_ENUM_VALUE; @@ -151,7 +151,7 @@ ResultVal RetrieveResourceLimitValue(Core::System& system, Handle resource_ ASSERT(current_process != nullptr); const auto resource_limit_object = - current_process->GetHandleTable().Get(resource_limit); + current_process->GetHandleTable().Get(resource_limit); if (!resource_limit_object) { LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", resource_limit); @@ -159,10 +159,10 @@ ResultVal RetrieveResourceLimitValue(Core::System& system, Handle resource_ } if (value_type == ResourceLimitValueType::CurrentValue) { - return MakeResult(resource_limit_object->GetCurrentResourceValue(type)); + return MakeResult(resource_limit_object->GetCurrentValue(type)); } - return MakeResult(resource_limit_object->GetMaxResourceValue(type)); + return MakeResult(resource_limit_object->GetLimitValue(type)); } } // Anonymous namespace @@ -312,7 +312,8 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, return ERR_NOT_FOUND; } - ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Sessions, 1)); + ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(LimitableResource::SessionCountMax, + 1)); auto client_port = it->second; @@ -1450,7 +1451,10 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e Svc::ResultInvalidPriority); R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority); - ASSERT(process.GetResourceLimit()->Reserve(ResourceType::Threads, 1)); + ASSERT(process.GetResourceLimit()->Reserve( + LimitableResource::ThreadCountMax, 1, + system.CoreTiming().GetClockTicks() + + Core::Timing::msToCycles(std::chrono::milliseconds{100}))); std::shared_ptr thread; { @@ -1972,7 +1976,7 @@ static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) LOG_DEBUG(Kernel_SVC, "called"); auto& kernel = system.Kernel(); - auto resource_limit = ResourceLimit::Create(kernel); + auto resource_limit = std::make_shared(kernel, system); auto* const current_process = kernel.CurrentProcess(); ASSERT(current_process != nullptr); @@ -2019,7 +2023,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit, resource_type, value); - const auto type = static_cast(resource_type); + const auto type = static_cast(resource_type); if (!IsValidResourceType(type)) { LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); return ERR_INVALID_ENUM_VALUE; @@ -2029,7 +2033,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour ASSERT(current_process != nullptr); auto resource_limit_object = - current_process->GetHandleTable().Get(resource_limit); + current_process->GetHandleTable().Get(resource_limit); if (!resource_limit_object) { LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", resource_limit); @@ -2041,8 +2045,8 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour LOG_ERROR( Kernel_SVC, "Attempted to lower resource limit ({}) for category '{}' below its current value ({})", - resource_limit_object->GetMaxResourceValue(type), resource_type, - resource_limit_object->GetCurrentResourceValue(type)); + resource_limit_object->GetLimitValue(type), resource_type, + resource_limit_object->GetCurrentValue(type)); return set_result; } From 3bf62c7a8a68822e608c2f5f5748bd111d7ee4cf Mon Sep 17 00:00:00 2001 From: Chloe Marcec Date: Sat, 30 Jan 2021 21:03:10 +1100 Subject: [PATCH 2/8] Move to GetGlobalTimeNs, fix GetTotalPhysicalMemoryAvailable --- src/core/hle/kernel/k_resource_limit.cpp | 7 +++---- src/core/hle/kernel/process.cpp | 2 +- src/core/hle/kernel/svc.cpp | 7 +++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index f943d6562..b3076b030 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -14,8 +14,7 @@ namespace Kernel { namespace { -static const s64 DefaultTimeout = - Core::Timing::msToCycles(std::chrono::milliseconds{10000}); // 10 seconds +constexpr s64 DefaultTimeout = 10000000000; // 10 seconds } KResourceLimit::KResourceLimit(KernelCore& kernel, Core::System& system) @@ -86,7 +85,7 @@ ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { } bool KResourceLimit::Reserve(LimitableResource which, s64 value) { - return Reserve(which, value, system.CoreTiming().GetClockTicks() + DefaultTimeout); + return Reserve(which, value, system.CoreTiming().GetGlobalTimeNs().count() + DefaultTimeout); } bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { @@ -117,7 +116,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { } if (current_hints[index] + value <= limit_values[index] && - (timeout < 0 || system.CoreTiming().GetClockTicks() < static_cast(timeout))) { + (timeout < 0 || system.CoreTiming().GetGlobalTimeNs().count() < timeout)) { waiter_count++; cond_var.Wait(&m_lock, timeout); waiter_count--; diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 6b63a32c5..9efcb95f3 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -154,7 +154,7 @@ void Process::DecrementThreadCount() { } u64 Process::GetTotalPhysicalMemoryAvailable() const { - const u64 capacity{resource_limit->GetCurrentValue(LimitableResource::PhysicalMemoryMax) + + const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemoryMax) + page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + main_thread_stack_size}; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 4bae37d10..d89873104 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1451,10 +1451,9 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e Svc::ResultInvalidPriority); R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority); - ASSERT(process.GetResourceLimit()->Reserve( - LimitableResource::ThreadCountMax, 1, - system.CoreTiming().GetClockTicks() + - Core::Timing::msToCycles(std::chrono::milliseconds{100}))); + ASSERT(process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1, + system.CoreTiming().GetGlobalTimeNs().count() + + 100000000)); std::shared_ptr thread; { From 7791cfd9603d983fe58d3463e94d87448ad9e5a6 Mon Sep 17 00:00:00 2001 From: Chloe Marcec Date: Sat, 30 Jan 2021 21:19:49 +1100 Subject: [PATCH 3/8] Drop m_ from lock --- src/core/hle/kernel/k_resource_limit.cpp | 16 ++++++++-------- src/core/hle/kernel/k_resource_limit.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index b3076b030..65c30e9b3 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -18,14 +18,14 @@ constexpr s64 DefaultTimeout = 10000000000; // 10 seconds } KResourceLimit::KResourceLimit(KernelCore& kernel, Core::System& system) - : Object{kernel}, m_lock{kernel}, cond_var{kernel}, kernel{kernel}, system(system) {} + : Object{kernel}, lock{kernel}, cond_var{kernel}, kernel{kernel}, system(system) {} KResourceLimit::~KResourceLimit() = default; s64 KResourceLimit::GetLimitValue(LimitableResource which) const { const auto index = static_cast(which); s64 value{}; { - KScopedLightLock lk{m_lock}; + KScopedLightLock lk{lock}; value = limit_values[index]; ASSERT(value >= 0); ASSERT(current_values[index] <= limit_values[index]); @@ -51,7 +51,7 @@ s64 KResourceLimit::GetPeakValue(LimitableResource which) const { const auto index = static_cast(which); s64 value{}; { - KScopedLightLock lk{m_lock}; + KScopedLightLock lk{lock}; value = peak_values[index]; ASSERT(value >= 0); ASSERT(current_values[index] <= limit_values[index]); @@ -64,7 +64,7 @@ s64 KResourceLimit::GetFreeValue(LimitableResource which) const { const auto index = static_cast(which); s64 value{}; { - KScopedLightLock lk(m_lock); + KScopedLightLock lk(lock); ASSERT(current_values[index] >= 0); ASSERT(current_values[index] <= limit_values[index]); ASSERT(current_hints[index] <= current_values[index]); @@ -76,7 +76,7 @@ s64 KResourceLimit::GetFreeValue(LimitableResource which) const { ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { const auto index = static_cast(which); - KScopedLightLock lk(m_lock); + KScopedLightLock lk(lock); R_UNLESS(current_values[index] <= value, Svc::ResultInvalidState); limit_values[index] = value; @@ -91,7 +91,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value) { bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { ASSERT(value >= 0); const auto index = static_cast(which); - KScopedLightLock lk(m_lock); + KScopedLightLock lk(lock); ASSERT(current_hints[index] <= current_values[index]); if (current_hints[index] >= limit_values[index]) { @@ -118,7 +118,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { if (current_hints[index] + value <= limit_values[index] && (timeout < 0 || system.CoreTiming().GetGlobalTimeNs().count() < timeout)) { waiter_count++; - cond_var.Wait(&m_lock, timeout); + cond_var.Wait(&lock, timeout); waiter_count--; } else { break; @@ -137,7 +137,7 @@ void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) { ASSERT(hint >= 0); const auto index = static_cast(which); - KScopedLightLock lk(m_lock); + KScopedLightLock lk(lock); ASSERT(current_values[index] <= limit_values[index]); ASSERT(current_hints[index] <= current_values[index]); ASSERT(value <= current_values[index]); diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index 84c59177c..5f916c99c 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h @@ -71,7 +71,7 @@ private: std::array(LimitableResource::Count)> current_values{}; std::array(LimitableResource::Count)> current_hints{}; std::array(LimitableResource::Count)> peak_values{}; - mutable KLightLock m_lock; + mutable KLightLock lock; s32 waiter_count{}; KLightConditionVariable cond_var; KernelCore& kernel; From 56742c6222b7185b43a3463955c58a142ed33c1e Mon Sep 17 00:00:00 2001 From: Chloe Marcec Date: Sat, 30 Jan 2021 21:20:35 +1100 Subject: [PATCH 4/8] cleanup commenting --- src/core/hle/kernel/k_resource_limit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index 65c30e9b3..1bcc390ff 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -98,12 +98,12 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { return false; } - /* Loop until we reserve or run out of time. */ + // Loop until we reserve or run out of time. while (true) { ASSERT(current_values[index] <= limit_values[index]); ASSERT(current_hints[index] <= current_values[index]); - /* If we would overflow, don't allow to succeed. */ + // If we would overflow, don't allow to succeed. if (current_values[index] + value <= current_values[index]) { break; } From ee333e063d9de4b36ccbc0c5b7b3e323bff9eda3 Mon Sep 17 00:00:00 2001 From: Chloe Marcec Date: Sat, 30 Jan 2021 21:51:22 +1100 Subject: [PATCH 5/8] fix compile error --- src/core/hle/kernel/k_resource_limit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index 1bcc390ff..3cee8d0f7 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -38,7 +38,7 @@ s64 KResourceLimit::GetCurrentValue(LimitableResource which) const { const auto index = static_cast(which); s64 value{}; { - KScopedLightLock lk{m_lock}; + KScopedLightLock lk{lock}; value = current_values[index]; ASSERT(value >= 0); ASSERT(current_values[index] <= limit_values[index]); From 9e4b2d60bc4827552b0d74675ae03fec06f73452 Mon Sep 17 00:00:00 2001 From: Chloe Marcec Date: Tue, 2 Feb 2021 13:23:00 +1100 Subject: [PATCH 6/8] Address issues --- .../hle/kernel/k_light_condition_variable.h | 21 ++++++++----------- src/core/hle/kernel/k_resource_limit.cpp | 2 -- src/core/hle/kernel/k_resource_limit.h | 11 +++++----- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h index 26573a239..26d94d7c0 100644 --- a/src/core/hle/kernel/k_light_condition_variable.h +++ b/src/core/hle/kernel/k_light_condition_variable.h @@ -17,44 +17,41 @@ namespace Kernel { class KernelCore; class KLightConditionVariable { -private: - KThreadQueue m_thread_queue; - public: - KLightConditionVariable(KernelCore& kernel) : m_thread_queue(kernel), kernel(kernel) {} + explicit KLightConditionVariable(KernelCore& kernel) : thread_queue(kernel), kernel(kernel) {} - void Wait(KLightLock* lock, s64 timeout = -1ll) { + void Wait(KLightLock* lock, s64 timeout = -1) { WaitImpl(lock, timeout); lock->Lock(); } void Broadcast() { KScopedSchedulerLock lk{kernel}; - while (m_thread_queue.WakeupFrontThread() != nullptr) { - /* We want to signal all threads, and so should continue waking up until there's nothing - * to wake. */ + while (thread_queue.WakeupFrontThread() != nullptr) { + // We want to signal all threads, and so should continue waking up until there's nothing + // to wake. } } private: void WaitImpl(KLightLock* lock, s64 timeout) { KThread* owner = GetCurrentThreadPointer(kernel); - // KHardwareTimer* timer; - /* Sleep the thread. */ + // Sleep the thread. { KScopedSchedulerLockAndSleep lk(kernel, owner, timeout); lock->Unlock(); - if (!m_thread_queue.SleepThread(owner)) { + if (!thread_queue.SleepThread(owner)) { lk.CancelSleep(); return; } } - /* Cancel the task that the sleep setup. */ + // Cancel the task that the sleep setup. kernel.TimeManager().UnscheduleTimeEvent(owner); } KernelCore& kernel; + KThreadQueue thread_queue; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index 3cee8d0f7..ab2ab683f 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -13,9 +13,7 @@ #include "core/hle/kernel/svc_results.h" namespace Kernel { -namespace { constexpr s64 DefaultTimeout = 10000000000; // 10 seconds -} KResourceLimit::KResourceLimit(KernelCore& kernel, Core::System& system) : Object{kernel}, lock{kernel}, cond_var{kernel}, kernel{kernel}, system(system) {} diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index 5f916c99c..6b3437ea6 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h @@ -37,7 +37,7 @@ constexpr bool IsValidResourceType(LimitableResource type) { class KResourceLimit final : public Object { public: - KResourceLimit(KernelCore& kernel, Core::System& system); + explicit KResourceLimit(KernelCore& kernel, Core::System& system); ~KResourceLimit(); s64 GetLimitValue(LimitableResource which) const; @@ -67,10 +67,11 @@ public: virtual void Finalize() override {} private: - std::array(LimitableResource::Count)> limit_values{}; - std::array(LimitableResource::Count)> current_values{}; - std::array(LimitableResource::Count)> current_hints{}; - std::array(LimitableResource::Count)> peak_values{}; + using ResourceArray = std::array(LimitableResource::Count)>; + ResourceArray limit_values{}; + ResourceArray current_values{}; + ResourceArray current_hints{}; + ResourceArray peak_values{}; mutable KLightLock lock; s32 waiter_count{}; KLightConditionVariable cond_var; From 64c35827051f12232caba423cc43364d471ee001 Mon Sep 17 00:00:00 2001 From: Chloe Marcec Date: Tue, 2 Feb 2021 13:23:34 +1100 Subject: [PATCH 7/8] Compile error --- src/core/hle/kernel/k_light_condition_variable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h index 26d94d7c0..362d0db28 100644 --- a/src/core/hle/kernel/k_light_condition_variable.h +++ b/src/core/hle/kernel/k_light_condition_variable.h @@ -51,7 +51,7 @@ private: // Cancel the task that the sleep setup. kernel.TimeManager().UnscheduleTimeEvent(owner); } - KernelCore& kernel; KThreadQueue thread_queue; + KernelCore& kernel; }; } // namespace Kernel From 2c6e94049362f592bfb578a2b078f6f3067ed0d8 Mon Sep 17 00:00:00 2001 From: Chloe Marcec Date: Wed, 3 Feb 2021 12:55:16 +1100 Subject: [PATCH 8/8] Simplify limitableresource names --- src/core/hle/kernel/k_resource_limit.h | 10 +++++----- src/core/hle/kernel/k_thread.cpp | 2 +- src/core/hle/kernel/kernel.cpp | 16 ++++++---------- src/core/hle/kernel/memory/page_table.cpp | 11 +++++------ src/core/hle/kernel/process.cpp | 18 +++++++++--------- src/core/hle/kernel/svc.cpp | 8 +++----- 6 files changed, 29 insertions(+), 36 deletions(-) diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index 6b3437ea6..58ae456f1 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h @@ -22,11 +22,11 @@ class System; namespace Kernel { class KernelCore; enum class LimitableResource : u32 { - PhysicalMemoryMax = 0, - ThreadCountMax = 1, - EventCountMax = 2, - TransferMemoryCountMax = 3, - SessionCountMax = 4, + PhysicalMemory = 0, + Threads = 1, + Events = 2, + TransferMemory = 3, + Sessions = 4, Count, }; diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 38fd8e500..b59259c4f 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -247,7 +247,7 @@ void KThread::Finalize() { // Decrement the parent process's thread count. if (parent != nullptr) { parent->DecrementThreadCount(); - parent->GetResourceLimit()->Release(LimitableResource::ThreadCountMax, 1); + parent->GetResourceLimit()->Release(LimitableResource::Threads, 1); } } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index c66a993c2..b20c2d13a 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -135,19 +135,15 @@ struct KernelCore::Impl { system_resource_limit = std::make_shared(kernel, system); // If setting the default system values fails, then something seriously wrong has occurred. - ASSERT( - system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemoryMax, 0x100000000) - .IsSuccess()); - ASSERT(system_resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 800) + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000) .IsSuccess()); - ASSERT(system_resource_limit->SetLimitValue(LimitableResource::EventCountMax, 700) - .IsSuccess()); - ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 200) - .IsSuccess()); - ASSERT(system_resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 900) + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 700).IsSuccess()); + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) .IsSuccess()); + ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 900).IsSuccess()); - if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, 0x60000)) { + if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, 0x60000)) { UNREACHABLE(); } } diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp index d8c7d980a..7de91c768 100644 --- a/src/core/hle/kernel/memory/page_table.cpp +++ b/src/core/hle/kernel/memory/page_table.cpp @@ -413,8 +413,8 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { const std::size_t remaining_size{size - mapped_size}; const std::size_t remaining_pages{remaining_size / PageSize}; - if (process->GetResourceLimit() && !process->GetResourceLimit()->Reserve( - LimitableResource::PhysicalMemoryMax, remaining_size)) { + if (process->GetResourceLimit() && + !process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemory, remaining_size)) { return ERR_RESOURCE_LIMIT_EXCEEDED; } @@ -422,8 +422,7 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { { auto block_guard = detail::ScopeExit([&] { system.Kernel().MemoryManager().Free(page_linked_list, remaining_pages, memory_pool); - process->GetResourceLimit()->Release(LimitableResource::PhysicalMemoryMax, - remaining_size); + process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, remaining_size); }); CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, @@ -475,7 +474,7 @@ ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) { CASCADE_CODE(UnmapMemory(addr, size)); auto process{system.Kernel().CurrentProcess()}; - process->GetResourceLimit()->Release(LimitableResource::PhysicalMemoryMax, mapped_size); + process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size); physical_memory_usage -= mapped_size; return RESULT_SUCCESS; @@ -784,7 +783,7 @@ ResultVal PageTable::SetHeapSize(std::size_t size) { auto process{system.Kernel().CurrentProcess()}; if (process->GetResourceLimit() && delta != 0 && - !process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemoryMax, delta)) { + !process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemory, delta)) { return ERR_RESOURCE_LIMIT_EXCEEDED; } diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 9efcb95f3..afdb27c54 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -154,7 +154,7 @@ void Process::DecrementThreadCount() { } u64 Process::GetTotalPhysicalMemoryAvailable() const { - const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemoryMax) + + const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + main_thread_stack_size}; @@ -308,13 +308,13 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, // Set initial resource limits resource_limit->SetLimitValue( - LimitableResource::PhysicalMemoryMax, + LimitableResource::PhysicalMemory, kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application)); - resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 608); - resource_limit->SetLimitValue(LimitableResource::EventCountMax, 700); - resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 128); - resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 894); - ASSERT(resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, code_size)); + resource_limit->SetLimitValue(LimitableResource::Threads, 608); + resource_limit->SetLimitValue(LimitableResource::Events, 700); + resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128); + resource_limit->SetLimitValue(LimitableResource::Sessions, 894); + ASSERT(resource_limit->Reserve(LimitableResource::PhysicalMemory, code_size)); // Create TLS region tls_region_address = CreateTLSRegion(); @@ -331,8 +331,8 @@ void Process::Run(s32 main_thread_priority, u64 stack_size) { ChangeStatus(ProcessStatus::Running); SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top); - resource_limit->Reserve(LimitableResource::ThreadCountMax, 1); - resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, main_thread_stack_size); + resource_limit->Reserve(LimitableResource::Threads, 1); + resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size); } void Process::PrepareForTermination() { diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index d89873104..74eb90100 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -312,8 +312,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, return ERR_NOT_FOUND; } - ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(LimitableResource::SessionCountMax, - 1)); + ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(LimitableResource::Sessions, 1)); auto client_port = it->second; @@ -1451,9 +1450,8 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e Svc::ResultInvalidPriority); R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority); - ASSERT(process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1, - system.CoreTiming().GetGlobalTimeNs().count() + - 100000000)); + ASSERT(process.GetResourceLimit()->Reserve( + LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000)); std::shared_ptr thread; {