pm/kern: update for 14.0.0

This commit is contained in:
Michael Scire 2022-03-21 23:52:16 -07:00
parent 40601cc74c
commit df1b133bc7
23 changed files with 260 additions and 96 deletions

View file

@ -49,8 +49,8 @@ namespace ams::kern {
constexpr size_t KernelSlabHeapGapsSizeMax = 2_MB - 64_KB;
constexpr size_t KernelSlabHeapSize = KernelSlabHeapDataSize + KernelSlabHeapGapsSizeMax;
/* NOTE: This is calculated from KThread slab counts, assuming KThread size <= 0x860. */
constexpr size_t KernelSlabHeapAdditionalSize = 0x68000;
/* NOTE: This is calculated from KThread slab counts, assuming KThread size <= 0x800. */
constexpr size_t KernelSlabHeapAdditionalSize = 0x148000;
constexpr size_t KernelResourceSize = KernelPageTableHeapSize + KernelInitialPageHeapSize + KernelSlabHeapSize;

View file

@ -72,7 +72,7 @@ namespace ams::kern::init {
constexpr size_t SlabCountKIoPool = 1;
constexpr size_t SlabCountKIoRegion = 6;
constexpr size_t SlabCountExtraKThread = 160;
constexpr size_t SlabCountExtraKThread = (1024 + 256 + 256) - SlabCountKThread;
namespace test {

View file

@ -27,6 +27,7 @@
AMS_SF_METHOD_INFO(C, H, 4, Result, GetApplicationProcessId, (sf::Out<os::ProcessId> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 5, Result, HookToCreateApplicationProcess, (sf::OutCopyHandle out_hook), (out_hook)) \
AMS_SF_METHOD_INFO(C, H, 6, Result, ClearHook, (u32 which), (which), hos::Version_6_0_0) \
AMS_SF_METHOD_INFO(C, H, 7, Result, GetProgramId, (sf::Out<ncm::ProgramId> out, os::ProcessId process_id), (out, process_id)) \
AMS_SF_METHOD_INFO(C, H, 65000, Result, AtmosphereGetProcessInfo, (sf::OutCopyHandle out_process_handle, sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id), (out_process_handle, out_loc, out_status, process_id)) \
AMS_SF_METHOD_INFO(C, H, 65001, Result, AtmosphereGetCurrentLimitInfo, (sf::Out<s64> out_cur_val, sf::Out<s64> out_lim_val, u32 group, u32 resource), (out_cur_val, out_lim_val, group, resource))
@ -40,6 +41,7 @@ AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IDebugMonitorInterface, AMS_PM_I_DEBUG_MO
AMS_SF_METHOD_INFO(C, H, 4, Result, HookToCreateProcess, (sf::OutCopyHandle out_hook, ncm::ProgramId program_id), (out_hook, program_id)) \
AMS_SF_METHOD_INFO(C, H, 5, Result, GetApplicationProcessId, (sf::Out<os::ProcessId> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 6, Result, HookToCreateApplicationProcess, (sf::OutCopyHandle out_hook), (out_hook)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, GetProgramId, (sf::Out<ncm::ProgramId> out, os::ProcessId process_id), (out, process_id)) \
AMS_SF_METHOD_INFO(C, H, 65000, Result, AtmosphereGetProcessInfo, (sf::OutCopyHandle out_process_handle, sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id), (out_process_handle, out_loc, out_status, process_id)) \
AMS_SF_METHOD_INFO(C, H, 65001, Result, AtmosphereGetCurrentLimitInfo, (sf::Out<s64> out_cur_val, sf::Out<s64> out_lim_val, u32 group, u32 resource), (out_cur_val, out_lim_val, group, resource))

View file

@ -19,10 +19,12 @@
#include <stratosphere/pm/pm_types.hpp>
#include <stratosphere/sf.hpp>
#define AMS_PM_I_INFORMATION_INTERFACE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, GetProgramId, (sf::Out<ncm::ProgramId> out, os::ProcessId process_id), (out, process_id)) \
AMS_SF_METHOD_INFO(C, H, 65000, Result, AtmosphereGetProcessId, (sf::Out<os::ProcessId> out, ncm::ProgramId program_id), (out, program_id)) \
AMS_SF_METHOD_INFO(C, H, 65001, Result, AtmosphereHasLaunchedBootProgram, (sf::Out<bool> out, ncm::ProgramId program_id), (out, program_id)) \
AMS_SF_METHOD_INFO(C, H, 65002, Result, AtmosphereGetProcessInfo, (sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id), (out_loc, out_status, process_id))
#define AMS_PM_I_INFORMATION_INTERFACE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, GetProgramId, (sf::Out<ncm::ProgramId> out, os::ProcessId process_id), (out, process_id)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, GetAppletCurrentResourceLimitValues, (sf::Out<pm::ResourceLimitValues> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, GetAppletPeakResourceLimitValues, (sf::Out<pm::ResourceLimitValues> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 65000, Result, AtmosphereGetProcessId, (sf::Out<os::ProcessId> out, ncm::ProgramId program_id), (out, program_id)) \
AMS_SF_METHOD_INFO(C, H, 65001, Result, AtmosphereHasLaunchedBootProgram, (sf::Out<bool> out, ncm::ProgramId program_id), (out, program_id)) \
AMS_SF_METHOD_INFO(C, H, 65002, Result, AtmosphereGetProcessInfo, (sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id), (out_loc, out_status, process_id))
AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IInformationInterface, AMS_PM_I_INFORMATION_INTERFACE_INTERFACE_INFO)

View file

@ -19,17 +19,18 @@
#include <stratosphere/pm/pm_types.hpp>
#include <stratosphere/sf.hpp>
#define AMS_PM_I_SHELL_INTERFACE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, LaunchProgram, (sf::Out<os::ProcessId> out_process_id, const ncm::ProgramLocation &loc, u32 flags), (out_process_id, loc, flags)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, TerminateProcess, (os::ProcessId process_id), (process_id)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, TerminateProgram, (ncm::ProgramId program_id), (program_id)) \
AMS_SF_METHOD_INFO(C, H, 3, void, GetProcessEventHandle, (sf::OutCopyHandle out), (out)) \
AMS_SF_METHOD_INFO(C, H, 4, void, GetProcessEventInfo, (sf::Out<pm::ProcessEventInfo> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 5, void, NotifyBootFinished, (), ()) \
AMS_SF_METHOD_INFO(C, H, 6, Result, GetApplicationProcessIdForShell, (sf::Out<os::ProcessId> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, BoostSystemMemoryResourceLimit, (u64 boost_size), (boost_size)) \
AMS_SF_METHOD_INFO(C, H, 8, Result, BoostApplicationThreadResourceLimit, (), (), hos::Version_7_0_0) \
AMS_SF_METHOD_INFO(C, H, 9, void, GetBootFinishedEventHandle, (sf::OutCopyHandle out), (out), hos::Version_8_0_0)
#define AMS_PM_I_SHELL_INTERFACE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, LaunchProgram, (sf::Out<os::ProcessId> out_process_id, const ncm::ProgramLocation &loc, u32 flags), (out_process_id, loc, flags)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, TerminateProcess, (os::ProcessId process_id), (process_id)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, TerminateProgram, (ncm::ProgramId program_id), (program_id)) \
AMS_SF_METHOD_INFO(C, H, 3, void, GetProcessEventHandle, (sf::OutCopyHandle out), (out)) \
AMS_SF_METHOD_INFO(C, H, 4, void, GetProcessEventInfo, (sf::Out<pm::ProcessEventInfo> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 5, void, NotifyBootFinished, (), ()) \
AMS_SF_METHOD_INFO(C, H, 6, Result, GetApplicationProcessIdForShell, (sf::Out<os::ProcessId> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, BoostSystemMemoryResourceLimit, (u64 boost_size), (boost_size)) \
AMS_SF_METHOD_INFO(C, H, 8, Result, BoostApplicationThreadResourceLimit, (), (), hos::Version_7_0_0) \
AMS_SF_METHOD_INFO(C, H, 9, void, GetBootFinishedEventHandle, (sf::OutCopyHandle out), (out), hos::Version_8_0_0) \
AMS_SF_METHOD_INFO(C, H, 10, Result, BoostSystemThreadResourceLimit, (), ())
AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IShellInterface, AMS_PM_I_SHELL_INTERFACE_INTERFACE_INFO)

View file

@ -24,6 +24,7 @@ namespace ams::pm::dmnt {
/* Debug Monitor API. */
Result StartProcess(os::ProcessId process_id);
Result GetProgramId(ncm::ProgramId *out_program_id, os::ProcessId process_id);
Result GetProcessId(os::ProcessId *out_process_id, const ncm::ProgramId program_id);
Result GetApplicationProcessId(os::ProcessId *out_process_id);
Result HookToCreateApplicationProcess(os::NativeHandle *out_handle);

View file

@ -29,6 +29,9 @@ namespace ams::pm::info {
Result GetProcessId(os::ProcessId *out_process_id, ncm::ProgramId program_id);
Result HasLaunchedBootProgram(bool *out, ncm::ProgramId program_id);
Result GetAppletCurrentResourceLimitValues(pm::ResourceLimitValues *out);
Result GetAppletPeakResourceLimitValues(pm::ResourceLimitValues *out);
Result GetProcessInfo(ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id);
/* Information convenience API. */

View file

@ -30,5 +30,6 @@ namespace ams::pm::shell {
Result GetApplicationProcessIdForShell(os::ProcessId *out);
Result BoostSystemMemoryResourceLimit(u64 size);
Result EnableApplicationExtraThread();
Result EnableSystemExtraThread();
}

View file

@ -52,6 +52,14 @@ namespace ams::pm {
LaunchFlagsDeprecated_SignalOnStart = (1 << 5),
};
struct ResourceLimitValues {
u64 physical_memory;
u32 thread_count;
u32 event_count;
u32 transfer_memory_count;
u32 session_count;
};
constexpr inline u32 LaunchFlagsMask = (1 << 6) - 1;
enum class ProcessEvent : u32 {

View file

@ -25,6 +25,12 @@ namespace ams::pm::dmnt {
return pmdmntStartProcess(static_cast<u64>(process_id));
}
Result GetProgramId(ncm::ProgramId *out_program_id, os::ProcessId process_id) {
/* TODO: return return pmdmntGetProgramId(reinterpret_cast<u64 *>(out_program_id), static_cast<u64>(process_id)); */
AMS_UNUSED(out_program_id, process_id);
AMS_ABORT("TODO");
}
Result GetProcessId(os::ProcessId *out_process_id, const ncm::ProgramId program_id) {
return pmdmntGetProcessId(reinterpret_cast<u64 *>(out_process_id), static_cast<u64>(program_id));
}

View file

@ -28,6 +28,18 @@ namespace ams::pm::info {
return pminfoAtmosphereGetProcessId(reinterpret_cast<u64 *>(out_process_id), static_cast<u64>(program_id));
}
Result GetAppletCurrentResourceLimitValues(pm::ResourceLimitValues *out) {
/* TODO: return pminfoGetAppletCurrentResourceLimitValues(reinterpret_cast<PmResourceLimitValues *>(out)); */
AMS_UNUSED(out);
AMS_ABORT("TODO");
}
Result GetAppletPeakResourceLimitValues(pm::ResourceLimitValues *out) {
/* TODO: return pminfoGetAppletPeakResourceLimitValues(reinterpret_cast<PmResourceLimitValues *>(out)); */
AMS_UNUSED(out);
AMS_ABORT("TODO");
}
Result GetProcessInfo(ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id) {
*out_loc = {};
*out_status = {};

View file

@ -55,4 +55,9 @@ namespace ams::pm::shell {
}
#endif
Result EnableSystemExtraThread() {
/* TODO: return ::pmshellEnableSystemExtraThread(); */
AMS_ABORT("TODO");
}
}

View file

@ -209,7 +209,7 @@ namespace ams::pm::impl {
Result StartProcess(ProcessInfo *process_info, const ldr::ProgramInfo *program_info) {
R_TRY(svc::StartProcess(process_info->GetHandle(), program_info->main_thread_priority, program_info->default_cpu_id, program_info->main_thread_stack_size));
process_info->SetState(svc::ProcessState_Running);
return ResultSuccess();
R_SUCCEED();
}
void CleanupProcessInfo(ProcessListAccessor &list, ProcessInfo *process_info) {
@ -416,7 +416,7 @@ namespace ams::pm::impl {
/* Start thread. */
os::StartThread(std::addressof(g_process_track_thread));
return ResultSuccess();
R_SUCCEED();
}
/* Process Management. */
@ -433,7 +433,7 @@ namespace ams::pm::impl {
g_process_launch_start_event.Signal();
g_process_launch_finish_event.Wait();
return g_process_launch_result;
R_RETURN(g_process_launch_result);
}
Result StartProcess(os::ProcessId process_id) {
@ -445,7 +445,7 @@ namespace ams::pm::impl {
ldr::ProgramInfo program_info;
R_TRY(ldr::pm::GetProgramInfo(std::addressof(program_info), process_info->GetProgramLocation()));
return StartProcess(process_info, std::addressof(program_info));
R_RETURN(StartProcess(process_info, std::addressof(program_info)));
}
Result TerminateProcess(os::ProcessId process_id) {
@ -454,7 +454,7 @@ namespace ams::pm::impl {
auto process_info = list->Find(process_id);
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
return svc::TerminateProcess(process_info->GetHandle());
R_RETURN(svc::TerminateProcess(process_info->GetHandle()));
}
Result TerminateProgram(ncm::ProgramId program_id) {
@ -463,12 +463,12 @@ namespace ams::pm::impl {
auto process_info = list->Find(program_id);
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
return svc::TerminateProcess(process_info->GetHandle());
R_RETURN(svc::TerminateProcess(process_info->GetHandle()));
}
Result GetProcessEventHandle(os::NativeHandle *out) {
*out = os::GetReadableHandleOfSystemEvent(std::addressof(g_process_event));
return ResultSuccess();
R_SUCCEED();
}
Result GetProcessEventInfo(ProcessEventInfo *out) {
@ -482,7 +482,7 @@ namespace ams::pm::impl {
process.ClearStartedStateChanged();
out->event = GetProcessEventValue(ProcessEvent::Started);
out->process_id = process.GetProcessId();
return ResultSuccess();
R_SUCCEED();
}
if (process.HasSuspendedStateChanged()) {
process.ClearSuspendedStateChanged();
@ -492,18 +492,18 @@ namespace ams::pm::impl {
out->event = GetProcessEventValue(ProcessEvent::DebugRunning);
}
out->process_id = process.GetProcessId();
return ResultSuccess();
R_SUCCEED();
}
if (process.HasExceptionOccurred()) {
process.ClearExceptionOccurred();
out->event = GetProcessEventValue(ProcessEvent::Exception);
out->process_id = process.GetProcessId();
return ResultSuccess();
R_SUCCEED();
}
if (hos::GetVersion() < hos::Version_5_0_0 && process.ShouldSignalOnExit() && process.HasTerminated()) {
out->event = GetProcessEventValue(ProcessEvent::Exited);
out->process_id = process.GetProcessId();
return ResultSuccess();
R_SUCCEED();
}
}
}
@ -518,13 +518,13 @@ namespace ams::pm::impl {
out->process_id = process_info.GetProcessId();
CleanupProcessInfo(dead_list, std::addressof(process_info));
return ResultSuccess();
R_SUCCEED();
}
}
out->process_id = os::ProcessId{};
out->event = GetProcessEventValue(ProcessEvent::None);
return ResultSuccess();
R_SUCCEED();
}
Result CleanupProcess(os::ProcessId process_id) {
@ -535,7 +535,7 @@ namespace ams::pm::impl {
R_UNLESS(process_info->HasTerminated(), pm::ResultNotTerminated());
CleanupProcessInfo(list, process_info);
return ResultSuccess();
R_SUCCEED();
}
Result ClearExceptionOccurred(os::ProcessId process_id) {
@ -545,7 +545,7 @@ namespace ams::pm::impl {
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
process_info->ClearExceptionOccurred();
return ResultSuccess();
R_SUCCEED();
}
/* Information Getters. */
@ -553,7 +553,7 @@ namespace ams::pm::impl {
/* This function was always stubbed... */
AMS_UNUSED(out_buf, max_out_count, unused);
*out_count = 0;
return ResultSuccess();
R_SUCCEED();
}
Result GetExceptionProcessIdList(u32 *out_count, os::ProcessId *out_process_ids, size_t max_out_count) {
@ -574,7 +574,7 @@ namespace ams::pm::impl {
}
*out_count = static_cast<u32>(count);
return ResultSuccess();
R_SUCCEED();
}
Result GetProcessId(os::ProcessId *out, ncm::ProgramId program_id) {
@ -584,7 +584,7 @@ namespace ams::pm::impl {
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
*out = process_info->GetProcessId();
return ResultSuccess();
R_SUCCEED();
}
Result GetProgramId(ncm::ProgramId *out, os::ProcessId process_id) {
@ -594,7 +594,7 @@ namespace ams::pm::impl {
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
*out = process_info->GetProgramLocation().program_id;
return ResultSuccess();
R_SUCCEED();
}
Result GetApplicationProcessId(os::ProcessId *out_process_id) {
@ -603,11 +603,11 @@ namespace ams::pm::impl {
for (auto &process : *list) {
if (process.IsApplication()) {
*out_process_id = process.GetProcessId();
return ResultSuccess();
R_SUCCEED();
}
}
return pm::ResultProcessNotFound();
R_THROW(pm::ResultProcessNotFound());
}
Result AtmosphereGetProcessInfo(os::NativeHandle *out_process_handle, ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id) {
@ -619,7 +619,7 @@ namespace ams::pm::impl {
*out_process_handle = process_info->GetHandle();
*out_loc = process_info->GetProgramLocation();
*out_status = process_info->GetOverrideStatus();
return ResultSuccess();
R_SUCCEED();
}
/* Hook API. */
@ -632,7 +632,7 @@ namespace ams::pm::impl {
}
*out_hook = os::GetReadableHandleOfSystemEvent(std::addressof(g_hook_to_create_process_event));
return ResultSuccess();
R_SUCCEED();
}
Result HookToCreateApplicationProcess(os::NativeHandle *out_hook) {
@ -644,7 +644,7 @@ namespace ams::pm::impl {
}
*out_hook = os::GetReadableHandleOfSystemEvent(std::addressof(g_hook_to_create_application_process_event));
return ResultSuccess();
R_SUCCEED();
}
Result ClearHook(u32 which) {
@ -654,7 +654,7 @@ namespace ams::pm::impl {
if (which & HookType_Application) {
g_application_hook = false;
}
return ResultSuccess();
R_SUCCEED();
}
/* Boot API. */
@ -676,7 +676,7 @@ namespace ams::pm::impl {
s_has_boot_finished = true;
os::SignalSystemEvent(std::addressof(g_boot_finished_event));
}
return ResultSuccess();
R_SUCCEED();
}
Result GetBootFinishedEventHandle(os::NativeHandle *out) {
@ -685,20 +685,32 @@ namespace ams::pm::impl {
/* We will signal it always, but only allow this function to succeed on safe mode. */
AMS_ABORT_UNLESS(spl::IsRecoveryBoot());
*out = os::GetReadableHandleOfSystemEvent(std::addressof(g_boot_finished_event));
return ResultSuccess();
R_SUCCEED();
}
/* Resource Limit API. */
Result BoostSystemMemoryResourceLimit(u64 boost_size) {
return resource::BoostSystemMemoryResourceLimit(boost_size);
R_RETURN(resource::BoostSystemMemoryResourceLimit(boost_size));
}
Result BoostApplicationThreadResourceLimit() {
return resource::BoostApplicationThreadResourceLimit();
R_RETURN(resource::BoostApplicationThreadResourceLimit());
}
Result BoostSystemThreadResourceLimit() {
R_RETURN(resource::BoostSystemThreadResourceLimit());
}
Result GetAppletCurrentResourceLimitValues(pm::ResourceLimitValues *out) {
R_RETURN(resource::GetCurrentResourceLimitValues(ResourceLimitGroup_Applet, out));
}
Result GetAppletPeakResourceLimitValues(pm::ResourceLimitValues *out) {
R_RETURN(resource::GetPeakResourceLimitValues(ResourceLimitGroup_Applet, out));
}
Result AtmosphereGetCurrentLimitInfo(s64 *out_cur_val, s64 *out_lim_val, u32 group, u32 resource) {
return resource::GetResourceLimitValues(out_cur_val, out_lim_val, static_cast<ResourceLimitGroup>(group), static_cast<svc::LimitableResource>(resource));
R_RETURN(resource::GetResourceLimitValues(out_cur_val, out_lim_val, static_cast<ResourceLimitGroup>(group), static_cast<svc::LimitableResource>(resource)));
}
}

View file

@ -51,6 +51,9 @@ namespace ams::pm::impl {
/* Resource Limit API. */
Result BoostSystemMemoryResourceLimit(u64 boost_size);
Result BoostApplicationThreadResourceLimit();
Result BoostSystemThreadResourceLimit();
Result GetAppletCurrentResourceLimitValues(pm::ResourceLimitValues *out);
Result GetAppletPeakResourceLimitValues(pm::ResourceLimitValues *out);
Result AtmosphereGetCurrentLimitInfo(s64 *out_cur_val, s64 *out_lim_val, u32 group, u32 resource);
}

View file

@ -35,31 +35,44 @@ namespace ams::pm::resource {
/* Atmosphere always allocates extra memory for system usage. */
constexpr size_t ExtraSystemMemorySizeAtmosphere = 24_MB;
/* Desired extra threads. */
constexpr u64 BaseApplicationThreads = 96;
constexpr u64 BaseAppletThreads = 96;
constexpr u64 BaseSystemThreads = 800 - BaseAppletThreads - BaseApplicationThreads;
constexpr s64 ExtraSystemThreads = 1024 - BaseSystemThreads;
constexpr s64 ExtraApplicationThreads = 256 - BaseApplicationThreads;
constexpr s64 ExtraAppletThreads = 256 - BaseAppletThreads;
static_assert(ExtraSystemThreads >= 0);
static_assert(ExtraApplicationThreads >= 0);
static_assert(ExtraAppletThreads >= 0);
/* Globals. */
constinit os::SdkMutex g_resource_limit_lock;
constinit os::NativeHandle g_resource_limit_handles[ResourceLimitGroup_Count];
constinit spl::MemoryArrangement g_memory_arrangement = spl::MemoryArrangement_Standard;
constinit u64 g_system_memory_boost_size = 0;
constinit u64 g_extra_application_threads_available = 0;
constinit u64 g_extra_threads_available[ResourceLimitGroup_Count];
constinit u64 g_resource_limits[ResourceLimitGroup_Count][svc::LimitableResource_Count] = {
[ResourceLimitGroup_System] = {
[svc::LimitableResource_PhysicalMemoryMax] = 0, /* Initialized dynamically later. */
[svc::LimitableResource_ThreadCountMax] = 608,
[svc::LimitableResource_ThreadCountMax] = BaseSystemThreads,
[svc::LimitableResource_EventCountMax] = 0, /* Initialized dynamically later. */
[svc::LimitableResource_TransferMemoryCountMax] = 0, /* Initialized dynamically later. */
[svc::LimitableResource_SessionCountMax] = 0, /* Initialized dynamically later. */
},
[ResourceLimitGroup_Application] = {
[svc::LimitableResource_PhysicalMemoryMax] = 0, /* Initialized dynamically later. */
[svc::LimitableResource_ThreadCountMax] = 96,
[svc::LimitableResource_ThreadCountMax] = BaseApplicationThreads,
[svc::LimitableResource_EventCountMax] = 0,
[svc::LimitableResource_TransferMemoryCountMax] = 32,
[svc::LimitableResource_SessionCountMax] = 1,
},
[ResourceLimitGroup_Applet] = {
[svc::LimitableResource_PhysicalMemoryMax] = 0, /* Initialized dynamically later. */
[svc::LimitableResource_ThreadCountMax] = 96,
[svc::LimitableResource_ThreadCountMax] = BaseAppletThreads,
[svc::LimitableResource_EventCountMax] = 0,
[svc::LimitableResource_TransferMemoryCountMax] = 32,
[svc::LimitableResource_SessionCountMax] = 5,
@ -118,7 +131,8 @@ namespace ams::pm::resource {
}
R_TRY(svc::SetResourceLimitLimitValue(GetResourceLimitHandle(group), resource, g_resource_limits[group][resource]));
}
return ResultSuccess();
R_SUCCEED();
}
inline ResourceLimitGroup GetResourceLimitGroup(const ldr::ProgramInfo *info) {
@ -166,6 +180,46 @@ namespace ams::pm::resource {
return value != 0;
}
ALWAYS_INLINE Result BoostThreadResourceLimitLocked(ResourceLimitGroup group) {
AMS_ASSERT(g_resource_limit_lock.IsLockedByCurrentThread());
/* Set new limit. */
const s64 new_thread_count = g_resource_limits[group][svc::LimitableResource_ThreadCountMax] + g_extra_threads_available[group];
R_TRY(svc::SetResourceLimitLimitValue(GetResourceLimitHandle(group), svc::LimitableResource_ThreadCountMax, new_thread_count));
/* Record that we did so. */
g_resource_limits[group][svc::LimitableResource_ThreadCountMax] = new_thread_count;
g_extra_threads_available[group] = 0;
R_SUCCEED();
}
template<auto GetResourceLimitValueImpl>
ALWAYS_INLINE Result GetResourceLimitValuesImpl(ResourceLimitGroup group, pm::ResourceLimitValues *out) {
/* Sanity check group. */
AMS_ABORT_UNLESS(group < ResourceLimitGroup_Count);
/* Get handle. */
const auto handle = GetResourceLimitHandle(group);
/* Get values. */
int64_t values[svc::LimitableResource_Count];
R_ABORT_UNLESS(GetResourceLimitValueImpl(std::addressof(values[svc::LimitableResource_PhysicalMemoryMax]), handle, svc::LimitableResource_PhysicalMemoryMax));
R_ABORT_UNLESS(GetResourceLimitValueImpl(std::addressof(values[svc::LimitableResource_ThreadCountMax]), handle, svc::LimitableResource_ThreadCountMax));
R_ABORT_UNLESS(GetResourceLimitValueImpl(std::addressof(values[svc::LimitableResource_EventCountMax]), handle, svc::LimitableResource_EventCountMax));
R_ABORT_UNLESS(GetResourceLimitValueImpl(std::addressof(values[svc::LimitableResource_TransferMemoryCountMax]), handle, svc::LimitableResource_TransferMemoryCountMax));
R_ABORT_UNLESS(GetResourceLimitValueImpl(std::addressof(values[svc::LimitableResource_SessionCountMax]), handle, svc::LimitableResource_SessionCountMax));
/* Set to output. */
out->physical_memory = values[svc::LimitableResource_PhysicalMemoryMax];
out->thread_count = values[svc::LimitableResource_ThreadCountMax];
out->event_count = values[svc::LimitableResource_EventCountMax];
out->transfer_memory_count = values[svc::LimitableResource_TransferMemoryCountMax];
out->session_count = values[svc::LimitableResource_SessionCountMax];
R_SUCCEED();
}
}
/* Resource API. */
@ -225,8 +279,20 @@ namespace ams::pm::resource {
const s64 required_threads = g_resource_limits[ResourceLimitGroup_System][svc::LimitableResource_ThreadCountMax] + g_resource_limits[ResourceLimitGroup_Application][svc::LimitableResource_ThreadCountMax] + g_resource_limits[ResourceLimitGroup_Applet][svc::LimitableResource_ThreadCountMax];
AMS_ABORT_UNLESS(total_threads >= required_threads);
/* Set the number of extra application threads. */
g_extra_application_threads_available = total_threads - required_threads;
/* Set the number of extra threads. */
const s64 extra_threads = total_threads - required_threads;
if constexpr (true /* TODO: Should we expose the old "all extra threads are application" behavior? Seems pointless. */) {
if (extra_threads > 0) {
/* If we have any extra threads at all, require that we have enough. */
AMS_ABORT_UNLESS(extra_threads >= (ExtraSystemThreads + ExtraApplicationThreads + ExtraAppletThreads));
g_extra_threads_available[ResourceLimitGroup_System] += ExtraSystemThreads;
g_extra_threads_available[ResourceLimitGroup_Application] += ExtraApplicationThreads;
g_extra_threads_available[ResourceLimitGroup_Applet] += ExtraAppletThreads;
}
} else {
g_extra_threads_available[ResourceLimitGroup_Application] = extra_threads;
}
}
/* Choose and initialize memory arrangement. */
@ -282,7 +348,7 @@ namespace ams::pm::resource {
}
}
return ResultSuccess();
R_SUCCEED();
}
Result BoostSystemMemoryResourceLimit(u64 boost_size) {
@ -316,21 +382,26 @@ namespace ams::pm::resource {
g_system_memory_boost_size = boost_size;
}
return ResultSuccess();
R_SUCCEED();
}
Result BoostApplicationThreadResourceLimit() {
std::scoped_lock lk(g_resource_limit_lock);
/* Set new limit. */
const s64 new_thread_count = g_resource_limits[ResourceLimitGroup_Application][svc::LimitableResource_ThreadCountMax] + g_extra_application_threads_available;
R_TRY(svc::SetResourceLimitLimitValue(GetResourceLimitHandle(ResourceLimitGroup_Application), svc::LimitableResource_ThreadCountMax, new_thread_count));
/* Boost the limit. */
R_TRY(BoostThreadResourceLimitLocked(ResourceLimitGroup_Application));
/* Record that we did so. */
g_resource_limits[ResourceLimitGroup_Application][svc::LimitableResource_ThreadCountMax] = new_thread_count;
g_extra_application_threads_available = 0;
R_SUCCEED();
}
return ResultSuccess();
Result BoostSystemThreadResourceLimit() {
std::scoped_lock lk(g_resource_limit_lock);
/* Boost the limits. */
R_TRY(BoostThreadResourceLimitLocked(ResourceLimitGroup_Applet));
R_TRY(BoostThreadResourceLimitLocked(ResourceLimitGroup_System));
R_SUCCEED();
}
os::NativeHandle GetResourceLimitHandle(ResourceLimitGroup group) {
@ -350,6 +421,18 @@ namespace ams::pm::resource {
}
}
Result GetCurrentResourceLimitValues(ResourceLimitGroup group, pm::ResourceLimitValues *out) {
R_RETURN(GetResourceLimitValuesImpl<::ams::svc::GetResourceLimitCurrentValue>(group, out));
}
Result GetPeakResourceLimitValues(ResourceLimitGroup group, pm::ResourceLimitValues *out) {
R_RETURN(GetResourceLimitValuesImpl<::ams::svc::GetResourceLimitPeakValue>(group, out));
}
Result GetLimitResourceLimitValues(ResourceLimitGroup group, pm::ResourceLimitValues *out) {
R_RETURN(GetResourceLimitValuesImpl<::ams::svc::GetResourceLimitLimitValue>(group, out));
}
Result GetResourceLimitValues(s64 *out_cur, s64 *out_lim, ResourceLimitGroup group, svc::LimitableResource resource) {
/* Do not allow out of bounds access. */
AMS_ABORT_UNLESS(group < ResourceLimitGroup_Count);
@ -359,7 +442,7 @@ namespace ams::pm::resource {
R_TRY(svc::GetResourceLimitCurrentValue(out_cur, reslimit_hnd, resource));
R_TRY(svc::GetResourceLimitLimitValue(out_lim, reslimit_hnd, resource));
return ResultSuccess();
R_SUCCEED();
}
}

View file

@ -22,12 +22,17 @@ namespace ams::pm::resource {
Result InitializeResourceManager();
Result BoostSystemMemoryResourceLimit(u64 boost_size);
Result BoostApplicationThreadResourceLimit();
Result BoostSystemThreadResourceLimit();
os::NativeHandle GetResourceLimitHandle(ResourceLimitGroup group);
os::NativeHandle GetResourceLimitHandle(const ldr::ProgramInfo *info);
void WaitResourceAvailable(const ldr::ProgramInfo *info);
Result GetCurrentResourceLimitValues(ResourceLimitGroup group, pm::ResourceLimitValues *out);
Result GetPeakResourceLimitValues(ResourceLimitGroup group, pm::ResourceLimitValues *out);
Result GetLimitResourceLimitValues(ResourceLimitGroup group, pm::ResourceLimitValues *out);
Result GetResourceLimitValues(s64 *out_cur, s64 *out_lim, ResourceLimitGroup group, svc::LimitableResource resource);
}

View file

@ -22,20 +22,20 @@ namespace ams::pm {
/* Actual command implementations. */
Result DebugMonitorService::GetModuleIdList(sf::Out<u32> out_count, const sf::OutBuffer &out_buf, u64 unused) {
R_UNLESS(out_buf.GetSize() <= std::numeric_limits<s32>::max(), pm::ResultInvalidSize());
return impl::GetModuleIdList(out_count.GetPointer(), out_buf.GetPointer(), out_buf.GetSize(), unused);
R_RETURN(impl::GetModuleIdList(out_count.GetPointer(), out_buf.GetPointer(), out_buf.GetSize(), unused));
}
Result DebugMonitorService::GetExceptionProcessIdList(sf::Out<u32> out_count, const sf::OutArray<os::ProcessId> &out_process_ids) {
R_UNLESS(out_process_ids.GetSize() <= std::numeric_limits<s32>::max(), pm::ResultInvalidSize());
return impl::GetExceptionProcessIdList(out_count.GetPointer(), out_process_ids.GetPointer(), out_process_ids.GetSize());
R_RETURN(impl::GetExceptionProcessIdList(out_count.GetPointer(), out_process_ids.GetPointer(), out_process_ids.GetSize()));
}
Result DebugMonitorService::StartProcess(os::ProcessId process_id) {
return impl::StartProcess(process_id);
R_RETURN(impl::StartProcess(process_id));
}
Result DebugMonitorService::GetProcessId(sf::Out<os::ProcessId> out, ncm::ProgramId program_id) {
return impl::GetProcessId(out.GetPointer(), program_id);
R_RETURN(impl::GetProcessId(out.GetPointer(), program_id));
}
Result DebugMonitorService::HookToCreateProcess(sf::OutCopyHandle out_hook, ncm::ProgramId program_id) {
@ -43,11 +43,11 @@ namespace ams::pm {
R_TRY(impl::HookToCreateProcess(std::addressof(event_handle), program_id));
out_hook.SetValue(event_handle, false);
return ResultSuccess();
R_SUCCEED();
}
Result DebugMonitorService::GetApplicationProcessId(sf::Out<os::ProcessId> out) {
return impl::GetApplicationProcessId(out.GetPointer());
R_RETURN(impl::GetApplicationProcessId(out.GetPointer()));
}
Result DebugMonitorService::HookToCreateApplicationProcess(sf::OutCopyHandle out_hook) {
@ -55,11 +55,15 @@ namespace ams::pm {
R_TRY(impl::HookToCreateApplicationProcess(std::addressof(event_handle)));
out_hook.SetValue(event_handle, false);
return ResultSuccess();
R_SUCCEED();
}
Result DebugMonitorService::ClearHook(u32 which) {
return impl::ClearHook(which);
R_RETURN(impl::ClearHook(which));
}
Result DebugMonitorService::GetProgramId(sf::Out<ncm::ProgramId> out, os::ProcessId process_id) {
R_RETURN(impl::GetProgramId(out.GetPointer(), process_id));
}
/* Atmosphere extension commands. */
@ -68,11 +72,11 @@ namespace ams::pm {
R_TRY(impl::AtmosphereGetProcessInfo(std::addressof(process_handle), out_loc.GetPointer(), out_status.GetPointer(), process_id));
out_process_handle.SetValue(process_handle, false);
return ResultSuccess();
R_SUCCEED();
}
Result DebugMonitorService::AtmosphereGetCurrentLimitInfo(sf::Out<s64> out_cur_val, sf::Out<s64> out_lim_val, u32 group, u32 resource) {
return impl::AtmosphereGetCurrentLimitInfo(out_cur_val.GetPointer(), out_lim_val.GetPointer(), group, resource);
R_RETURN(impl::AtmosphereGetCurrentLimitInfo(out_cur_val.GetPointer(), out_lim_val.GetPointer(), group, resource));
}
}

View file

@ -29,6 +29,7 @@ namespace ams::pm {
Result GetApplicationProcessId(sf::Out<os::ProcessId> out);
Result HookToCreateApplicationProcess(sf::OutCopyHandle out_hook);
Result ClearHook(u32 which);
Result GetProgramId(sf::Out<ncm::ProgramId> out, os::ProcessId process_id);
/* Atmosphere extension commands. */
Result AtmosphereGetProcessInfo(sf::OutCopyHandle out_process_handle, sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id);

View file

@ -23,29 +23,37 @@ namespace ams::pm {
namespace info {
Result HasLaunchedBootProgram(bool *out, ncm::ProgramId program_id) {
return ldr::pm::HasLaunchedBootProgram(out, program_id);
R_RETURN(ldr::pm::HasLaunchedBootProgram(out, program_id));
}
}
/* Actual command implementations. */
Result InformationService::GetProgramId(sf::Out<ncm::ProgramId> out, os::ProcessId process_id) {
return impl::GetProgramId(out.GetPointer(), process_id);
R_RETURN(impl::GetProgramId(out.GetPointer(), process_id));
}
Result InformationService::GetAppletCurrentResourceLimitValues(sf::Out<pm::ResourceLimitValues> out) {
R_RETURN(impl::GetAppletCurrentResourceLimitValues(out.GetPointer()));
}
Result InformationService::GetAppletPeakResourceLimitValues(sf::Out<pm::ResourceLimitValues> out) {
R_RETURN(impl::GetAppletPeakResourceLimitValues(out.GetPointer()));
}
/* Atmosphere extension commands. */
Result InformationService::AtmosphereGetProcessId(sf::Out<os::ProcessId> out, ncm::ProgramId program_id) {
return impl::GetProcessId(out.GetPointer(), program_id);
R_RETURN(impl::GetProcessId(out.GetPointer(), program_id));
}
Result InformationService::AtmosphereHasLaunchedBootProgram(sf::Out<bool> out, ncm::ProgramId program_id) {
return pm::info::HasLaunchedBootProgram(out.GetPointer(), program_id);
R_RETURN(pm::info::HasLaunchedBootProgram(out.GetPointer(), program_id));
}
Result InformationService::AtmosphereGetProcessInfo(sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id) {
/* NOTE: We don't need to worry about closing this handle, because it's an in-process copy, not a newly allocated handle. */
os::NativeHandle dummy_handle;
return impl::AtmosphereGetProcessInfo(&dummy_handle, out_loc.GetPointer(), out_status.GetPointer(), process_id);
R_RETURN(impl::AtmosphereGetProcessInfo(&dummy_handle, out_loc.GetPointer(), out_status.GetPointer(), process_id));
}
}

View file

@ -22,6 +22,8 @@ namespace ams::pm {
public:
/* Actual command implementations. */
Result GetProgramId(sf::Out<ncm::ProgramId> out, os::ProcessId process_id);
Result GetAppletCurrentResourceLimitValues(sf::Out<pm::ResourceLimitValues> out);
Result GetAppletPeakResourceLimitValues(sf::Out<pm::ResourceLimitValues> out);
/* Atmosphere extension commands. */
Result AtmosphereGetProcessId(sf::Out<os::ProcessId> out, ncm::ProgramId program_id);

View file

@ -132,20 +132,20 @@ namespace ams {
switch (port_index) {
case PortIndex_Shell:
if (hos::GetVersion() >= hos::Version_5_0_0) {
return this->AcceptImpl(server, g_shell_service.GetShared());
R_RETURN(this->AcceptImpl(server, g_shell_service.GetShared()));
} else {
return this->AcceptImpl(server, g_deprecated_shell_service.GetShared());
R_RETURN(this->AcceptImpl(server, g_deprecated_shell_service.GetShared()));
}
case PortIndex_DebugMonitor:
if (hos::GetVersion() >= hos::Version_5_0_0) {
return this->AcceptImpl(server, g_dmnt_service.GetShared());
R_RETURN(this->AcceptImpl(server, g_dmnt_service.GetShared()));
} else {
return this->AcceptImpl(server, g_deprecated_dmnt_service.GetShared());
R_RETURN(this->AcceptImpl(server, g_deprecated_dmnt_service.GetShared()));
}
case PortIndex_BootMode:
return this->AcceptImpl(server, g_boot_mode_service.GetShared());
R_RETURN(this->AcceptImpl(server, g_boot_mode_service.GetShared()));
case PortIndex_Information:
return this->AcceptImpl(server, g_information_service.GetShared());
R_RETURN(this->AcceptImpl(server, g_information_service.GetShared()));
AMS_UNREACHABLE_DEFAULT_CASE();
}
}

View file

@ -23,22 +23,22 @@ namespace ams::pm {
namespace shell {
Result LaunchProgram(os::ProcessId *out_process_id, const ncm::ProgramLocation &loc, u32 launch_flags) {
return impl::LaunchProgram(out_process_id, loc, launch_flags);
R_RETURN(impl::LaunchProgram(out_process_id, loc, launch_flags));
}
}
/* Service command implementations. */
Result ShellService::LaunchProgram(sf::Out<os::ProcessId> out_process_id, const ncm::ProgramLocation &loc, u32 flags) {
return pm::shell::LaunchProgram(out_process_id.GetPointer(), loc, flags);
R_RETURN(pm::shell::LaunchProgram(out_process_id.GetPointer(), loc, flags));
}
Result ShellService::TerminateProcess(os::ProcessId process_id) {
return impl::TerminateProcess(process_id);
R_RETURN(impl::TerminateProcess(process_id));
}
Result ShellService::TerminateProgram(ncm::ProgramId program_id) {
return impl::TerminateProgram(program_id);
R_RETURN(impl::TerminateProgram(program_id));
}
void ShellService::GetProcessEventHandle(sf::OutCopyHandle out) {
@ -53,11 +53,11 @@ namespace ams::pm {
}
Result ShellService::CleanupProcess(os::ProcessId process_id) {
return impl::CleanupProcess(process_id);
R_RETURN(impl::CleanupProcess(process_id));
}
Result ShellService::ClearExceptionOccurred(os::ProcessId process_id) {
return impl::ClearExceptionOccurred(process_id);
R_RETURN(impl::ClearExceptionOccurred(process_id));
}
void ShellService::NotifyBootFinished() {
@ -65,15 +65,15 @@ namespace ams::pm {
}
Result ShellService::GetApplicationProcessIdForShell(sf::Out<os::ProcessId> out) {
return impl::GetApplicationProcessId(out.GetPointer());
R_RETURN(impl::GetApplicationProcessId(out.GetPointer()));
}
Result ShellService::BoostSystemMemoryResourceLimit(u64 boost_size) {
return impl::BoostSystemMemoryResourceLimit(boost_size);
R_RETURN(impl::BoostSystemMemoryResourceLimit(boost_size));
}
Result ShellService::BoostApplicationThreadResourceLimit() {
return impl::BoostApplicationThreadResourceLimit();
R_RETURN(impl::BoostApplicationThreadResourceLimit());
}
void ShellService::GetBootFinishedEventHandle(sf::OutCopyHandle out) {
@ -83,4 +83,8 @@ namespace ams::pm {
out.SetValue(event_handle, false);
}
Result ShellService::BoostSystemThreadResourceLimit() {
R_RETURN(impl::BoostSystemThreadResourceLimit());
}
}

View file

@ -33,6 +33,7 @@ namespace ams::pm {
Result BoostSystemMemoryResourceLimit(u64 boost_size);
Result BoostApplicationThreadResourceLimit();
void GetBootFinishedEventHandle(sf::OutCopyHandle out);
Result BoostSystemThreadResourceLimit();
};
static_assert(pm::impl::IsIShellInterface<ShellService>);