From 08ad48fbf31ff90ff0f646e18cf8b339b58362d4 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 2 Jul 2019 21:27:53 -0700 Subject: [PATCH] pm: implement correct application thread boosting mechanism --- .../pm/source/impl/pm_process_manager.cpp | 4 +- .../pm/source/impl/pm_process_manager.hpp | 2 +- .../pm/source/impl/pm_resource_manager.cpp | 40 +++++++++++++++---- .../pm/source/impl/pm_resource_manager.hpp | 2 +- stratosphere/pm/source/pm_shell_service.cpp | 4 +- stratosphere/pm/source/pm_shell_service.hpp | 24 +++++------ 6 files changed, 50 insertions(+), 26 deletions(-) diff --git a/stratosphere/pm/source/impl/pm_process_manager.cpp b/stratosphere/pm/source/impl/pm_process_manager.cpp index 17bc69c99..1b75e7f60 100644 --- a/stratosphere/pm/source/impl/pm_process_manager.cpp +++ b/stratosphere/pm/source/impl/pm_process_manager.cpp @@ -669,8 +669,8 @@ namespace sts::pm::impl { return resource::BoostSystemMemoryResourceLimit(boost_size); } - Result BoostSystemThreadResourceLimit() { - return resource::BoostSystemThreadResourceLimit(); + Result BoostApplicationThreadResourceLimit() { + return resource::BoostApplicationThreadResourceLimit(); } Result AtmosphereGetCurrentLimitInfo(u64 *out_cur_val, u64 *out_lim_val, u32 group, u32 resource) { diff --git a/stratosphere/pm/source/impl/pm_process_manager.hpp b/stratosphere/pm/source/impl/pm_process_manager.hpp index 0d810fb35..bc576da78 100644 --- a/stratosphere/pm/source/impl/pm_process_manager.hpp +++ b/stratosphere/pm/source/impl/pm_process_manager.hpp @@ -54,7 +54,7 @@ namespace sts::pm::impl { /* Resource Limit API. */ Result BoostSystemMemoryResourceLimit(u64 boost_size); - Result BoostSystemThreadResourceLimit(); + Result BoostApplicationThreadResourceLimit(); Result AtmosphereGetCurrentLimitInfo(u64 *out_cur_val, u64 *out_lim_val, u32 group, u32 resource); } diff --git a/stratosphere/pm/source/impl/pm_resource_manager.cpp b/stratosphere/pm/source/impl/pm_resource_manager.cpp index e6ed25a5f..657746fee 100644 --- a/stratosphere/pm/source/impl/pm_resource_manager.cpp +++ b/stratosphere/pm/source/impl/pm_resource_manager.cpp @@ -49,6 +49,7 @@ namespace sts::pm::resource { Handle g_resource_limit_handles[ResourceLimitGroup_Count]; spl::MemoryArrangement g_memory_arrangement = spl::MemoryArrangement_Standard; u64 g_system_memory_boost_size = 0; + u64 g_extra_application_threads_available = 0; u64 g_resource_limits[ResourceLimitGroup_Count][LimitableResource_Count] = { [ResourceLimitGroup_System] = { @@ -205,8 +206,25 @@ namespace sts::pm::resource { g_resource_limits[ResourceLimitGroup_System][LimitableResource_Sessions] += ExtraSystemSessionCount600; } - /* 7.0.0+: Nintendo restricts the number of system threads here, from 0x260 -> 0x60. */ - /* We will not do this. */ + /* 7.0.0+: Calculate the number of extra application threads available. */ + if (GetRuntimeFirmwareVersion() >= FirmwareVersion_700) { + /* See how many threads we have available. */ + u64 total_threads_available = 0; + R_ASSERT(svcGetResourceLimitLimitValue(&total_threads_available, GetResourceLimitHandle(ResourceLimitGroup_System), LimitableResource_Threads)); + + /* See how many threads we're expecting. */ + const size_t total_threads_allocated = g_resource_limits[ResourceLimitGroup_System][LimitableResource_Threads] - + g_resource_limits[ResourceLimitGroup_Application][LimitableResource_Threads] - + g_resource_limits[ResourceLimitGroup_Applet][LimitableResource_Threads]; + + /* Ensure we don't over-commit threads. */ + if (total_threads_available < total_threads_allocated) { + std::abort(); + } + + /* Set number of extra threads. */ + g_extra_application_threads_available = total_threads_available; + } /* Choose and initialize memory arrangement. */ if (firmware_version >= FirmwareVersion_600) { @@ -248,7 +266,7 @@ namespace sts::pm::resource { /* Actually set resource limits. */ { - std::scoped_lock lk(g_resource_limit_lock); + std::scoped_lock lk(g_resource_limit_lock); for (size_t group = 0; group < ResourceLimitGroup_Count; group++) { R_ASSERT(SetResourceLimitLimitValues(static_cast(group), g_memory_resource_limits[g_memory_arrangement][group])); @@ -266,7 +284,7 @@ namespace sts::pm::resource { const u64 new_app_size = g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_Application] - boost_size; { - std::scoped_lock lk(g_resource_limit_lock); + std::scoped_lock lk(g_resource_limit_lock); if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) { /* Starting in 5.0.0, PM does not allow for only one of the sets to fail. */ @@ -294,10 +312,16 @@ namespace sts::pm::resource { return ResultSuccess; } - Result BoostSystemThreadResourceLimit() { - /* Starting in 7.0.0, Nintendo reduces the number of system threads from 0x260 to 0x60, */ - /* Until this command is called to double that amount to 0xC0. */ - /* We will simply not reduce the number of system threads available for no reason. */ + Result BoostApplicationThreadResourceLimit() { + std::scoped_lock lk(g_resource_limit_lock); + /* Set new limit. */ + const u64 new_thread_count = g_resource_limits[ResourceLimitGroup_Application][LimitableResource_Threads] + g_extra_application_threads_available; + R_TRY(svcSetResourceLimitLimitValue(GetResourceLimitHandle(ResourceLimitGroup_Application), LimitableResource_Threads, new_thread_count)); + + /* Record that we did so. */ + g_resource_limits[ResourceLimitGroup_Application][LimitableResource_Threads] = new_thread_count; + g_extra_application_threads_available = 0; + return ResultSuccess; } diff --git a/stratosphere/pm/source/impl/pm_resource_manager.hpp b/stratosphere/pm/source/impl/pm_resource_manager.hpp index b43f95154..667d03e74 100644 --- a/stratosphere/pm/source/impl/pm_resource_manager.hpp +++ b/stratosphere/pm/source/impl/pm_resource_manager.hpp @@ -25,7 +25,7 @@ namespace sts::pm::resource { /* Resource API. */ Result InitializeResourceManager(); Result BoostSystemMemoryResourceLimit(u64 boost_size); - Result BoostSystemThreadResourceLimit(); + Result BoostApplicationThreadResourceLimit(); Handle GetResourceLimitHandle(ResourceLimitGroup group); Handle GetResourceLimitHandle(const ldr::ProgramInfo *info); void WaitResourceAvailable(const ldr::ProgramInfo *info); diff --git a/stratosphere/pm/source/pm_shell_service.cpp b/stratosphere/pm/source/pm_shell_service.cpp index c82803f4e..8a59c3f52 100644 --- a/stratosphere/pm/source/pm_shell_service.cpp +++ b/stratosphere/pm/source/pm_shell_service.cpp @@ -65,8 +65,8 @@ namespace sts::pm::shell { return impl::BoostSystemMemoryResourceLimit(boost_size); } - Result ShellServiceBase::BoostSystemThreadResourceLimit() { - return impl::BoostSystemThreadResourceLimit(); + Result ShellServiceBase::BoostApplicationThreadResourceLimit() { + return impl::BoostApplicationThreadResourceLimit(); } void ShellServiceBase::GetBootFinishedEventHandle(Out out) { diff --git a/stratosphere/pm/source/pm_shell_service.hpp b/stratosphere/pm/source/pm_shell_service.hpp index 101293044..cca6f2a1e 100644 --- a/stratosphere/pm/source/pm_shell_service.hpp +++ b/stratosphere/pm/source/pm_shell_service.hpp @@ -35,7 +35,7 @@ namespace sts::pm::shell { virtual void NotifyBootFinished(); virtual Result GetApplicationProcessIdForShell(Out out); virtual Result BoostSystemMemoryResourceLimit(u64 boost_size); - virtual Result BoostSystemThreadResourceLimit(); + virtual Result BoostApplicationThreadResourceLimit(); virtual void GetBootFinishedEventHandle(Out out); public: DEFINE_SERVICE_DISPATCH_TABLE { @@ -47,16 +47,16 @@ namespace sts::pm::shell { class ShellService final : public ShellServiceBase { private: enum class CommandId { - LaunchTitle = 0, - TerminateProcess = 1, - TerminateTitle = 2, - GetProcessEventHandle = 3, - GetProcessEventInfo = 4, - NotifyBootFinished = 5, - GetApplicationProcessIdForShell = 6, - BoostSystemMemoryResourceLimit = 7, - BoostSystemThreadResourceLimit = 8, - GetBootFinishedEventHandle = 9, + LaunchTitle = 0, + TerminateProcess = 1, + TerminateTitle = 2, + GetProcessEventHandle = 3, + GetProcessEventInfo = 4, + NotifyBootFinished = 5, + GetApplicationProcessIdForShell = 6, + BoostSystemMemoryResourceLimit = 7, + BoostApplicationThreadResourceLimit = 8, + GetBootFinishedEventHandle = 9, }; public: DEFINE_SERVICE_DISPATCH_TABLE { @@ -71,7 +71,7 @@ namespace sts::pm::shell { MAKE_SERVICE_COMMAND_META(ShellService, BoostSystemMemoryResourceLimit), /* 7.0.0-* */ - MAKE_SERVICE_COMMAND_META(ShellService, BoostSystemThreadResourceLimit, FirmwareVersion_700), + MAKE_SERVICE_COMMAND_META(ShellService, BoostApplicationThreadResourceLimit, FirmwareVersion_700), /* 8.0.0-* */ MAKE_SERVICE_COMMAND_META(ShellService, GetBootFinishedEventHandle, FirmwareVersion_800),