summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Lioncash2018-11-19 12:54:06 -0500
committerGravatar Lioncash2018-11-19 18:16:39 -0500
commit5d46038c5cd91504b00b76660212a3a28b244f38 (patch)
tree01e29da6e94c76109225ae27ed92dbfe7973c22d /src
parentMerge pull request #1634 from DarkLordZach/better-hid-2 (diff)
downloadyuzu-5d46038c5cd91504b00b76660212a3a28b244f38.tar.gz
yuzu-5d46038c5cd91504b00b76660212a3a28b244f38.tar.xz
yuzu-5d46038c5cd91504b00b76660212a3a28b244f38.zip
kernel/resource_limit: Clean up interface
Cleans out the citra/3DS-specific implementation details that don't apply to the Switch. Sets the stage for implementing ResourceLimit instances properly. While we're at it, remove the erroneous checks within CreateThread() and SetThreadPriority(). While these are indeed checked in some capacity, they are not checked via a ResourceLimit instance. In the process of moving out Citra-specifics, this also replaces the system ResourceLimit instance's values with ones from the Switch.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/kernel.cpp79
-rw-r--r--src/core/hle/kernel/kernel.h6
-rw-r--r--src/core/hle/kernel/process.cpp2
-rw-r--r--src/core/hle/kernel/resource_limit.cpp75
-rw-r--r--src/core/hle/kernel/resource_limit.h98
-rw-r--r--src/core/hle/kernel/svc.cpp11
6 files changed, 81 insertions, 190 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 1fd4ba5d2..e441c5bc6 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -105,7 +105,7 @@ struct KernelCore::Impl {
105 void Initialize(KernelCore& kernel) { 105 void Initialize(KernelCore& kernel) {
106 Shutdown(); 106 Shutdown();
107 107
108 InitializeResourceLimits(kernel); 108 InitializeSystemResourceLimit(kernel);
109 InitializeThreads(); 109 InitializeThreads();
110 InitializeTimers(); 110 InitializeTimers();
111 } 111 }
@@ -118,7 +118,7 @@ struct KernelCore::Impl {
118 process_list.clear(); 118 process_list.clear();
119 current_process = nullptr; 119 current_process = nullptr;
120 120
121 resource_limits.fill(nullptr); 121 system_resource_limit = nullptr;
122 122
123 thread_wakeup_callback_handle_table.Clear(); 123 thread_wakeup_callback_handle_table.Clear();
124 thread_wakeup_event_type = nullptr; 124 thread_wakeup_event_type = nullptr;
@@ -129,63 +129,17 @@ struct KernelCore::Impl {
129 named_ports.clear(); 129 named_ports.clear();
130 } 130 }
131 131
132 void InitializeResourceLimits(KernelCore& kernel) { 132 // Creates the default system resource limit
133 // Create the four resource limits that the system uses 133 void InitializeSystemResourceLimit(KernelCore& kernel) {
134 // Create the APPLICATION resource limit 134 system_resource_limit = ResourceLimit::Create(kernel, "System");
135 SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create(kernel, "Applications"); 135
136 resource_limit->max_priority = 0x18; 136 // If setting the default system values fails, then something seriously wrong has occurred.
137 resource_limit->max_commit = 0x4000000; 137 ASSERT(system_resource_limit->SetLimitValue(ResourceType::PhysicalMemory, 0x200000000)
138 resource_limit->max_threads = 0x20; 138 .IsSuccess());
139 resource_limit->max_events = 0x20; 139 ASSERT(system_resource_limit->SetLimitValue(ResourceType::Threads, 800).IsSuccess());
140 resource_limit->max_mutexes = 0x20; 140 ASSERT(system_resource_limit->SetLimitValue(ResourceType::Events, 700).IsSuccess());
141 resource_limit->max_semaphores = 0x8; 141 ASSERT(system_resource_limit->SetLimitValue(ResourceType::TransferMemory, 200).IsSuccess());
142 resource_limit->max_timers = 0x8; 142 ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess());
143 resource_limit->max_shared_mems = 0x10;
144 resource_limit->max_address_arbiters = 0x2;
145 resource_limit->max_cpu_time = 0x1E;
146 resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = resource_limit;
147
148 // Create the SYS_APPLET resource limit
149 resource_limit = ResourceLimit::Create(kernel, "System Applets");
150 resource_limit->max_priority = 0x4;
151 resource_limit->max_commit = 0x5E00000;
152 resource_limit->max_threads = 0x1D;
153 resource_limit->max_events = 0xB;
154 resource_limit->max_mutexes = 0x8;
155 resource_limit->max_semaphores = 0x4;
156 resource_limit->max_timers = 0x4;
157 resource_limit->max_shared_mems = 0x8;
158 resource_limit->max_address_arbiters = 0x3;
159 resource_limit->max_cpu_time = 0x2710;
160 resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_APPLET)] = resource_limit;
161
162 // Create the LIB_APPLET resource limit
163 resource_limit = ResourceLimit::Create(kernel, "Library Applets");
164 resource_limit->max_priority = 0x4;
165 resource_limit->max_commit = 0x600000;
166 resource_limit->max_threads = 0xE;
167 resource_limit->max_events = 0x8;
168 resource_limit->max_mutexes = 0x8;
169 resource_limit->max_semaphores = 0x4;
170 resource_limit->max_timers = 0x4;
171 resource_limit->max_shared_mems = 0x8;
172 resource_limit->max_address_arbiters = 0x1;
173 resource_limit->max_cpu_time = 0x2710;
174 resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = resource_limit;
175
176 // Create the OTHER resource limit
177 resource_limit = ResourceLimit::Create(kernel, "Others");
178 resource_limit->max_priority = 0x4;
179 resource_limit->max_commit = 0x2180000;
180 resource_limit->max_threads = 0xE1;
181 resource_limit->max_events = 0x108;
182 resource_limit->max_mutexes = 0x25;
183 resource_limit->max_semaphores = 0x43;
184 resource_limit->max_timers = 0x2C;
185 resource_limit->max_shared_mems = 0x1F;
186 resource_limit->max_address_arbiters = 0x2D;
187 resource_limit->max_cpu_time = 0x3E8;
188 resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit;
189 } 143 }
190 144
191 void InitializeThreads() { 145 void InitializeThreads() {
@@ -208,7 +162,7 @@ struct KernelCore::Impl {
208 std::vector<SharedPtr<Process>> process_list; 162 std::vector<SharedPtr<Process>> process_list;
209 Process* current_process = nullptr; 163 Process* current_process = nullptr;
210 164
211 std::array<SharedPtr<ResourceLimit>, 4> resource_limits; 165 SharedPtr<ResourceLimit> system_resource_limit;
212 166
213 /// The event type of the generic timer callback event 167 /// The event type of the generic timer callback event
214 CoreTiming::EventType* timer_callback_event_type = nullptr; 168 CoreTiming::EventType* timer_callback_event_type = nullptr;
@@ -239,9 +193,8 @@ void KernelCore::Shutdown() {
239 impl->Shutdown(); 193 impl->Shutdown();
240} 194}
241 195
242SharedPtr<ResourceLimit> KernelCore::ResourceLimitForCategory( 196SharedPtr<ResourceLimit> KernelCore::GetSystemResourceLimit() const {
243 ResourceLimitCategory category) const { 197 return impl->system_resource_limit;
244 return impl->resource_limits.at(static_cast<std::size_t>(category));
245} 198}
246 199
247SharedPtr<Thread> KernelCore::RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const { 200SharedPtr<Thread> KernelCore::RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 7f822d524..ea00c89f5 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -24,8 +24,6 @@ class ResourceLimit;
24class Thread; 24class Thread;
25class Timer; 25class Timer;
26 26
27enum class ResourceLimitCategory : u8;
28
29/// Represents a single instance of the kernel. 27/// Represents a single instance of the kernel.
30class KernelCore { 28class KernelCore {
31private: 29private:
@@ -47,8 +45,8 @@ public:
47 /// Clears all resources in use by the kernel instance. 45 /// Clears all resources in use by the kernel instance.
48 void Shutdown(); 46 void Shutdown();
49 47
50 /// Retrieves a shared pointer to a ResourceLimit identified by the given category. 48 /// Retrieves a shared pointer to the system resource limit instance.
51 SharedPtr<ResourceLimit> ResourceLimitForCategory(ResourceLimitCategory category) const; 49 SharedPtr<ResourceLimit> GetSystemResourceLimit() const;
52 50
53 /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. 51 /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
54 SharedPtr<Thread> RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const; 52 SharedPtr<Thread> RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const;
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index a257c3726..1412257a0 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -28,7 +28,7 @@ SharedPtr<Process> Process::Create(KernelCore& kernel, std::string&& name) {
28 process->name = std::move(name); 28 process->name = std::move(name);
29 process->flags.raw = 0; 29 process->flags.raw = 0;
30 process->flags.memory_region.Assign(MemoryRegion::APPLICATION); 30 process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
31 process->resource_limit = kernel.ResourceLimitForCategory(ResourceLimitCategory::APPLICATION); 31 process->resource_limit = kernel.GetSystemResourceLimit();
32 process->status = ProcessStatus::Created; 32 process->status = ProcessStatus::Created;
33 process->program_id = 0; 33 process->program_id = 0;
34 process->process_id = kernel.CreateNewProcessID(); 34 process->process_id = kernel.CreateNewProcessID();
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
index b253a680f..2f9695005 100644
--- a/src/core/hle/kernel/resource_limit.cpp
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -2,12 +2,16 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring> 5#include "core/hle/kernel/errors.h"
6#include "common/assert.h"
7#include "common/logging/log.h"
8#include "core/hle/kernel/resource_limit.h" 6#include "core/hle/kernel/resource_limit.h"
7#include "core/hle/result.h"
9 8
10namespace Kernel { 9namespace Kernel {
10namespace {
11constexpr std::size_t ResourceTypeToIndex(ResourceType type) {
12 return static_cast<std::size_t>(type);
13}
14} // Anonymous namespace
11 15
12ResourceLimit::ResourceLimit(KernelCore& kernel) : Object{kernel} {} 16ResourceLimit::ResourceLimit(KernelCore& kernel) : Object{kernel} {}
13ResourceLimit::~ResourceLimit() = default; 17ResourceLimit::~ResourceLimit() = default;
@@ -19,59 +23,22 @@ SharedPtr<ResourceLimit> ResourceLimit::Create(KernelCore& kernel, std::string n
19 return resource_limit; 23 return resource_limit;
20} 24}
21 25
22s32 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const { 26s64 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const {
23 switch (resource) { 27 return values.at(ResourceTypeToIndex(resource));
24 case ResourceType::Commit: 28}
25 return current_commit; 29
26 case ResourceType::Thread: 30s64 ResourceLimit::GetMaxResourceValue(ResourceType resource) const {
27 return current_threads; 31 return limits.at(ResourceTypeToIndex(resource));
28 case ResourceType::Event:
29 return current_events;
30 case ResourceType::Mutex:
31 return current_mutexes;
32 case ResourceType::Semaphore:
33 return current_semaphores;
34 case ResourceType::Timer:
35 return current_timers;
36 case ResourceType::SharedMemory:
37 return current_shared_mems;
38 case ResourceType::AddressArbiter:
39 return current_address_arbiters;
40 case ResourceType::CPUTime:
41 return current_cpu_time;
42 default:
43 LOG_ERROR(Kernel, "Unknown resource type={:08X}", static_cast<u32>(resource));
44 UNIMPLEMENTED();
45 return 0;
46 }
47} 32}
48 33
49u32 ResourceLimit::GetMaxResourceValue(ResourceType resource) const { 34ResultCode ResourceLimit::SetLimitValue(ResourceType resource, s64 value) {
50 switch (resource) { 35 const auto index = ResourceTypeToIndex(resource);
51 case ResourceType::Priority: 36
52 return max_priority; 37 if (value < values[index]) {
53 case ResourceType::Commit: 38 return ERR_INVALID_STATE;
54 return max_commit;
55 case ResourceType::Thread:
56 return max_threads;
57 case ResourceType::Event:
58 return max_events;
59 case ResourceType::Mutex:
60 return max_mutexes;
61 case ResourceType::Semaphore:
62 return max_semaphores;
63 case ResourceType::Timer:
64 return max_timers;
65 case ResourceType::SharedMemory:
66 return max_shared_mems;
67 case ResourceType::AddressArbiter:
68 return max_address_arbiters;
69 case ResourceType::CPUTime:
70 return max_cpu_time;
71 default:
72 LOG_ERROR(Kernel, "Unknown resource type={:08X}", static_cast<u32>(resource));
73 UNIMPLEMENTED();
74 return 0;
75 } 39 }
40
41 values[index] = value;
42 return RESULT_SUCCESS;
76} 43}
77} // namespace Kernel 44} // namespace Kernel
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
index 219e49562..bec065543 100644
--- a/src/core/hle/kernel/resource_limit.h
+++ b/src/core/hle/kernel/resource_limit.h
@@ -4,31 +4,25 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
7#include "common/common_types.h" 8#include "common/common_types.h"
8#include "core/hle/kernel/object.h" 9#include "core/hle/kernel/object.h"
9 10
11union ResultCode;
12
10namespace Kernel { 13namespace Kernel {
11 14
12class KernelCore; 15class KernelCore;
13 16
14enum class ResourceLimitCategory : u8 {
15 APPLICATION = 0,
16 SYS_APPLET = 1,
17 LIB_APPLET = 2,
18 OTHER = 3
19};
20
21enum class ResourceType { 17enum class ResourceType {
22 Priority = 0, 18 PhysicalMemory,
23 Commit = 1, 19 Threads,
24 Thread = 2, 20 Events,
25 Event = 3, 21 TransferMemory,
26 Mutex = 4, 22 Sessions,
27 Semaphore = 5, 23
28 Timer = 6, 24 // Used as a count, not an actual type.
29 SharedMemory = 7, 25 ResourceTypeCount
30 AddressArbiter = 8,
31 CPUTime = 9,
32}; 26};
33 27
34class ResourceLimit final : public Object { 28class ResourceLimit final : public Object {
@@ -55,61 +49,51 @@ public:
55 * @param resource Requested resource type 49 * @param resource Requested resource type
56 * @returns The current value of the resource type 50 * @returns The current value of the resource type
57 */ 51 */
58 s32 GetCurrentResourceValue(ResourceType resource) const; 52 s64 GetCurrentResourceValue(ResourceType resource) const;
59 53
60 /** 54 /**
61 * Gets the max value for the specified resource. 55 * Gets the max value for the specified resource.
62 * @param resource Requested resource type 56 * @param resource Requested resource type
63 * @returns The max value of the resource type 57 * @returns The max value of the resource type
64 */ 58 */
65 u32 GetMaxResourceValue(ResourceType resource) const; 59 s64 GetMaxResourceValue(ResourceType resource) const;
66
67 /// Name of resource limit object.
68 std::string name;
69
70 /// Max thread priority that a process in this category can create
71 s32 max_priority = 0;
72
73 /// Max memory that processes in this category can use
74 s32 max_commit = 0;
75 60
76 ///< Max number of objects that can be collectively created by the processes in this category 61 /**
77 s32 max_threads = 0; 62 * Sets the limit value for a given resource type.
78 s32 max_events = 0; 63 *
79 s32 max_mutexes = 0; 64 * @param resource The resource type to apply the limit to.
80 s32 max_semaphores = 0; 65 * @param value The limit to apply to the given resource type.
81 s32 max_timers = 0; 66 *
82 s32 max_shared_mems = 0; 67 * @return A result code indicating if setting the limit value
83 s32 max_address_arbiters = 0; 68 * was successful or not.
69 *
70 * @note The supplied limit value *must* be greater than or equal to
71 * the current resource value for the given resource type,
72 * otherwise ERR_INVALID_STATE will be returned.
73 */
74 ResultCode SetLimitValue(ResourceType resource, s64 value);
84 75
85 /// Max CPU time that the processes in this category can utilize 76private:
86 s32 max_cpu_time = 0; 77 explicit ResourceLimit(KernelCore& kernel);
78 ~ResourceLimit() override;
87 79
88 // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind 80 // TODO(Subv): Increment resource limit current values in their respective Kernel::T::Create
89 // that APPLICATION resource limits should not be affected by the objects created by service 81 // functions
90 // modules. 82 //
91 // Currently we have no way of distinguishing if a Create was called by the running application, 83 // Currently we have no way of distinguishing if a Create was called by the running application,
92 // or by a service module. Approach this once we have separated the service modules into their 84 // or by a service module. Approach this once we have separated the service modules into their
93 // own processes 85 // own processes
94 86
95 /// Current memory that the processes in this category are using 87 using ResourceArray =
96 s32 current_commit = 0; 88 std::array<s64, static_cast<std::size_t>(ResourceType::ResourceTypeCount)>;
97 89
98 ///< Current number of objects among all processes in this category 90 /// Maximum values a resource type may reach.
99 s32 current_threads = 0; 91 ResourceArray limits{};
100 s32 current_events = 0; 92 /// Current resource limit values.
101 s32 current_mutexes = 0; 93 ResourceArray values{};
102 s32 current_semaphores = 0;
103 s32 current_timers = 0;
104 s32 current_shared_mems = 0;
105 s32 current_address_arbiters = 0;
106 94
107 /// Current CPU time that the processes in this category are utilizing 95 /// Name of resource limit object.
108 s32 current_cpu_time = 0; 96 std::string name;
109
110private:
111 explicit ResourceLimit(KernelCore& kernel);
112 ~ResourceLimit() override;
113}; 97};
114 98
115} // namespace Kernel 99} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 75dbfc31d..9904605cd 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -736,13 +736,6 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
736 736
737 const auto* const current_process = Core::CurrentProcess(); 737 const auto* const current_process = Core::CurrentProcess();
738 738
739 // Note: The kernel uses the current process's resource limit instead of
740 // the one from the thread owner's resource limit.
741 const ResourceLimit& resource_limit = current_process->GetResourceLimit();
742 if (resource_limit.GetMaxResourceValue(ResourceType::Priority) > priority) {
743 return ERR_INVALID_THREAD_PRIORITY;
744 }
745
746 SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle); 739 SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle);
747 if (!thread) { 740 if (!thread) {
748 return ERR_INVALID_HANDLE; 741 return ERR_INVALID_HANDLE;
@@ -885,10 +878,6 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
885 } 878 }
886 879
887 auto* const current_process = Core::CurrentProcess(); 880 auto* const current_process = Core::CurrentProcess();
888 const ResourceLimit& resource_limit = current_process->GetResourceLimit();
889 if (resource_limit.GetMaxResourceValue(ResourceType::Priority) > priority) {
890 return ERR_INVALID_THREAD_PRIORITY;
891 }
892 881
893 if (processor_id == THREADPROCESSORID_DEFAULT) { 882 if (processor_id == THREADPROCESSORID_DEFAULT) {
894 // Set the target CPU to the one specified in the process' exheader. 883 // Set the target CPU to the one specified in the process' exheader.