diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.h | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/process.cpp | 1 | ||||
-rw-r--r-- | src/core/hle/kernel/process.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/resource_limit.cpp | 157 | ||||
-rw-r--r-- | src/core/hle/kernel/resource_limit.h | 119 |
6 files changed, 286 insertions, 1 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b5c98b249..726e4d2ff 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -10,6 +10,7 @@ #include "core/arm/arm_interface.h" #include "core/core.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/thread.h" #include "core/hle/kernel/timer.h" @@ -134,6 +135,7 @@ void HandleTable::Clear() { /// Initialize the kernel void Init() { + Kernel::ResourceLimitsInit(); Kernel::ThreadingInit(); Kernel::TimersInit(); @@ -147,6 +149,7 @@ void Init() { void Shutdown() { Kernel::ThreadingShutdown(); Kernel::TimersShutdown(); + Kernel::ResourceLimitsShutdown(); g_handle_table.Clear(); // Free all kernel objects g_current_process = nullptr; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 7c106d37c..28748c8f5 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -46,7 +46,8 @@ enum class HandleType : u32 { Process = 8, AddressArbiter = 9, Semaphore = 10, - Timer = 11 + Timer = 11, + ResourceLimit = 12, }; enum { diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 0cdfa58d7..b5c87e883 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -7,6 +7,7 @@ #include "common/logging/log.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/thread.h" #include "core/memory.h" diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 90881054c..7b8a68610 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -45,6 +45,8 @@ union ProcessFlags { BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000). }; +class ResourceLimit; + class Process final : public Object { public: static SharedPtr<Process> Create(std::string name, u64 program_id); @@ -61,6 +63,8 @@ public: std::string name; /// Title ID corresponding to the process u64 program_id; + /// Resource limit descriptor for this process + SharedPtr<ResourceLimit> resource_limit; /// The process may only call SVCs which have the corresponding bit set. std::bitset<0x80> svc_access_mask; diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp new file mode 100644 index 000000000..94b3e3298 --- /dev/null +++ b/src/core/hle/kernel/resource_limit.cpp @@ -0,0 +1,157 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <cstring> + +#include "common/logging/log.h" + +#include "core/mem_map.h" +#include "core/hle/kernel/resource_limit.h" + +namespace Kernel { + +static SharedPtr<ResourceLimit> resource_limits[4]; + +ResourceLimit::ResourceLimit() {} +ResourceLimit::~ResourceLimit() {} + +SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) { + SharedPtr<ResourceLimit> resource_limit(new ResourceLimit); + + resource_limit->name = std::move(name); + return resource_limit; +} + +SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) { + switch (category) + { + case ResourceLimitCategory::APPLICATION: + case ResourceLimitCategory::SYS_APPLET: + case ResourceLimitCategory::LIB_APPLET: + case ResourceLimitCategory::OTHER: + return resource_limits[static_cast<u8>(category)]; + default: + LOG_CRITICAL(Kernel, "Unknown resource limit category"); + UNREACHABLE(); + } +} + +s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { + switch (resource) { + case COMMIT: + return current_commit; + case THREAD: + return current_threads; + case EVENT: + return current_events; + case MUTEX: + return current_mutexes; + case SEMAPHORE: + return current_semaphores; + case TIMER: + return current_timers; + case SHARED_MEMORY: + return current_shared_mems; + case ADDRESS_ARBITER: + return current_address_arbiters; + case CPU_TIME: + return current_cpu_time; + default: + LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); + UNIMPLEMENTED(); + return 0; + } +} + +s32 ResourceLimit::GetMaxResourceValue(u32 resource) const { + switch (resource) { + case COMMIT: + return max_commit; + case THREAD: + return max_threads; + case EVENT: + return max_events; + case MUTEX: + return max_mutexes; + case SEMAPHORE: + return max_semaphores; + case TIMER: + return max_timers; + case SHARED_MEMORY: + return max_shared_mems; + case ADDRESS_ARBITER: + return max_address_arbiters; + case CPU_TIME: + return max_cpu_time; + default: + LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); + UNIMPLEMENTED(); + return 0; + } +} + +void ResourceLimitsInit() { + // Create the four resource limits that the system uses + // Create the APPLICATION resource limit + SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create("Applications"); + resource_limit->max_priority = 0x18; + resource_limit->max_commit = 0x4000000; + resource_limit->max_threads = 0x20; + resource_limit->max_events = 0x20; + resource_limit->max_mutexes = 0x20; + resource_limit->max_semaphores = 0x8; + resource_limit->max_timers = 0x8; + resource_limit->max_shared_mems = 0x10; + resource_limit->max_address_arbiters = 0x2; + resource_limit->max_cpu_time = 0x1E; + resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = resource_limit; + + // Create the SYS_APPLET resource limit + resource_limit = ResourceLimit::Create("System Applets"); + resource_limit->max_priority = 0x4; + resource_limit->max_commit = 0x5E00000; + resource_limit->max_threads = 0x1D; + resource_limit->max_events = 0xB; + resource_limit->max_mutexes = 0x8; + resource_limit->max_semaphores = 0x4; + resource_limit->max_timers = 0x4; + resource_limit->max_shared_mems = 0x8; + resource_limit->max_address_arbiters = 0x3; + resource_limit->max_cpu_time = 0x2710; + resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_APPLET)] = resource_limit; + + // Create the LIB_APPLET resource limit + resource_limit = ResourceLimit::Create("Library Applets"); + resource_limit->max_priority = 0x4; + resource_limit->max_commit = 0x600000; + resource_limit->max_threads = 0xE; + resource_limit->max_events = 0x8; + resource_limit->max_mutexes = 0x8; + resource_limit->max_semaphores = 0x4; + resource_limit->max_timers = 0x4; + resource_limit->max_shared_mems = 0x8; + resource_limit->max_address_arbiters = 0x1; + resource_limit->max_cpu_time = 0x2710; + resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = resource_limit; + + // Create the OTHER resource limit + resource_limit = ResourceLimit::Create("Others"); + resource_limit->max_priority = 0x4; + resource_limit->max_commit = 0x2180000; + resource_limit->max_threads = 0xE1; + resource_limit->max_events = 0x108; + resource_limit->max_mutexes = 0x25; + resource_limit->max_semaphores = 0x43; + resource_limit->max_timers = 0x2C; + resource_limit->max_shared_mems = 0x1F; + resource_limit->max_address_arbiters = 0x2D; + resource_limit->max_cpu_time = 0x3E8; + resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit; +} + +void ResourceLimitsShutdown() { + +} + +} // namespace diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h new file mode 100644 index 000000000..201ec0db9 --- /dev/null +++ b/src/core/hle/kernel/resource_limit.h @@ -0,0 +1,119 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +#include "core/hle/kernel/kernel.h" + +namespace Kernel { + +enum class ResourceLimitCategory : u8 { + APPLICATION = 0, + SYS_APPLET = 1, + LIB_APPLET = 2, + OTHER = 3 +}; + +enum ResourceTypes { + PRIORITY = 0, + COMMIT = 1, + THREAD = 2, + EVENT = 3, + MUTEX = 4, + SEMAPHORE = 5, + TIMER = 6, + SHARED_MEMORY = 7, + ADDRESS_ARBITER = 8, + CPU_TIME = 9, +}; + +class ResourceLimit final : public Object { +public: + /** + * Creates a resource limit object. + */ + static SharedPtr<ResourceLimit> Create(std::string name = "Unknown"); + + /** + * Retrieves the resource limit associated with the specified resource limit category. + * @param category The resource limit category + * @returns The resource limit associated with the category + */ + static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category); + + std::string GetTypeName() const override { return "ResourceLimit"; } + std::string GetName() const override { return name; } + + static const HandleType HANDLE_TYPE = HandleType::ResourceLimit; + HandleType GetHandleType() const override { return HANDLE_TYPE; } + + /** + * Gets the current value for the specified resource. + * @param resource Requested resource type + * @returns The current value of the resource type + */ + s32 GetCurrentResourceValue(u32 resource) const; + + /** + * Gets the max value for the specified resource. + * @param resource Requested resource type + * @returns The max value of the resource type + */ + s32 GetMaxResourceValue(u32 resource) const; + + /// Name of resource limit object. + std::string name; + + /// Max thread priority that a process in this category can create + s32 max_priority = 0; + + /// Max memory that processes in this category can use + s32 max_commit = 0; + + ///< Max number of objects that can be collectively created by the processes in this category + s32 max_threads = 0; + s32 max_events = 0; + s32 max_mutexes = 0; + s32 max_semaphores = 0; + s32 max_timers = 0; + s32 max_shared_mems = 0; + s32 max_address_arbiters = 0; + + /// Max CPU time that the processes in this category can utilize + s32 max_cpu_time = 0; + + // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that + // APPLICATION resource limits should not be affected by the objects created by service modules. + // 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 + + /// Current memory that the processes in this category are using + s32 current_commit = 0; + + ///< Current number of objects among all processes in this category + s32 current_threads = 0; + s32 current_events = 0; + s32 current_mutexes = 0; + s32 current_semaphores = 0; + s32 current_timers = 0; + s32 current_shared_mems = 0; + s32 current_address_arbiters = 0; + + /// Current CPU time that the processes in this category are utilizing + s32 current_cpu_time = 0; + +private: + ResourceLimit(); + ~ResourceLimit() override; +}; + +/// Initializes the resource limits +void ResourceLimitsInit(); + +// Destroys the resource limits +void ResourceLimitsShutdown(); + +} // namespace |