summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/init/init_slab_setup.cpp6
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp14
-rw-r--r--src/core/hle/kernel/k_resource_limit.h20
-rw-r--r--src/core/hle/kernel/k_scoped_resource_reservation.h8
-rw-r--r--src/core/hle/kernel/k_shared_memory.cpp28
-rw-r--r--src/core/hle/kernel/k_shared_memory.h2
-rw-r--r--src/core/hle/kernel/k_transfer_memory.h5
-rw-r--r--src/core/hle/kernel/kernel.cpp24
-rw-r--r--src/core/hle/kernel/kernel.h38
-rw-r--r--src/core/hle/kernel/process.cpp20
-rw-r--r--src/core/hle/kernel/process.h8
-rw-r--r--src/core/hle/kernel/svc.cpp127
-rw-r--r--src/core/hle/kernel/svc_wrap.h19
13 files changed, 197 insertions, 122 deletions
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp
index ce7a24c40..a5ddd7344 100644
--- a/src/core/hle/kernel/init/init_slab_setup.cpp
+++ b/src/core/hle/kernel/init/init_slab_setup.cpp
@@ -12,11 +12,12 @@
12#include "core/hle/kernel/k_event.h" 12#include "core/hle/kernel/k_event.h"
13#include "core/hle/kernel/k_memory_layout.h" 13#include "core/hle/kernel/k_memory_layout.h"
14#include "core/hle/kernel/k_memory_manager.h" 14#include "core/hle/kernel/k_memory_manager.h"
15#include "core/hle/kernel/k_resource_limit.h"
15#include "core/hle/kernel/k_session.h" 16#include "core/hle/kernel/k_session.h"
16#include "core/hle/kernel/k_shared_memory.h" 17#include "core/hle/kernel/k_shared_memory.h"
17#include "core/hle/kernel/k_transfer_memory.h"
18#include "core/hle/kernel/k_system_control.h" 18#include "core/hle/kernel/k_system_control.h"
19#include "core/hle/kernel/k_thread.h" 19#include "core/hle/kernel/k_thread.h"
20#include "core/hle/kernel/k_transfer_memory.h"
20#include "core/hle/kernel/memory_types.h" 21#include "core/hle/kernel/memory_types.h"
21#include "core/hle/kernel/process.h" 22#include "core/hle/kernel/process.h"
22#include "core/memory.h" 23#include "core/memory.h"
@@ -31,7 +32,8 @@ namespace Kernel::Init {
31 HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \ 32 HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \
32 HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ 33 HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \
33 HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \ 34 HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \
34 HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) 35 HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \
36 HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__)
35 37
36namespace { 38namespace {
37 39
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
index d05b34ea3..ad5095bfd 100644
--- a/src/core/hle/kernel/k_resource_limit.cpp
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -10,10 +10,16 @@
10namespace Kernel { 10namespace Kernel {
11constexpr s64 DefaultTimeout = 10000000000; // 10 seconds 11constexpr s64 DefaultTimeout = 10000000000; // 10 seconds
12 12
13KResourceLimit::KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_) 13KResourceLimit::KResourceLimit(KernelCore& kernel)
14 : Object{kernel}, lock{kernel}, cond_var{kernel}, core_timing(core_timing_) {} 14 : KAutoObjectWithSlabHeapAndContainer{kernel}, lock{kernel}, cond_var{kernel} {}
15KResourceLimit::~KResourceLimit() = default; 15KResourceLimit::~KResourceLimit() = default;
16 16
17void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing_) {
18 core_timing = core_timing_;
19}
20
21void KResourceLimit::Finalize() {}
22
17s64 KResourceLimit::GetLimitValue(LimitableResource which) const { 23s64 KResourceLimit::GetLimitValue(LimitableResource which) const {
18 const auto index = static_cast<std::size_t>(which); 24 const auto index = static_cast<std::size_t>(which);
19 s64 value{}; 25 s64 value{};
@@ -78,7 +84,7 @@ ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
78} 84}
79 85
80bool KResourceLimit::Reserve(LimitableResource which, s64 value) { 86bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
81 return Reserve(which, value, core_timing.GetGlobalTimeNs().count() + DefaultTimeout); 87 return Reserve(which, value, core_timing->GetGlobalTimeNs().count() + DefaultTimeout);
82} 88}
83 89
84bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { 90bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
@@ -109,7 +115,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
109 } 115 }
110 116
111 if (current_hints[index] + value <= limit_values[index] && 117 if (current_hints[index] + value <= limit_values[index] &&
112 (timeout < 0 || core_timing.GetGlobalTimeNs().count() < timeout)) { 118 (timeout < 0 || core_timing->GetGlobalTimeNs().count() < timeout)) {
113 waiter_count++; 119 waiter_count++;
114 cond_var.Wait(&lock, timeout); 120 cond_var.Wait(&lock, timeout);
115 waiter_count--; 121 waiter_count--;
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
index 4542317d0..483c66c33 100644
--- a/src/core/hle/kernel/k_resource_limit.h
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -32,10 +32,16 @@ constexpr bool IsValidResourceType(LimitableResource type) {
32 return type < LimitableResource::Count; 32 return type < LimitableResource::Count;
33} 33}
34 34
35class KResourceLimit final : public Object { 35class KResourceLimit final
36 : public KAutoObjectWithSlabHeapAndContainer<KResourceLimit, KAutoObjectWithList> {
37 KERNEL_AUTOOBJECT_TRAITS(KResourceLimit, KAutoObject);
38
36public: 39public:
37 explicit KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_); 40 explicit KResourceLimit(KernelCore& kernel);
38 ~KResourceLimit(); 41 virtual ~KResourceLimit();
42
43 void Initialize(const Core::Timing::CoreTiming* core_timing_);
44 virtual void Finalize() override;
39 45
40 s64 GetLimitValue(LimitableResource which) const; 46 s64 GetLimitValue(LimitableResource which) const;
41 s64 GetCurrentValue(LimitableResource which) const; 47 s64 GetCurrentValue(LimitableResource which) const;
@@ -49,6 +55,10 @@ public:
49 void Release(LimitableResource which, s64 value); 55 void Release(LimitableResource which, s64 value);
50 void Release(LimitableResource which, s64 value, s64 hint); 56 void Release(LimitableResource which, s64 value, s64 hint);
51 57
58 static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
59
60 // DEPRECATED
61
52 std::string GetTypeName() const override { 62 std::string GetTypeName() const override {
53 return "KResourceLimit"; 63 return "KResourceLimit";
54 } 64 }
@@ -61,8 +71,6 @@ public:
61 return HANDLE_TYPE; 71 return HANDLE_TYPE;
62 } 72 }
63 73
64 virtual void Finalize() override {}
65
66private: 74private:
67 using ResourceArray = std::array<s64, static_cast<std::size_t>(LimitableResource::Count)>; 75 using ResourceArray = std::array<s64, static_cast<std::size_t>(LimitableResource::Count)>;
68 ResourceArray limit_values{}; 76 ResourceArray limit_values{};
@@ -72,6 +80,6 @@ private:
72 mutable KLightLock lock; 80 mutable KLightLock lock;
73 s32 waiter_count{}; 81 s32 waiter_count{};
74 KLightConditionVariable cond_var; 82 KLightConditionVariable cond_var;
75 const Core::Timing::CoreTiming& core_timing; 83 const Core::Timing::CoreTiming* core_timing{};
76}; 84};
77} // namespace Kernel 85} // namespace Kernel
diff --git a/src/core/hle/kernel/k_scoped_resource_reservation.h b/src/core/hle/kernel/k_scoped_resource_reservation.h
index c5deca00b..b160587c5 100644
--- a/src/core/hle/kernel/k_scoped_resource_reservation.h
+++ b/src/core/hle/kernel/k_scoped_resource_reservation.h
@@ -15,8 +15,7 @@ namespace Kernel {
15 15
16class KScopedResourceReservation { 16class KScopedResourceReservation {
17public: 17public:
18 explicit KScopedResourceReservation(std::shared_ptr<KResourceLimit> l, LimitableResource r, 18 explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v, s64 timeout)
19 s64 v, s64 timeout)
20 : resource_limit(std::move(l)), value(v), resource(r) { 19 : resource_limit(std::move(l)), value(v), resource(r) {
21 if (resource_limit && value) { 20 if (resource_limit && value) {
22 success = resource_limit->Reserve(resource, value, timeout); 21 success = resource_limit->Reserve(resource, value, timeout);
@@ -25,8 +24,7 @@ public:
25 } 24 }
26 } 25 }
27 26
28 explicit KScopedResourceReservation(std::shared_ptr<KResourceLimit> l, LimitableResource r, 27 explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v = 1)
29 s64 v = 1)
30 : resource_limit(std::move(l)), value(v), resource(r) { 28 : resource_limit(std::move(l)), value(v), resource(r) {
31 if (resource_limit && value) { 29 if (resource_limit && value) {
32 success = resource_limit->Reserve(resource, value); 30 success = resource_limit->Reserve(resource, value);
@@ -58,7 +56,7 @@ public:
58 } 56 }
59 57
60private: 58private:
61 std::shared_ptr<KResourceLimit> resource_limit; 59 KResourceLimit* resource_limit{};
62 s64 value; 60 s64 value;
63 LimitableResource resource; 61 LimitableResource resource;
64 bool success; 62 bool success;
diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp
index 9e20c2350..e91bc94bd 100644
--- a/src/core/hle/kernel/k_shared_memory.cpp
+++ b/src/core/hle/kernel/k_shared_memory.cpp
@@ -8,6 +8,7 @@
8#include "core/hle/kernel/k_scoped_resource_reservation.h" 8#include "core/hle/kernel/k_scoped_resource_reservation.h"
9#include "core/hle/kernel/k_shared_memory.h" 9#include "core/hle/kernel/k_shared_memory.h"
10#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/svc_results.h"
11 12
12namespace Kernel { 13namespace Kernel {
13 14
@@ -22,12 +23,7 @@ ResultCode KSharedMemory::Initialize(KernelCore& kernel_, Core::DeviceMemory& de
22 KMemoryPermission owner_permission_, 23 KMemoryPermission owner_permission_,
23 KMemoryPermission user_permission_, PAddr physical_address_, 24 KMemoryPermission user_permission_, PAddr physical_address_,
24 std::size_t size_, std::string name_) { 25 std::size_t size_, std::string name_) {
25 26 // Set members.
26 resource_limit = kernel_.GetSystemResourceLimit();
27 KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory,
28 size_);
29 ASSERT(memory_reservation.Succeeded());
30
31 owner_process = owner_process_; 27 owner_process = owner_process_;
32 device_memory = &device_memory_; 28 device_memory = &device_memory_;
33 page_list = std::move(page_list_); 29 page_list = std::move(page_list_);
@@ -36,10 +32,28 @@ ResultCode KSharedMemory::Initialize(KernelCore& kernel_, Core::DeviceMemory& de
36 physical_address = physical_address_; 32 physical_address = physical_address_;
37 size = size_; 33 size = size_;
38 name = name_; 34 name = name_;
39 is_initialized = true;
40 35
36 // Get the resource limit.
37 KResourceLimit* reslimit = kernel.GetSystemResourceLimit();
38
39 // Reserve memory for ourselves.
40 KScopedResourceReservation memory_reservation(reslimit, LimitableResource::PhysicalMemory,
41 size_);
42 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
43
44 // Commit our reservation.
41 memory_reservation.Commit(); 45 memory_reservation.Commit();
42 46
47 // Set our resource limit.
48 resource_limit = reslimit;
49 resource_limit->Open();
50
51 // Mark initialized.
52 is_initialized = true;
53
54 // Clear all pages in the memory.
55 std::memset(device_memory_.GetPointer(physical_address_), 0, size_);
56
43 return RESULT_SUCCESS; 57 return RESULT_SUCCESS;
44} 58}
45 59
diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h
index aaa773bfc..93153ab20 100644
--- a/src/core/hle/kernel/k_shared_memory.h
+++ b/src/core/hle/kernel/k_shared_memory.h
@@ -88,7 +88,7 @@ private:
88 KMemoryPermission user_permission{}; 88 KMemoryPermission user_permission{};
89 PAddr physical_address{}; 89 PAddr physical_address{};
90 std::size_t size{}; 90 std::size_t size{};
91 std::shared_ptr<KResourceLimit> resource_limit; 91 KResourceLimit* resource_limit{};
92 bool is_initialized{}; 92 bool is_initialized{};
93}; 93};
94 94
diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h
index f43725c7f..3c3fa401b 100644
--- a/src/core/hle/kernel/k_transfer_memory.h
+++ b/src/core/hle/kernel/k_transfer_memory.h
@@ -27,9 +27,7 @@ class KTransferMemory final
27 27
28public: 28public:
29 explicit KTransferMemory(KernelCore& kernel); 29 explicit KTransferMemory(KernelCore& kernel);
30 ~KTransferMemory() override; 30 virtual ~KTransferMemory() override;
31
32 static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory;
33 31
34 ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_); 32 ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_);
35 33
@@ -67,6 +65,7 @@ public:
67 return GetTypeName(); 65 return GetTypeName();
68 } 66 }
69 67
68 static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory;
70 HandleType GetHandleType() const override { 69 HandleType GetHandleType() const override {
71 return HANDLE_TYPE; 70 return HANDLE_TYPE;
72 } 71 }
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 472c71cf1..ada993f46 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -74,8 +74,8 @@ struct KernelCore::Impl {
74 Init::InitializeSlabHeaps(system, memory_layout); 74 Init::InitializeSlabHeaps(system, memory_layout);
75 75
76 // Initialize kernel memory and resources. 76 // Initialize kernel memory and resources.
77 InitializeMemoryLayout(memory_layout);
78 InitializeSystemResourceLimit(kernel, system.CoreTiming(), memory_layout); 77 InitializeSystemResourceLimit(kernel, system.CoreTiming(), memory_layout);
78 InitializeMemoryLayout(memory_layout);
79 InitializePageSlab(); 79 InitializePageSlab();
80 InitializeSchedulers(); 80 InitializeSchedulers();
81 InitializeSuspendThreads(); 81 InitializeSuspendThreads();
@@ -126,11 +126,19 @@ struct KernelCore::Impl {
126 126
127 exclusive_monitor.reset(); 127 exclusive_monitor.reset();
128 128
129 hid_shared_mem->Close();
129 hid_shared_mem = nullptr; 130 hid_shared_mem = nullptr;
131
132 font_shared_mem->Close();
130 font_shared_mem = nullptr; 133 font_shared_mem = nullptr;
134
135 irs_shared_mem->Close();
131 irs_shared_mem = nullptr; 136 irs_shared_mem = nullptr;
137
138 time_shared_mem->Close();
132 time_shared_mem = nullptr; 139 time_shared_mem = nullptr;
133 140
141 system_resource_limit->Close();
134 system_resource_limit = nullptr; 142 system_resource_limit = nullptr;
135 143
136 // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others 144 // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
@@ -156,7 +164,9 @@ struct KernelCore::Impl {
156 void InitializeSystemResourceLimit(KernelCore& kernel, 164 void InitializeSystemResourceLimit(KernelCore& kernel,
157 const Core::Timing::CoreTiming& core_timing, 165 const Core::Timing::CoreTiming& core_timing,
158 const KMemoryLayout& memory_layout) { 166 const KMemoryLayout& memory_layout) {
159 system_resource_limit = std::make_shared<KResourceLimit>(kernel, core_timing); 167 system_resource_limit = KResourceLimit::Create(system.Kernel());
168 system_resource_limit->Initialize(&core_timing);
169
160 const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes(); 170 const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes();
161 171
162 // If setting the default system values fails, then something seriously wrong has occurred. 172 // If setting the default system values fails, then something seriously wrong has occurred.
@@ -627,11 +637,11 @@ struct KernelCore::Impl {
627 637
628 // Lists all processes that exist in the current session. 638 // Lists all processes that exist in the current session.
629 std::vector<Process*> process_list; 639 std::vector<Process*> process_list;
630 Process* current_process = nullptr; 640 Process* current_process{};
631 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; 641 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
632 Kernel::TimeManager time_manager; 642 Kernel::TimeManager time_manager;
633 643
634 std::shared_ptr<KResourceLimit> system_resource_limit; 644 KResourceLimit* system_resource_limit{};
635 645
636 std::shared_ptr<Core::Timing::EventType> preemption_event; 646 std::shared_ptr<Core::Timing::EventType> preemption_event;
637 647
@@ -704,7 +714,11 @@ void KernelCore::Shutdown() {
704 impl->Shutdown(); 714 impl->Shutdown();
705} 715}
706 716
707std::shared_ptr<KResourceLimit> KernelCore::GetSystemResourceLimit() const { 717const KResourceLimit* KernelCore::GetSystemResourceLimit() const {
718 return impl->system_resource_limit;
719}
720
721KResourceLimit* KernelCore::GetSystemResourceLimit() {
708 return impl->system_resource_limit; 722 return impl->system_resource_limit;
709} 723}
710 724
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index f07f0276e..43e49603b 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -92,7 +92,10 @@ public:
92 void Shutdown(); 92 void Shutdown();
93 93
94 /// Retrieves a shared pointer to the system resource limit instance. 94 /// Retrieves a shared pointer to the system resource limit instance.
95 std::shared_ptr<KResourceLimit> GetSystemResourceLimit() const; 95 const KResourceLimit* GetSystemResourceLimit() const;
96
97 /// Retrieves a shared pointer to the system resource limit instance.
98 KResourceLimit* GetSystemResourceLimit();
96 99
97 /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. 100 /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
98 KScopedAutoObject<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const; 101 KScopedAutoObject<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const;
@@ -263,24 +266,26 @@ public:
263 /// Gets the slab heap for the specified kernel object type. 266 /// Gets the slab heap for the specified kernel object type.
264 template <typename T> 267 template <typename T>
265 KSlabHeap<T>& SlabHeap() { 268 KSlabHeap<T>& SlabHeap() {
266 if constexpr (std::is_same_v<T, Process>) { 269 if constexpr (std::is_same_v<T, KClientSession>) {
267 return slab_heap_container->process; 270 return slab_heap_container->client_session;
268 } else if constexpr (std::is_same_v<T, KThread>) {
269 return slab_heap_container->thread;
270 } else if constexpr (std::is_same_v<T, KEvent>) { 271 } else if constexpr (std::is_same_v<T, KEvent>) {
271 return slab_heap_container->event; 272 return slab_heap_container->event;
272 } else if constexpr (std::is_same_v<T, KSharedMemory>) {
273 return slab_heap_container->shared_memory;
274 } else if constexpr (std::is_same_v<T, KLinkedListNode>) { 273 } else if constexpr (std::is_same_v<T, KLinkedListNode>) {
275 return slab_heap_container->linked_list_node; 274 return slab_heap_container->linked_list_node;
276 } else if constexpr (std::is_same_v<T, KWritableEvent>) { 275 } else if constexpr (std::is_same_v<T, Process>) {
277 return slab_heap_container->writeable_event; 276 return slab_heap_container->process;
278 } else if constexpr (std::is_same_v<T, KClientSession>) { 277 } else if constexpr (std::is_same_v<T, KResourceLimit>) {
279 return slab_heap_container->client_session; 278 return slab_heap_container->resource_limit;
280 } else if constexpr (std::is_same_v<T, KSession>) { 279 } else if constexpr (std::is_same_v<T, KSession>) {
281 return slab_heap_container->session; 280 return slab_heap_container->session;
281 } else if constexpr (std::is_same_v<T, KSharedMemory>) {
282 return slab_heap_container->shared_memory;
283 } else if constexpr (std::is_same_v<T, KThread>) {
284 return slab_heap_container->thread;
282 } else if constexpr (std::is_same_v<T, KTransferMemory>) { 285 } else if constexpr (std::is_same_v<T, KTransferMemory>) {
283 return slab_heap_container->transfer_memory; 286 return slab_heap_container->transfer_memory;
287 } else if constexpr (std::is_same_v<T, KWritableEvent>) {
288 return slab_heap_container->writeable_event;
284 } 289 }
285 } 290 }
286 291
@@ -315,15 +320,16 @@ private:
315private: 320private:
316 /// Helper to encapsulate all slab heaps in a single heap allocated container 321 /// Helper to encapsulate all slab heaps in a single heap allocated container
317 struct SlabHeapContainer { 322 struct SlabHeapContainer {
318 KSlabHeap<Process> process; 323 KSlabHeap<KClientSession> client_session;
319 KSlabHeap<KThread> thread;
320 KSlabHeap<KEvent> event; 324 KSlabHeap<KEvent> event;
321 KSlabHeap<KSharedMemory> shared_memory;
322 KSlabHeap<KLinkedListNode> linked_list_node; 325 KSlabHeap<KLinkedListNode> linked_list_node;
323 KSlabHeap<KWritableEvent> writeable_event; 326 KSlabHeap<Process> process;
324 KSlabHeap<KClientSession> client_session; 327 KSlabHeap<KResourceLimit> resource_limit;
325 KSlabHeap<KSession> session; 328 KSlabHeap<KSession> session;
329 KSlabHeap<KSharedMemory> shared_memory;
330 KSlabHeap<KThread> thread;
326 KSlabHeap<KTransferMemory> transfer_memory; 331 KSlabHeap<KTransferMemory> transfer_memory;
332 KSlabHeap<KWritableEvent> writeable_event;
327 }; 333 };
328 334
329 std::unique_ptr<SlabHeapContainer> slab_heap_container; 335 std::unique_ptr<SlabHeapContainer> slab_heap_container;
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 678037923..315640bea 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -138,10 +138,13 @@ ResultCode Process::Initialize(Process* process, Core::System& system, std::stri
138 138
139 kernel.AppendNewProcess(process); 139 kernel.AppendNewProcess(process);
140 140
141 // Open a reference to the resource limit.
142 process->resource_limit->Open();
143
141 return RESULT_SUCCESS; 144 return RESULT_SUCCESS;
142} 145}
143 146
144std::shared_ptr<KResourceLimit> Process::GetResourceLimit() const { 147KResourceLimit* Process::GetResourceLimit() const {
145 return resource_limit; 148 return resource_limit;
146} 149}
147 150
@@ -166,7 +169,10 @@ u64 Process::GetTotalPhysicalMemoryAvailable() const {
166 const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + 169 const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
167 page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + 170 page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
168 main_thread_stack_size}; 171 main_thread_stack_size};
169 ASSERT(capacity == kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); 172 if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application);
173 capacity != pool_size) {
174 LOG_WARNING(Kernel, "capacity {} != application pool size {}", capacity, pool_size);
175 }
170 if (capacity < memory_usage_capacity) { 176 if (capacity < memory_usage_capacity) {
171 return capacity; 177 return capacity;
172 } 178 }
@@ -371,6 +377,16 @@ void Process::PrepareForTermination() {
371 ChangeStatus(ProcessStatus::Exited); 377 ChangeStatus(ProcessStatus::Exited);
372} 378}
373 379
380void Process::Finalize() {
381 // Release memory to the resource limit.
382 if (resource_limit != nullptr) {
383 resource_limit->Close();
384 }
385
386 // Perform inherited finalization.
387 KAutoObjectWithSlabHeapAndContainer<Process, KSynchronizationObject>::Finalize();
388}
389
374/** 390/**
375 * Attempts to find a TLS page that contains a free slot for 391 * Attempts to find a TLS page that contains a free slot for
376 * use by a thread. 392 * use by a thread.
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index df3c7997d..35fe16433 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -171,7 +171,7 @@ public:
171 } 171 }
172 172
173 /// Gets the resource limit descriptor for this process 173 /// Gets the resource limit descriptor for this process
174 std::shared_ptr<KResourceLimit> GetResourceLimit() const; 174 KResourceLimit* GetResourceLimit() const;
175 175
176 /// Gets the ideal CPU core ID for this process 176 /// Gets the ideal CPU core ID for this process
177 u8 GetIdealCoreId() const { 177 u8 GetIdealCoreId() const {
@@ -348,9 +348,7 @@ public:
348 348
349 static void PostDestroy([[maybe_unused]] uintptr_t arg) {} 349 static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
350 350
351 virtual void Finalize() override { 351 virtual void Finalize();
352 UNIMPLEMENTED();
353 }
354 352
355 virtual u64 GetId() const override final { 353 virtual u64 GetId() const override final {
356 return GetProcessID(); 354 return GetProcessID();
@@ -415,7 +413,7 @@ private:
415 u32 system_resource_size = 0; 413 u32 system_resource_size = 0;
416 414
417 /// Resource limit descriptor for this process 415 /// Resource limit descriptor for this process
418 std::shared_ptr<KResourceLimit> resource_limit; 416 KResourceLimit* resource_limit{};
419 417
420 /// The ideal CPU core for this process, threads are scheduled on this core by default. 418 /// The ideal CPU core for this process, threads are scheduled on this core by default.
421 u8 ideal_core = 0; 419 u8 ideal_core = 0;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 9e8184758..a78bfd1da 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -153,9 +153,9 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_
153 const auto* const current_process = system.Kernel().CurrentProcess(); 153 const auto* const current_process = system.Kernel().CurrentProcess();
154 ASSERT(current_process != nullptr); 154 ASSERT(current_process != nullptr);
155 155
156 const auto resource_limit_object = 156 auto resource_limit_object =
157 current_process->GetHandleTable().Get<KResourceLimit>(resource_limit); 157 current_process->GetHandleTable().GetObject<KResourceLimit>(resource_limit);
158 if (!resource_limit_object) { 158 if (resource_limit_object.IsNull()) {
159 LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", 159 LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
160 resource_limit); 160 resource_limit);
161 return ResultInvalidHandle; 161 return ResultInvalidHandle;
@@ -843,12 +843,10 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle
843 return RESULT_SUCCESS; 843 return RESULT_SUCCESS;
844 } 844 }
845 845
846 const auto table_result = handle_table.Create(resource_limit.get()); 846 Handle handle{};
847 if (table_result.Failed()) { 847 R_TRY(handle_table.Add(&handle, resource_limit));
848 return table_result.Code();
849 }
850 848
851 *result = *table_result; 849 *result = handle;
852 return RESULT_SUCCESS; 850 return RESULT_SUCCESS;
853 } 851 }
854 852
@@ -2093,83 +2091,86 @@ static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_
2093} 2091}
2094 2092
2095static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) { 2093static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) {
2096 std::lock_guard lock{HLE::g_hle_lock};
2097 LOG_DEBUG(Kernel_SVC, "called"); 2094 LOG_DEBUG(Kernel_SVC, "called");
2098 2095
2096 // Create a new resource limit.
2099 auto& kernel = system.Kernel(); 2097 auto& kernel = system.Kernel();
2100 auto resource_limit = std::make_shared<KResourceLimit>(kernel, system.CoreTiming()); 2098 KResourceLimit* resource_limit = KResourceLimit::Create(kernel);
2099 R_UNLESS(resource_limit != nullptr, ResultOutOfResource);
2101 2100
2102 auto* const current_process = kernel.CurrentProcess(); 2101 // Ensure we don't leak a reference to the limit.
2103 ASSERT(current_process != nullptr); 2102 SCOPE_EXIT({ resource_limit->Close(); });
2104 2103
2105 const auto handle = current_process->GetHandleTable().Create(resource_limit.get()); 2104 // Initialize the resource limit.
2106 if (handle.Failed()) { 2105 resource_limit->Initialize(&system.CoreTiming());
2107 return handle.Code(); 2106
2108 } 2107 // Register the limit.
2108 KResourceLimit::Register(kernel, resource_limit);
2109
2110 // Add the limit to the handle table.
2111 R_TRY(kernel.CurrentProcess()->GetHandleTable().Add(out_handle, resource_limit));
2109 2112
2110 *out_handle = *handle;
2111 return RESULT_SUCCESS; 2113 return RESULT_SUCCESS;
2112} 2114}
2113 2115
2114static ResultCode GetResourceLimitLimitValue(Core::System& system, u64* out_value, 2116static ResultCode GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value,
2115 Handle resource_limit, u32 resource_type) { 2117 Handle resource_limit_handle,
2116 LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type); 2118 LimitableResource which) {
2119 LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle,
2120 which);
2117 2121
2118 const auto limit_value = RetrieveResourceLimitValue(system, resource_limit, resource_type, 2122 // Validate the resource.
2119 ResourceLimitValueType::LimitValue); 2123 R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue);
2120 if (limit_value.Failed()) { 2124
2121 return limit_value.Code(); 2125 // Get the resource limit.
2122 } 2126 auto& kernel = system.Kernel();
2127 KScopedAutoObject resource_limit =
2128 kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle);
2129 R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle);
2130
2131 // Get the limit value.
2132 *out_limit_value = resource_limit->GetLimitValue(which);
2123 2133
2124 *out_value = static_cast<u64>(*limit_value);
2125 return RESULT_SUCCESS; 2134 return RESULT_SUCCESS;
2126} 2135}
2127 2136
2128static ResultCode GetResourceLimitCurrentValue(Core::System& system, u64* out_value, 2137static ResultCode GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value,
2129 Handle resource_limit, u32 resource_type) { 2138 Handle resource_limit_handle,
2130 LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type); 2139 LimitableResource which) {
2140 LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle,
2141 which);
2131 2142
2132 const auto current_value = RetrieveResourceLimitValue(system, resource_limit, resource_type, 2143 // Validate the resource.
2133 ResourceLimitValueType::CurrentValue); 2144 R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue);
2134 if (current_value.Failed()) { 2145
2135 return current_value.Code(); 2146 // Get the resource limit.
2136 } 2147 auto& kernel = system.Kernel();
2148 KScopedAutoObject resource_limit =
2149 kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle);
2150 R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle);
2151
2152 // Get the current value.
2153 *out_current_value = resource_limit->GetCurrentValue(which);
2137 2154
2138 *out_value = static_cast<u64>(*current_value);
2139 return RESULT_SUCCESS; 2155 return RESULT_SUCCESS;
2140} 2156}
2141 2157
2142static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resource_limit, 2158static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle,
2143 u32 resource_type, u64 value) { 2159 LimitableResource which, u64 limit_value) {
2144 LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit, 2160 LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}, limit_value={}",
2145 resource_type, value); 2161 resource_limit_handle, which, limit_value);
2146 2162
2147 const auto type = static_cast<LimitableResource>(resource_type); 2163 // Validate the resource.
2148 if (!IsValidResourceType(type)) { 2164 R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue);
2149 LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
2150 return ResultInvalidEnumValue;
2151 }
2152
2153 auto* const current_process = system.Kernel().CurrentProcess();
2154 ASSERT(current_process != nullptr);
2155 2165
2156 auto resource_limit_object = 2166 // Get the resource limit.
2157 current_process->GetHandleTable().Get<KResourceLimit>(resource_limit); 2167 auto& kernel = system.Kernel();
2158 if (!resource_limit_object) { 2168 KScopedAutoObject resource_limit =
2159 LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", 2169 kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle);
2160 resource_limit); 2170 R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle);
2161 return ResultInvalidHandle;
2162 }
2163 2171
2164 const auto set_result = resource_limit_object->SetLimitValue(type, static_cast<s64>(value)); 2172 // Set the limit value.
2165 if (set_result.IsError()) { 2173 R_TRY(resource_limit->SetLimitValue(which, limit_value));
2166 LOG_ERROR(Kernel_SVC,
2167 "Attempted to lower resource limit ({}) for category '{}' below its current "
2168 "value ({})",
2169 resource_limit_object->GetLimitValue(type), resource_type,
2170 resource_limit_object->GetCurrentValue(type));
2171 return set_result;
2172 }
2173 2174
2174 return RESULT_SUCCESS; 2175 return RESULT_SUCCESS;
2175} 2176}
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index 61986bb52..d3df25d0f 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -154,15 +154,28 @@ void SvcWrap64(Core::System& system) {
154 FuncReturn(system, retval); 154 FuncReturn(system, retval);
155} 155}
156 156
157// Used by GetResourceLimitLimitValue.
158template <ResultCode func(Core::System&, u64*, Handle, LimitableResource)>
159void SvcWrap64(Core::System& system) {
160 u64 param_1 = 0;
161 const u32 retval = func(system, &param_1, static_cast<Handle>(Param(system, 1)),
162 static_cast<LimitableResource>(Param(system, 2)))
163 .raw;
164
165 system.CurrentArmInterface().SetReg(1, param_1);
166 FuncReturn(system, retval);
167}
168
157template <ResultCode func(Core::System&, u32, u64)> 169template <ResultCode func(Core::System&, u32, u64)>
158void SvcWrap64(Core::System& system) { 170void SvcWrap64(Core::System& system) {
159 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw); 171 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw);
160} 172}
161 173
162template <ResultCode func(Core::System&, u32, u32, u64)> 174// Used by SetResourceLimitLimitValue
175template <ResultCode func(Core::System&, Handle, LimitableResource, u64)>
163void SvcWrap64(Core::System& system) { 176void SvcWrap64(Core::System& system) {
164 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), 177 FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)),
165 static_cast<u32>(Param(system, 1)), Param(system, 2)) 178 static_cast<LimitableResource>(Param(system, 1)), Param(system, 2))
166 .raw); 179 .raw);
167} 180}
168 181