diff options
| author | 2021-02-04 20:06:54 -0500 | |
|---|---|---|
| committer | 2021-02-12 18:57:34 -0500 | |
| commit | 5fa6b15215d2c15a1601c88ac1125a28c55797fc (patch) | |
| tree | 4a25c58180aecd1eb9bcc3560a1a3dfa18c67761 /src/core/hle/kernel/process.cpp | |
| parent | kernel: Unify result codes (#5890) (diff) | |
| download | yuzu-5fa6b15215d2c15a1601c88ac1125a28c55797fc.tar.gz yuzu-5fa6b15215d2c15a1601c88ac1125a28c55797fc.tar.xz yuzu-5fa6b15215d2c15a1601c88ac1125a28c55797fc.zip | |
kernel: KScopedReservation implementation
This implements KScopedReservation, allowing resource limit reservations to be more HW accurate, and release upon failure without requiring too many conditionals.
Diffstat (limited to 'src/core/hle/kernel/process.cpp')
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 39dc3898a..05e21830c 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" |
| @@ -116,6 +117,9 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name, | |||
| 116 | 117 | ||
| 117 | std::shared_ptr<Process> process = std::make_shared<Process>(system); | 118 | std::shared_ptr<Process> process = std::make_shared<Process>(system); |
| 118 | process->name = std::move(name); | 119 | process->name = std::move(name); |
| 120 | |||
| 121 | // TODO: This is inaccurate | ||
| 122 | // The process should hold a reference to the kernel-wide resource limit. | ||
| 119 | process->resource_limit = std::make_shared<KResourceLimit>(kernel, system); | 123 | process->resource_limit = std::make_shared<KResourceLimit>(kernel, system); |
| 120 | process->status = ProcessStatus::Created; | 124 | process->status = ProcessStatus::Created; |
| 121 | process->program_id = 0; | 125 | process->program_id = 0; |
| @@ -154,6 +158,9 @@ void Process::DecrementThreadCount() { | |||
| 154 | } | 158 | } |
| 155 | 159 | ||
| 156 | u64 Process::GetTotalPhysicalMemoryAvailable() const { | 160 | u64 Process::GetTotalPhysicalMemoryAvailable() const { |
| 161 | // TODO: This is expected to always return the application memory pool size after accurately | ||
| 162 | // reserving kernel resources. The current workaround uses a process-local resource limit of | ||
| 163 | // application memory pool size, which is inaccurate. | ||
| 157 | const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + | 164 | const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + |
| 158 | page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + | 165 | page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + |
| 159 | main_thread_stack_size}; | 166 | main_thread_stack_size}; |
| @@ -263,6 +270,17 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | |||
| 263 | system_resource_size = metadata.GetSystemResourceSize(); | 270 | system_resource_size = metadata.GetSystemResourceSize(); |
| 264 | image_size = code_size; | 271 | image_size = code_size; |
| 265 | 272 | ||
| 273 | // Set initial resource limits | ||
| 274 | resource_limit->SetLimitValue( | ||
| 275 | LimitableResource::PhysicalMemory, | ||
| 276 | kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application)); | ||
| 277 | KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, | ||
| 278 | code_size + system_resource_size); | ||
| 279 | if (!memory_reservation.Succeeded()) { | ||
| 280 | LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes", | ||
| 281 | code_size + system_resource_size); | ||
| 282 | return ERR_RESOURCE_LIMIT_EXCEEDED; | ||
| 283 | } | ||
| 266 | // Initialize proces address space | 284 | // Initialize proces address space |
| 267 | if (const ResultCode result{ | 285 | if (const ResultCode result{ |
| 268 | page_table->InitializeForProcess(metadata.GetAddressSpaceType(), false, 0x8000000, | 286 | page_table->InitializeForProcess(metadata.GetAddressSpaceType(), false, 0x8000000, |
| @@ -304,24 +322,22 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | |||
| 304 | UNREACHABLE(); | 322 | UNREACHABLE(); |
| 305 | } | 323 | } |
| 306 | 324 | ||
| 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); | 325 | resource_limit->SetLimitValue(LimitableResource::Threads, 608); |
| 312 | resource_limit->SetLimitValue(LimitableResource::Events, 700); | 326 | resource_limit->SetLimitValue(LimitableResource::Events, 700); |
| 313 | resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128); | 327 | resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128); |
| 314 | resource_limit->SetLimitValue(LimitableResource::Sessions, 894); | 328 | resource_limit->SetLimitValue(LimitableResource::Sessions, 894); |
| 315 | ASSERT(resource_limit->Reserve(LimitableResource::PhysicalMemory, code_size)); | ||
| 316 | 329 | ||
| 317 | // Create TLS region | 330 | // Create TLS region |
| 318 | tls_region_address = CreateTLSRegion(); | 331 | tls_region_address = CreateTLSRegion(); |
| 332 | memory_reservation.Commit(); | ||
| 319 | 333 | ||
| 320 | return handle_table.SetSize(capabilities.GetHandleTableSize()); | 334 | return handle_table.SetSize(capabilities.GetHandleTableSize()); |
| 321 | } | 335 | } |
| 322 | 336 | ||
| 323 | void Process::Run(s32 main_thread_priority, u64 stack_size) { | 337 | void Process::Run(s32 main_thread_priority, u64 stack_size) { |
| 324 | AllocateMainThreadStack(stack_size); | 338 | AllocateMainThreadStack(stack_size); |
| 339 | resource_limit->Reserve(LimitableResource::Threads, 1); | ||
| 340 | resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size); | ||
| 325 | 341 | ||
| 326 | const std::size_t heap_capacity{memory_usage_capacity - main_thread_stack_size - image_size}; | 342 | const std::size_t heap_capacity{memory_usage_capacity - main_thread_stack_size - image_size}; |
| 327 | ASSERT(!page_table->SetHeapCapacity(heap_capacity).IsError()); | 343 | ASSERT(!page_table->SetHeapCapacity(heap_capacity).IsError()); |
| @@ -329,8 +345,6 @@ void Process::Run(s32 main_thread_priority, u64 stack_size) { | |||
| 329 | ChangeStatus(ProcessStatus::Running); | 345 | ChangeStatus(ProcessStatus::Running); |
| 330 | 346 | ||
| 331 | SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top); | 347 | 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 | } | 348 | } |
| 335 | 349 | ||
| 336 | void Process::PrepareForTermination() { | 350 | void Process::PrepareForTermination() { |
| @@ -357,6 +371,11 @@ void Process::PrepareForTermination() { | |||
| 357 | FreeTLSRegion(tls_region_address); | 371 | FreeTLSRegion(tls_region_address); |
| 358 | tls_region_address = 0; | 372 | tls_region_address = 0; |
| 359 | 373 | ||
| 374 | if (resource_limit) { | ||
| 375 | resource_limit->Release(LimitableResource::PhysicalMemory, | ||
| 376 | main_thread_stack_size + image_size); | ||
| 377 | } | ||
| 378 | |||
| 360 | ChangeStatus(ProcessStatus::Exited); | 379 | ChangeStatus(ProcessStatus::Exited); |
| 361 | } | 380 | } |
| 362 | 381 | ||