summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/hle/kernel/k_scoped_resource_reservation.h67
-rw-r--r--src/core/hle/kernel/kernel.cpp15
-rw-r--r--src/core/hle/kernel/memory/page_table.cpp37
-rw-r--r--src/core/hle/kernel/process.cpp34
-rw-r--r--src/core/hle/kernel/session.cpp11
-rw-r--r--src/core/hle/kernel/shared_memory.cpp11
-rw-r--r--src/core/hle/kernel/svc.cpp48
-rw-r--r--src/core/hle/kernel/transfer_memory.cpp2
9 files changed, 190 insertions, 36 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 52151e788..1662ec63d 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -174,6 +174,7 @@ add_library(core STATIC
174 hle/kernel/k_scheduler.h 174 hle/kernel/k_scheduler.h
175 hle/kernel/k_scheduler_lock.h 175 hle/kernel/k_scheduler_lock.h
176 hle/kernel/k_scoped_lock.h 176 hle/kernel/k_scoped_lock.h
177 hle/kernel/k_scoped_resource_reservation.h
177 hle/kernel/k_scoped_scheduler_lock_and_sleep.h 178 hle/kernel/k_scoped_scheduler_lock_and_sleep.h
178 hle/kernel/k_synchronization_object.cpp 179 hle/kernel/k_synchronization_object.cpp
179 hle/kernel/k_synchronization_object.h 180 hle/kernel/k_synchronization_object.h
diff --git a/src/core/hle/kernel/k_scoped_resource_reservation.h b/src/core/hle/kernel/k_scoped_resource_reservation.h
new file mode 100644
index 000000000..c5deca00b
--- /dev/null
+++ b/src/core/hle/kernel/k_scoped_resource_reservation.h
@@ -0,0 +1,67 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#pragma once
9
10#include "common/common_types.h"
11#include "core/hle/kernel/k_resource_limit.h"
12#include "core/hle/kernel/process.h"
13
14namespace Kernel {
15
16class KScopedResourceReservation {
17public:
18 explicit KScopedResourceReservation(std::shared_ptr<KResourceLimit> l, LimitableResource r,
19 s64 v, s64 timeout)
20 : resource_limit(std::move(l)), value(v), resource(r) {
21 if (resource_limit && value) {
22 success = resource_limit->Reserve(resource, value, timeout);
23 } else {
24 success = true;
25 }
26 }
27
28 explicit KScopedResourceReservation(std::shared_ptr<KResourceLimit> l, LimitableResource r,
29 s64 v = 1)
30 : resource_limit(std::move(l)), value(v), resource(r) {
31 if (resource_limit && value) {
32 success = resource_limit->Reserve(resource, value);
33 } else {
34 success = true;
35 }
36 }
37
38 explicit KScopedResourceReservation(const Process* p, LimitableResource r, s64 v, s64 t)
39 : KScopedResourceReservation(p->GetResourceLimit(), r, v, t) {}
40
41 explicit KScopedResourceReservation(const Process* p, LimitableResource r, s64 v = 1)
42 : KScopedResourceReservation(p->GetResourceLimit(), r, v) {}
43
44 ~KScopedResourceReservation() noexcept {
45 if (resource_limit && value && success) {
46 // resource was not committed, release the reservation.
47 resource_limit->Release(resource, value);
48 }
49 }
50
51 /// Commit the resource reservation, destruction of this object does not release the resource
52 void Commit() {
53 resource_limit = nullptr;
54 }
55
56 [[nodiscard]] bool Succeeded() const {
57 return success;
58 }
59
60private:
61 std::shared_ptr<KResourceLimit> resource_limit;
62 s64 value;
63 LimitableResource resource;
64 bool success;
65};
66
67} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 8da5a5c86..b6e6f115e 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -141,11 +141,17 @@ struct KernelCore::Impl {
141 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 700).IsSuccess()); 141 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 700).IsSuccess());
142 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) 142 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200)
143 .IsSuccess()); 143 .IsSuccess());
144 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 900).IsSuccess()); 144 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 933).IsSuccess());
145 145
146 if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, 0x60000)) { 146 // Derived from recent software updates. The kernel reserves 27MB
147 constexpr u64 kernel_size{0x1b00000};
148 if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size)) {
147 UNREACHABLE(); 149 UNREACHABLE();
148 } 150 }
151 // Reserve secure applet memory, introduced in firmware 5.0.0
152 constexpr u64 secure_applet_memory_size{0x400000};
153 ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
154 secure_applet_memory_size));
149 } 155 }
150 156
151 void InitializePreemption(KernelCore& kernel) { 157 void InitializePreemption(KernelCore& kernel) {
@@ -302,8 +308,11 @@ struct KernelCore::Impl {
302 // Allocate slab heaps 308 // Allocate slab heaps
303 user_slab_heap_pages = std::make_unique<Memory::SlabHeap<Memory::Page>>(); 309 user_slab_heap_pages = std::make_unique<Memory::SlabHeap<Memory::Page>>();
304 310
311 constexpr u64 user_slab_heap_size{0x1ef000};
312 // Reserve slab heaps
313 ASSERT(
314 system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size));
305 // Initialize slab heaps 315 // Initialize slab heaps
306 constexpr u64 user_slab_heap_size{0x3de000};
307 user_slab_heap_pages->Initialize( 316 user_slab_heap_pages->Initialize(
308 system.DeviceMemory().GetPointer(Core::DramMemoryMap::SlabHeapBase), 317 system.DeviceMemory().GetPointer(Core::DramMemoryMap::SlabHeapBase),
309 user_slab_heap_size); 318 user_slab_heap_size);
diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp
index 5947fc748..00ed9b881 100644
--- a/src/core/hle/kernel/memory/page_table.cpp
+++ b/src/core/hle/kernel/memory/page_table.cpp
@@ -6,7 +6,7 @@
6#include "common/assert.h" 6#include "common/assert.h"
7#include "common/scope_exit.h" 7#include "common/scope_exit.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/kernel/k_resource_limit.h" 9#include "core/hle/kernel/k_scoped_resource_reservation.h"
10#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/memory/address_space_info.h" 11#include "core/hle/kernel/memory/address_space_info.h"
12#include "core/hle/kernel/memory/memory_block.h" 12#include "core/hle/kernel/memory/memory_block.h"
@@ -409,27 +409,25 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
409 return RESULT_SUCCESS; 409 return RESULT_SUCCESS;
410 } 410 }
411 411
412 auto process{system.Kernel().CurrentProcess()};
413 const std::size_t remaining_size{size - mapped_size}; 412 const std::size_t remaining_size{size - mapped_size};
414 const std::size_t remaining_pages{remaining_size / PageSize}; 413 const std::size_t remaining_pages{remaining_size / PageSize};
415 414
416 if (process->GetResourceLimit() && 415 // Reserve the memory from the process resource limit.
417 !process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemory, remaining_size)) { 416 KScopedResourceReservation memory_reservation(
417 system.Kernel().CurrentProcess()->GetResourceLimit(), LimitableResource::PhysicalMemory,
418 remaining_size);
419 if (!memory_reservation.Succeeded()) {
420 LOG_ERROR(Kernel, "Could not reserve remaining {:X} bytes", remaining_size);
418 return ResultResourceLimitedExceeded; 421 return ResultResourceLimitedExceeded;
419 } 422 }
420 423
421 PageLinkedList page_linked_list; 424 PageLinkedList page_linked_list;
422 {
423 auto block_guard = detail::ScopeExit([&] {
424 system.Kernel().MemoryManager().Free(page_linked_list, remaining_pages, memory_pool);
425 process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, remaining_size);
426 });
427 425
428 CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, 426 CASCADE_CODE(
429 memory_pool)); 427 system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, memory_pool));
430 428
431 block_guard.Cancel(); 429 // We succeeded, so commit the memory reservation.
432 } 430 memory_reservation.Commit();
433 431
434 MapPhysicalMemory(page_linked_list, addr, end_addr); 432 MapPhysicalMemory(page_linked_list, addr, end_addr);
435 433
@@ -781,9 +779,13 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
781 779
782 const u64 delta{size - previous_heap_size}; 780 const u64 delta{size - previous_heap_size};
783 781
784 auto process{system.Kernel().CurrentProcess()}; 782 // Reserve memory for the heap extension.
785 if (process->GetResourceLimit() && delta != 0 && 783 KScopedResourceReservation memory_reservation(
786 !process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemory, delta)) { 784 system.Kernel().CurrentProcess()->GetResourceLimit(), LimitableResource::PhysicalMemory,
785 delta);
786
787 if (!memory_reservation.Succeeded()) {
788 LOG_ERROR(Kernel, "Could not reserve heap extension of size {:X} bytes", delta);
787 return ResultResourceLimitedExceeded; 789 return ResultResourceLimitedExceeded;
788 } 790 }
789 791
@@ -800,6 +802,9 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
800 CASCADE_CODE( 802 CASCADE_CODE(
801 Operate(current_heap_addr, num_pages, page_linked_list, OperationType::MapGroup)); 803 Operate(current_heap_addr, num_pages, page_linked_list, OperationType::MapGroup));
802 804
805 // Succeeded in allocation, commit the resource reservation
806 memory_reservation.Commit();
807
803 block_manager->Update(current_heap_addr, num_pages, MemoryState::Normal, 808 block_manager->Update(current_heap_addr, num_pages, MemoryState::Normal,
804 MemoryPermission::ReadAndWrite); 809 MemoryPermission::ReadAndWrite);
805 810
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 39dc3898a..47b3ac57b 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -16,6 +16,7 @@
16#include "core/hle/kernel/code_set.h" 16#include "core/hle/kernel/code_set.h"
17#include "core/hle/kernel/k_resource_limit.h" 17#include "core/hle/kernel/k_resource_limit.h"
18#include "core/hle/kernel/k_scheduler.h" 18#include "core/hle/kernel/k_scheduler.h"
19#include "core/hle/kernel/k_scoped_resource_reservation.h"
19#include "core/hle/kernel/k_thread.h" 20#include "core/hle/kernel/k_thread.h"
20#include "core/hle/kernel/kernel.h" 21#include "core/hle/kernel/kernel.h"
21#include "core/hle/kernel/memory/memory_block_manager.h" 22#include "core/hle/kernel/memory/memory_block_manager.h"
@@ -38,6 +39,7 @@ namespace {
38 */ 39 */
39void SetupMainThread(Core::System& system, Process& owner_process, u32 priority, VAddr stack_top) { 40void SetupMainThread(Core::System& system, Process& owner_process, u32 priority, VAddr stack_top) {
40 const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart(); 41 const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart();
42 ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::Threads, 1));
41 auto thread_res = KThread::Create(system, ThreadType::User, "main", entry_point, priority, 0, 43 auto thread_res = KThread::Create(system, ThreadType::User, "main", entry_point, priority, 0,
42 owner_process.GetIdealCoreId(), stack_top, &owner_process); 44 owner_process.GetIdealCoreId(), stack_top, &owner_process);
43 45
@@ -116,6 +118,9 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
116 118
117 std::shared_ptr<Process> process = std::make_shared<Process>(system); 119 std::shared_ptr<Process> process = std::make_shared<Process>(system);
118 process->name = std::move(name); 120 process->name = std::move(name);
121
122 // TODO: This is inaccurate
123 // The process should hold a reference to the kernel-wide resource limit.
119 process->resource_limit = std::make_shared<KResourceLimit>(kernel, system); 124 process->resource_limit = std::make_shared<KResourceLimit>(kernel, system);
120 process->status = ProcessStatus::Created; 125 process->status = ProcessStatus::Created;
121 process->program_id = 0; 126 process->program_id = 0;
@@ -154,6 +159,9 @@ void Process::DecrementThreadCount() {
154} 159}
155 160
156u64 Process::GetTotalPhysicalMemoryAvailable() const { 161u64 Process::GetTotalPhysicalMemoryAvailable() const {
162 // TODO: This is expected to always return the application memory pool size after accurately
163 // reserving kernel resources. The current workaround uses a process-local resource limit of
164 // application memory pool size, which is inaccurate.
157 const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + 165 const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
158 page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + 166 page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
159 main_thread_stack_size}; 167 main_thread_stack_size};
@@ -263,6 +271,17 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
263 system_resource_size = metadata.GetSystemResourceSize(); 271 system_resource_size = metadata.GetSystemResourceSize();
264 image_size = code_size; 272 image_size = code_size;
265 273
274 // Set initial resource limits
275 resource_limit->SetLimitValue(
276 LimitableResource::PhysicalMemory,
277 kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application));
278 KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory,
279 code_size + system_resource_size);
280 if (!memory_reservation.Succeeded()) {
281 LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes",
282 code_size + system_resource_size);
283 return ResultResourceLimitedExceeded;
284 }
266 // Initialize proces address space 285 // Initialize proces address space
267 if (const ResultCode result{ 286 if (const ResultCode result{
268 page_table->InitializeForProcess(metadata.GetAddressSpaceType(), false, 0x8000000, 287 page_table->InitializeForProcess(metadata.GetAddressSpaceType(), false, 0x8000000,
@@ -304,24 +323,22 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
304 UNREACHABLE(); 323 UNREACHABLE();
305 } 324 }
306 325
307 // Set initial resource limits
308 resource_limit->SetLimitValue(
309 LimitableResource::PhysicalMemory,
310 kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application));
311 resource_limit->SetLimitValue(LimitableResource::Threads, 608); 326 resource_limit->SetLimitValue(LimitableResource::Threads, 608);
312 resource_limit->SetLimitValue(LimitableResource::Events, 700); 327 resource_limit->SetLimitValue(LimitableResource::Events, 700);
313 resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128); 328 resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128);
314 resource_limit->SetLimitValue(LimitableResource::Sessions, 894); 329 resource_limit->SetLimitValue(LimitableResource::Sessions, 894);
315 ASSERT(resource_limit->Reserve(LimitableResource::PhysicalMemory, code_size));
316 330
317 // Create TLS region 331 // Create TLS region
318 tls_region_address = CreateTLSRegion(); 332 tls_region_address = CreateTLSRegion();
333 memory_reservation.Commit();
319 334
320 return handle_table.SetSize(capabilities.GetHandleTableSize()); 335 return handle_table.SetSize(capabilities.GetHandleTableSize());
321} 336}
322 337
323void Process::Run(s32 main_thread_priority, u64 stack_size) { 338void Process::Run(s32 main_thread_priority, u64 stack_size) {
324 AllocateMainThreadStack(stack_size); 339 AllocateMainThreadStack(stack_size);
340 resource_limit->Reserve(LimitableResource::Threads, 1);
341 resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size);
325 342
326 const std::size_t heap_capacity{memory_usage_capacity - main_thread_stack_size - image_size}; 343 const std::size_t heap_capacity{memory_usage_capacity - main_thread_stack_size - image_size};
327 ASSERT(!page_table->SetHeapCapacity(heap_capacity).IsError()); 344 ASSERT(!page_table->SetHeapCapacity(heap_capacity).IsError());
@@ -329,8 +346,6 @@ void Process::Run(s32 main_thread_priority, u64 stack_size) {
329 ChangeStatus(ProcessStatus::Running); 346 ChangeStatus(ProcessStatus::Running);
330 347
331 SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top); 348 SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top);
332 resource_limit->Reserve(LimitableResource::Threads, 1);
333 resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size);
334} 349}
335 350
336void Process::PrepareForTermination() { 351void Process::PrepareForTermination() {
@@ -357,6 +372,11 @@ void Process::PrepareForTermination() {
357 FreeTLSRegion(tls_region_address); 372 FreeTLSRegion(tls_region_address);
358 tls_region_address = 0; 373 tls_region_address = 0;
359 374
375 if (resource_limit) {
376 resource_limit->Release(LimitableResource::PhysicalMemory,
377 main_thread_stack_size + image_size);
378 }
379
360 ChangeStatus(ProcessStatus::Exited); 380 ChangeStatus(ProcessStatus::Exited);
361} 381}
362 382
diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp
index 75304b961..8830d4e91 100644
--- a/src/core/hle/kernel/session.cpp
+++ b/src/core/hle/kernel/session.cpp
@@ -4,15 +4,23 @@
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "core/hle/kernel/client_session.h" 6#include "core/hle/kernel/client_session.h"
7#include "core/hle/kernel/k_scoped_resource_reservation.h"
7#include "core/hle/kernel/server_session.h" 8#include "core/hle/kernel/server_session.h"
8#include "core/hle/kernel/session.h" 9#include "core/hle/kernel/session.h"
9 10
10namespace Kernel { 11namespace Kernel {
11 12
12Session::Session(KernelCore& kernel) : KSynchronizationObject{kernel} {} 13Session::Session(KernelCore& kernel) : KSynchronizationObject{kernel} {}
13Session::~Session() = default; 14Session::~Session() {
15 // Release reserved resource when the Session pair was created.
16 kernel.GetSystemResourceLimit()->Release(LimitableResource::Sessions, 1);
17}
14 18
15Session::SessionPair Session::Create(KernelCore& kernel, std::string name) { 19Session::SessionPair Session::Create(KernelCore& kernel, std::string name) {
20 // Reserve a new session from the resource limit.
21 KScopedResourceReservation session_reservation(kernel.GetSystemResourceLimit(),
22 LimitableResource::Sessions);
23 ASSERT(session_reservation.Succeeded());
16 auto session{std::make_shared<Session>(kernel)}; 24 auto session{std::make_shared<Session>(kernel)};
17 auto client_session{Kernel::ClientSession::Create(kernel, session, name + "_Client").Unwrap()}; 25 auto client_session{Kernel::ClientSession::Create(kernel, session, name + "_Client").Unwrap()};
18 auto server_session{Kernel::ServerSession::Create(kernel, session, name + "_Server").Unwrap()}; 26 auto server_session{Kernel::ServerSession::Create(kernel, session, name + "_Server").Unwrap()};
@@ -21,6 +29,7 @@ Session::SessionPair Session::Create(KernelCore& kernel, std::string name) {
21 session->client = client_session; 29 session->client = client_session;
22 session->server = server_session; 30 session->server = server_session;
23 31
32 session_reservation.Commit();
24 return std::make_pair(std::move(client_session), std::move(server_session)); 33 return std::make_pair(std::move(client_session), std::move(server_session));
25} 34}
26 35
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 0cd467110..2eadd51d7 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -4,6 +4,7 @@
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "core/core.h" 6#include "core/core.h"
7#include "core/hle/kernel/k_scoped_resource_reservation.h"
7#include "core/hle/kernel/kernel.h" 8#include "core/hle/kernel/kernel.h"
8#include "core/hle/kernel/memory/page_table.h" 9#include "core/hle/kernel/memory/page_table.h"
9#include "core/hle/kernel/shared_memory.h" 10#include "core/hle/kernel/shared_memory.h"
@@ -13,7 +14,9 @@ namespace Kernel {
13SharedMemory::SharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory) 14SharedMemory::SharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory)
14 : Object{kernel}, device_memory{device_memory} {} 15 : Object{kernel}, device_memory{device_memory} {}
15 16
16SharedMemory::~SharedMemory() = default; 17SharedMemory::~SharedMemory() {
18 kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size);
19}
17 20
18std::shared_ptr<SharedMemory> SharedMemory::Create( 21std::shared_ptr<SharedMemory> SharedMemory::Create(
19 KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process, 22 KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process,
@@ -21,6 +24,11 @@ std::shared_ptr<SharedMemory> SharedMemory::Create(
21 Memory::MemoryPermission user_permission, PAddr physical_address, std::size_t size, 24 Memory::MemoryPermission user_permission, PAddr physical_address, std::size_t size,
22 std::string name) { 25 std::string name) {
23 26
27 const auto resource_limit = kernel.GetSystemResourceLimit();
28 KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory,
29 size);
30 ASSERT(memory_reservation.Succeeded());
31
24 std::shared_ptr<SharedMemory> shared_memory{ 32 std::shared_ptr<SharedMemory> shared_memory{
25 std::make_shared<SharedMemory>(kernel, device_memory)}; 33 std::make_shared<SharedMemory>(kernel, device_memory)};
26 34
@@ -32,6 +40,7 @@ std::shared_ptr<SharedMemory> SharedMemory::Create(
32 shared_memory->size = size; 40 shared_memory->size = size;
33 shared_memory->name = name; 41 shared_memory->name = name;
34 42
43 memory_reservation.Commit();
35 return shared_memory; 44 return shared_memory;
36} 45}
37 46
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 4ef3c7ac5..31d899e06 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -30,6 +30,7 @@
30#include "core/hle/kernel/k_readable_event.h" 30#include "core/hle/kernel/k_readable_event.h"
31#include "core/hle/kernel/k_resource_limit.h" 31#include "core/hle/kernel/k_resource_limit.h"
32#include "core/hle/kernel/k_scheduler.h" 32#include "core/hle/kernel/k_scheduler.h"
33#include "core/hle/kernel/k_scoped_resource_reservation.h"
33#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 34#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
34#include "core/hle/kernel/k_synchronization_object.h" 35#include "core/hle/kernel/k_synchronization_object.h"
35#include "core/hle/kernel/k_thread.h" 36#include "core/hle/kernel/k_thread.h"
@@ -137,6 +138,7 @@ ResultCode MapUnmapMemorySanityChecks(const Memory::PageTable& manager, VAddr ds
137enum class ResourceLimitValueType { 138enum class ResourceLimitValueType {
138 CurrentValue, 139 CurrentValue,
139 LimitValue, 140 LimitValue,
141 PeakValue,
140}; 142};
141 143
142ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit, 144ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit,
@@ -159,11 +161,17 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_
159 return ResultInvalidHandle; 161 return ResultInvalidHandle;
160 } 162 }
161 163
162 if (value_type == ResourceLimitValueType::CurrentValue) { 164 switch (value_type) {
165 case ResourceLimitValueType::CurrentValue:
163 return MakeResult(resource_limit_object->GetCurrentValue(type)); 166 return MakeResult(resource_limit_object->GetCurrentValue(type));
167 case ResourceLimitValueType::LimitValue:
168 return MakeResult(resource_limit_object->GetLimitValue(type));
169 case ResourceLimitValueType::PeakValue:
170 return MakeResult(resource_limit_object->GetPeakValue(type));
171 default:
172 LOG_ERROR(Kernel_SVC, "Invalid resource value_type: '{}'", value_type);
173 return ResultInvalidEnumValue;
164 } 174 }
165
166 return MakeResult(resource_limit_object->GetLimitValue(type));
167} 175}
168} // Anonymous namespace 176} // Anonymous namespace
169 177
@@ -313,8 +321,6 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
313 return ResultNotFound; 321 return ResultNotFound;
314 } 322 }
315 323
316 ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(LimitableResource::Sessions, 1));
317
318 auto client_port = it->second; 324 auto client_port = it->second;
319 325
320 std::shared_ptr<ClientSession> client_session; 326 std::shared_ptr<ClientSession> client_session;
@@ -1516,8 +1522,13 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
1516 return ResultInvalidPriority; 1522 return ResultInvalidPriority;
1517 } 1523 }
1518 1524
1519 ASSERT(process.GetResourceLimit()->Reserve( 1525 KScopedResourceReservation thread_reservation(
1520 LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000)); 1526 kernel.CurrentProcess(), LimitableResource::Threads, 1,
1527 system.CoreTiming().GetGlobalTimeNs().count() + 100000000);
1528 if (!thread_reservation.Succeeded()) {
1529 LOG_ERROR(Kernel_SVC, "Could not reserve a new thread");
1530 return ResultResourceLimitedExceeded;
1531 }
1521 1532
1522 std::shared_ptr<KThread> thread; 1533 std::shared_ptr<KThread> thread;
1523 { 1534 {
@@ -1537,6 +1548,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
1537 // Set the thread name for debugging purposes. 1548 // Set the thread name for debugging purposes.
1538 thread->SetName( 1549 thread->SetName(
1539 fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle)); 1550 fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle));
1551 thread_reservation.Commit();
1540 1552
1541 return RESULT_SUCCESS; 1553 return RESULT_SUCCESS;
1542} 1554}
@@ -1884,6 +1896,13 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
1884 } 1896 }
1885 1897
1886 auto& kernel = system.Kernel(); 1898 auto& kernel = system.Kernel();
1899 // Reserve a new transfer memory from the process resource limit.
1900 KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(),
1901 LimitableResource::TransferMemory);
1902 if (!trmem_reservation.Succeeded()) {
1903 LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory");
1904 return ResultResourceLimitedExceeded;
1905 }
1887 auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms); 1906 auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms);
1888 1907
1889 if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) { 1908 if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) {
@@ -1895,6 +1914,7 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
1895 if (result.Failed()) { 1914 if (result.Failed()) {
1896 return result.Code(); 1915 return result.Code();
1897 } 1916 }
1917 trmem_reservation.Commit();
1898 1918
1899 *handle = *result; 1919 *handle = *result;
1900 return RESULT_SUCCESS; 1920 return RESULT_SUCCESS;
@@ -2002,8 +2022,17 @@ static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle
2002static ResultCode SignalEvent(Core::System& system, Handle event_handle) { 2022static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
2003 LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle); 2023 LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
2004 2024
2025 auto& kernel = system.Kernel();
2005 // Get the current handle table. 2026 // Get the current handle table.
2006 const HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 2027 const HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
2028
2029 // Reserve a new event from the process resource limit.
2030 KScopedResourceReservation event_reservation(kernel.CurrentProcess(),
2031 LimitableResource::Events);
2032 if (!event_reservation.Succeeded()) {
2033 LOG_ERROR(Kernel, "Could not reserve a new event");
2034 return ResultResourceLimitedExceeded;
2035 }
2007 2036
2008 // Get the writable event. 2037 // Get the writable event.
2009 auto writable_event = handle_table.Get<KWritableEvent>(event_handle); 2038 auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
@@ -2012,6 +2041,9 @@ static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
2012 return ResultInvalidHandle; 2041 return ResultInvalidHandle;
2013 } 2042 }
2014 2043
2044 // Commit the successfuly reservation.
2045 event_reservation.Commit();
2046
2015 return writable_event->Signal(); 2047 return writable_event->Signal();
2016} 2048}
2017 2049
diff --git a/src/core/hle/kernel/transfer_memory.cpp b/src/core/hle/kernel/transfer_memory.cpp
index 765f408c3..6b0fc1591 100644
--- a/src/core/hle/kernel/transfer_memory.cpp
+++ b/src/core/hle/kernel/transfer_memory.cpp
@@ -2,6 +2,7 @@
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 "core/hle/kernel/k_resource_limit.h"
5#include "core/hle/kernel/kernel.h" 6#include "core/hle/kernel/kernel.h"
6#include "core/hle/kernel/memory/page_table.h" 7#include "core/hle/kernel/memory/page_table.h"
7#include "core/hle/kernel/process.h" 8#include "core/hle/kernel/process.h"
@@ -17,6 +18,7 @@ TransferMemory::TransferMemory(KernelCore& kernel, Core::Memory::Memory& memory)
17TransferMemory::~TransferMemory() { 18TransferMemory::~TransferMemory() {
18 // Release memory region when transfer memory is destroyed 19 // Release memory region when transfer memory is destroyed
19 Reset(); 20 Reset();
21 owner_process->GetResourceLimit()->Release(LimitableResource::TransferMemory, 1);
20} 22}
21 23
22std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, 24std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel,