pm: implement correct application thread boosting mechanism

This commit is contained in:
Michael Scire 2019-07-02 21:27:53 -07:00 committed by SciresM
parent 2d0c881ffe
commit 08ad48fbf3
6 changed files with 50 additions and 26 deletions

View file

@ -669,8 +669,8 @@ namespace sts::pm::impl {
return resource::BoostSystemMemoryResourceLimit(boost_size); return resource::BoostSystemMemoryResourceLimit(boost_size);
} }
Result BoostSystemThreadResourceLimit() { Result BoostApplicationThreadResourceLimit() {
return resource::BoostSystemThreadResourceLimit(); return resource::BoostApplicationThreadResourceLimit();
} }
Result AtmosphereGetCurrentLimitInfo(u64 *out_cur_val, u64 *out_lim_val, u32 group, u32 resource) { Result AtmosphereGetCurrentLimitInfo(u64 *out_cur_val, u64 *out_lim_val, u32 group, u32 resource) {

View file

@ -54,7 +54,7 @@ namespace sts::pm::impl {
/* Resource Limit API. */ /* Resource Limit API. */
Result BoostSystemMemoryResourceLimit(u64 boost_size); Result BoostSystemMemoryResourceLimit(u64 boost_size);
Result BoostSystemThreadResourceLimit(); Result BoostApplicationThreadResourceLimit();
Result AtmosphereGetCurrentLimitInfo(u64 *out_cur_val, u64 *out_lim_val, u32 group, u32 resource); Result AtmosphereGetCurrentLimitInfo(u64 *out_cur_val, u64 *out_lim_val, u32 group, u32 resource);
} }

View file

@ -49,6 +49,7 @@ namespace sts::pm::resource {
Handle g_resource_limit_handles[ResourceLimitGroup_Count]; Handle g_resource_limit_handles[ResourceLimitGroup_Count];
spl::MemoryArrangement g_memory_arrangement = spl::MemoryArrangement_Standard; spl::MemoryArrangement g_memory_arrangement = spl::MemoryArrangement_Standard;
u64 g_system_memory_boost_size = 0; u64 g_system_memory_boost_size = 0;
u64 g_extra_application_threads_available = 0;
u64 g_resource_limits[ResourceLimitGroup_Count][LimitableResource_Count] = { u64 g_resource_limits[ResourceLimitGroup_Count][LimitableResource_Count] = {
[ResourceLimitGroup_System] = { [ResourceLimitGroup_System] = {
@ -205,8 +206,25 @@ namespace sts::pm::resource {
g_resource_limits[ResourceLimitGroup_System][LimitableResource_Sessions] += ExtraSystemSessionCount600; g_resource_limits[ResourceLimitGroup_System][LimitableResource_Sessions] += ExtraSystemSessionCount600;
} }
/* 7.0.0+: Nintendo restricts the number of system threads here, from 0x260 -> 0x60. */ /* 7.0.0+: Calculate the number of extra application threads available. */
/* We will not do this. */ 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. */ /* Choose and initialize memory arrangement. */
if (firmware_version >= FirmwareVersion_600) { if (firmware_version >= FirmwareVersion_600) {
@ -248,7 +266,7 @@ namespace sts::pm::resource {
/* Actually set resource limits. */ /* Actually set resource limits. */
{ {
std::scoped_lock<HosMutex> lk(g_resource_limit_lock); std::scoped_lock lk(g_resource_limit_lock);
for (size_t group = 0; group < ResourceLimitGroup_Count; group++) { for (size_t group = 0; group < ResourceLimitGroup_Count; group++) {
R_ASSERT(SetResourceLimitLimitValues(static_cast<ResourceLimitGroup>(group), g_memory_resource_limits[g_memory_arrangement][group])); R_ASSERT(SetResourceLimitLimitValues(static_cast<ResourceLimitGroup>(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; const u64 new_app_size = g_memory_resource_limits[g_memory_arrangement][ResourceLimitGroup_Application] - boost_size;
{ {
std::scoped_lock<HosMutex> lk(g_resource_limit_lock); std::scoped_lock lk(g_resource_limit_lock);
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) { if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) {
/* Starting in 5.0.0, PM does not allow for only one of the sets to fail. */ /* 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; return ResultSuccess;
} }
Result BoostSystemThreadResourceLimit() { Result BoostApplicationThreadResourceLimit() {
/* Starting in 7.0.0, Nintendo reduces the number of system threads from 0x260 to 0x60, */ std::scoped_lock lk(g_resource_limit_lock);
/* Until this command is called to double that amount to 0xC0. */ /* Set new limit. */
/* We will simply not reduce the number of system threads available for no reason. */ 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; return ResultSuccess;
} }

View file

@ -25,7 +25,7 @@ namespace sts::pm::resource {
/* Resource API. */ /* Resource API. */
Result InitializeResourceManager(); Result InitializeResourceManager();
Result BoostSystemMemoryResourceLimit(u64 boost_size); Result BoostSystemMemoryResourceLimit(u64 boost_size);
Result BoostSystemThreadResourceLimit(); Result BoostApplicationThreadResourceLimit();
Handle GetResourceLimitHandle(ResourceLimitGroup group); Handle GetResourceLimitHandle(ResourceLimitGroup group);
Handle GetResourceLimitHandle(const ldr::ProgramInfo *info); Handle GetResourceLimitHandle(const ldr::ProgramInfo *info);
void WaitResourceAvailable(const ldr::ProgramInfo *info); void WaitResourceAvailable(const ldr::ProgramInfo *info);

View file

@ -65,8 +65,8 @@ namespace sts::pm::shell {
return impl::BoostSystemMemoryResourceLimit(boost_size); return impl::BoostSystemMemoryResourceLimit(boost_size);
} }
Result ShellServiceBase::BoostSystemThreadResourceLimit() { Result ShellServiceBase::BoostApplicationThreadResourceLimit() {
return impl::BoostSystemThreadResourceLimit(); return impl::BoostApplicationThreadResourceLimit();
} }
void ShellServiceBase::GetBootFinishedEventHandle(Out<CopiedHandle> out) { void ShellServiceBase::GetBootFinishedEventHandle(Out<CopiedHandle> out) {

View file

@ -35,7 +35,7 @@ namespace sts::pm::shell {
virtual void NotifyBootFinished(); virtual void NotifyBootFinished();
virtual Result GetApplicationProcessIdForShell(Out<u64> out); virtual Result GetApplicationProcessIdForShell(Out<u64> out);
virtual Result BoostSystemMemoryResourceLimit(u64 boost_size); virtual Result BoostSystemMemoryResourceLimit(u64 boost_size);
virtual Result BoostSystemThreadResourceLimit(); virtual Result BoostApplicationThreadResourceLimit();
virtual void GetBootFinishedEventHandle(Out<CopiedHandle> out); virtual void GetBootFinishedEventHandle(Out<CopiedHandle> out);
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
@ -47,16 +47,16 @@ namespace sts::pm::shell {
class ShellService final : public ShellServiceBase { class ShellService final : public ShellServiceBase {
private: private:
enum class CommandId { enum class CommandId {
LaunchTitle = 0, LaunchTitle = 0,
TerminateProcess = 1, TerminateProcess = 1,
TerminateTitle = 2, TerminateTitle = 2,
GetProcessEventHandle = 3, GetProcessEventHandle = 3,
GetProcessEventInfo = 4, GetProcessEventInfo = 4,
NotifyBootFinished = 5, NotifyBootFinished = 5,
GetApplicationProcessIdForShell = 6, GetApplicationProcessIdForShell = 6,
BoostSystemMemoryResourceLimit = 7, BoostSystemMemoryResourceLimit = 7,
BoostSystemThreadResourceLimit = 8, BoostApplicationThreadResourceLimit = 8,
GetBootFinishedEventHandle = 9, GetBootFinishedEventHandle = 9,
}; };
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
@ -71,7 +71,7 @@ namespace sts::pm::shell {
MAKE_SERVICE_COMMAND_META(ShellService, BoostSystemMemoryResourceLimit), MAKE_SERVICE_COMMAND_META(ShellService, BoostSystemMemoryResourceLimit),
/* 7.0.0-* */ /* 7.0.0-* */
MAKE_SERVICE_COMMAND_META(ShellService, BoostSystemThreadResourceLimit, FirmwareVersion_700), MAKE_SERVICE_COMMAND_META(ShellService, BoostApplicationThreadResourceLimit, FirmwareVersion_700),
/* 8.0.0-* */ /* 8.0.0-* */
MAKE_SERVICE_COMMAND_META(ShellService, GetBootFinishedEventHandle, FirmwareVersion_800), MAKE_SERVICE_COMMAND_META(ShellService, GetBootFinishedEventHandle, FirmwareVersion_800),