diff options
| author | 2024-01-16 00:09:00 +0000 | |
|---|---|---|
| committer | 2024-01-16 00:09:00 +0000 | |
| commit | 90ab89a0b0174f8df559b79dc06a03479d959f93 (patch) | |
| tree | 3d11a790e44945e309f0e68f5332b33b42e72bbb /src/core/hle/kernel | |
| parent | Fix typos in arrays.xml (diff) | |
| parent | Merge pull request #12681 from t895/stick-toggles (diff) | |
| download | yuzu-90ab89a0b0174f8df559b79dc06a03479d959f93.tar.gz yuzu-90ab89a0b0174f8df559b79dc06a03479d959f93.tar.xz yuzu-90ab89a0b0174f8df559b79dc06a03479d959f93.zip | |
Merge remote-tracking branch 'origin/master' into typos3
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/k_memory_block_manager.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_memory_block_manager.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table_base.cpp | 34 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table_base.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.cpp | 10 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 31 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc/svc_process.cpp | 8 |
8 files changed, 81 insertions, 17 deletions
diff --git a/src/core/hle/kernel/k_memory_block_manager.cpp b/src/core/hle/kernel/k_memory_block_manager.cpp index 58a1e7216..f08a6e448 100644 --- a/src/core/hle/kernel/k_memory_block_manager.cpp +++ b/src/core/hle/kernel/k_memory_block_manager.cpp | |||
| @@ -28,14 +28,14 @@ Result KMemoryBlockManager::Initialize(KProcessAddress st, KProcessAddress nd, | |||
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager, | 30 | void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager, |
| 31 | HostUnmapCallback&& host_unmap_callback) { | 31 | BlockCallback&& block_callback) { |
| 32 | // Erase every block until we have none left. | 32 | // Erase every block until we have none left. |
| 33 | auto it = m_memory_block_tree.begin(); | 33 | auto it = m_memory_block_tree.begin(); |
| 34 | while (it != m_memory_block_tree.end()) { | 34 | while (it != m_memory_block_tree.end()) { |
| 35 | KMemoryBlock* block = std::addressof(*it); | 35 | KMemoryBlock* block = std::addressof(*it); |
| 36 | it = m_memory_block_tree.erase(it); | 36 | it = m_memory_block_tree.erase(it); |
| 37 | block_callback(block->GetAddress(), block->GetSize()); | ||
| 37 | slab_manager->Free(block); | 38 | slab_manager->Free(block); |
| 38 | host_unmap_callback(block->GetAddress(), block->GetSize()); | ||
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | ASSERT(m_memory_block_tree.empty()); | 41 | ASSERT(m_memory_block_tree.empty()); |
diff --git a/src/core/hle/kernel/k_memory_block_manager.h b/src/core/hle/kernel/k_memory_block_manager.h index cb7b6f430..377628504 100644 --- a/src/core/hle/kernel/k_memory_block_manager.h +++ b/src/core/hle/kernel/k_memory_block_manager.h | |||
| @@ -85,11 +85,11 @@ public: | |||
| 85 | public: | 85 | public: |
| 86 | KMemoryBlockManager(); | 86 | KMemoryBlockManager(); |
| 87 | 87 | ||
| 88 | using HostUnmapCallback = std::function<void(Common::ProcessAddress, u64)>; | 88 | using BlockCallback = std::function<void(Common::ProcessAddress, u64)>; |
| 89 | 89 | ||
| 90 | Result Initialize(KProcessAddress st, KProcessAddress nd, | 90 | Result Initialize(KProcessAddress st, KProcessAddress nd, |
| 91 | KMemoryBlockSlabManager* slab_manager); | 91 | KMemoryBlockSlabManager* slab_manager); |
| 92 | void Finalize(KMemoryBlockSlabManager* slab_manager, HostUnmapCallback&& host_unmap_callback); | 92 | void Finalize(KMemoryBlockSlabManager* slab_manager, BlockCallback&& block_callback); |
| 93 | 93 | ||
| 94 | iterator end() { | 94 | iterator end() { |
| 95 | return m_memory_block_tree.end(); | 95 | return m_memory_block_tree.end(); |
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 73fbda331..3f0a39d33 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp | |||
| @@ -431,15 +431,43 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool | |||
| 431 | m_memory_block_slab_manager)); | 431 | m_memory_block_slab_manager)); |
| 432 | } | 432 | } |
| 433 | 433 | ||
| 434 | Result KPageTableBase::FinalizeProcess() { | ||
| 435 | // Only process tables should be finalized. | ||
| 436 | ASSERT(!this->IsKernel()); | ||
| 437 | |||
| 438 | // NOTE: Here Nintendo calls an unknown OnFinalize function. | ||
| 439 | // this->OnFinalize(); | ||
| 440 | |||
| 441 | // NOTE: Here Nintendo calls a second unknown OnFinalize function. | ||
| 442 | // this->OnFinalize2(); | ||
| 443 | |||
| 444 | // NOTE: Here Nintendo does a page table walk to discover heap pages to free. | ||
| 445 | // We will use the block manager finalization below to free them. | ||
| 446 | |||
| 447 | R_SUCCEED(); | ||
| 448 | } | ||
| 449 | |||
| 434 | void KPageTableBase::Finalize() { | 450 | void KPageTableBase::Finalize() { |
| 435 | auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) { | 451 | this->FinalizeProcess(); |
| 436 | if (Settings::IsFastmemEnabled()) { | 452 | |
| 453 | auto BlockCallback = [&](KProcessAddress addr, u64 size) { | ||
| 454 | if (m_impl->fastmem_arena) { | ||
| 437 | m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false); | 455 | m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false); |
| 438 | } | 456 | } |
| 457 | |||
| 458 | // Get physical pages. | ||
| 459 | KPageGroup pg(m_kernel, m_block_info_manager); | ||
| 460 | this->MakePageGroup(pg, addr, size / PageSize); | ||
| 461 | |||
| 462 | // Free the pages. | ||
| 463 | pg.CloseAndReset(); | ||
| 439 | }; | 464 | }; |
| 440 | 465 | ||
| 441 | // Finalize memory blocks. | 466 | // Finalize memory blocks. |
| 442 | m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(HostUnmapCallback)); | 467 | { |
| 468 | KScopedLightLock lk(m_general_lock); | ||
| 469 | m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(BlockCallback)); | ||
| 470 | } | ||
| 443 | 471 | ||
| 444 | // Free any unsafe mapped memory. | 472 | // Free any unsafe mapped memory. |
| 445 | if (m_mapped_unsafe_physical_memory) { | 473 | if (m_mapped_unsafe_physical_memory) { |
diff --git a/src/core/hle/kernel/k_page_table_base.h b/src/core/hle/kernel/k_page_table_base.h index 077cafc96..748419f86 100644 --- a/src/core/hle/kernel/k_page_table_base.h +++ b/src/core/hle/kernel/k_page_table_base.h | |||
| @@ -241,6 +241,7 @@ public: | |||
| 241 | KResourceLimit* resource_limit, Core::Memory::Memory& memory, | 241 | KResourceLimit* resource_limit, Core::Memory::Memory& memory, |
| 242 | KProcessAddress aslr_space_start); | 242 | KProcessAddress aslr_space_start); |
| 243 | 243 | ||
| 244 | Result FinalizeProcess(); | ||
| 244 | void Finalize(); | 245 | void Finalize(); |
| 245 | 246 | ||
| 246 | bool IsKernel() const { | 247 | bool IsKernel() const { |
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 068e71dff..53735a225 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -171,6 +171,12 @@ void KProcess::Finalize() { | |||
| 171 | m_resource_limit->Close(); | 171 | m_resource_limit->Close(); |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | // Clear expensive resources, as the destructor is not called for guest objects. | ||
| 175 | for (auto& interface : m_arm_interfaces) { | ||
| 176 | interface.reset(); | ||
| 177 | } | ||
| 178 | m_exclusive_monitor.reset(); | ||
| 179 | |||
| 174 | // Perform inherited finalization. | 180 | // Perform inherited finalization. |
| 175 | KSynchronizationObject::Finalize(); | 181 | KSynchronizationObject::Finalize(); |
| 176 | } | 182 | } |
| @@ -1233,10 +1239,10 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { | |||
| 1233 | ReprotectSegment(code_set.DataSegment(), Svc::MemoryPermission::ReadWrite); | 1239 | ReprotectSegment(code_set.DataSegment(), Svc::MemoryPermission::ReadWrite); |
| 1234 | 1240 | ||
| 1235 | #ifdef HAS_NCE | 1241 | #ifdef HAS_NCE |
| 1236 | if (this->IsApplication() && Settings::IsNceEnabled()) { | 1242 | const auto& patch = code_set.PatchSegment(); |
| 1243 | if (this->IsApplication() && Settings::IsNceEnabled() && patch.size != 0) { | ||
| 1237 | auto& buffer = m_kernel.System().DeviceMemory().buffer; | 1244 | auto& buffer = m_kernel.System().DeviceMemory().buffer; |
| 1238 | const auto& code = code_set.CodeSegment(); | 1245 | const auto& code = code_set.CodeSegment(); |
| 1239 | const auto& patch = code_set.PatchSegment(); | ||
| 1240 | buffer.Protect(GetInteger(base_addr + code.addr), code.size, | 1246 | buffer.Protect(GetInteger(base_addr + code.addr), code.size, |
| 1241 | Common::MemoryPermission::Read | Common::MemoryPermission::Execute); | 1247 | Common::MemoryPermission::Read | Common::MemoryPermission::Execute); |
| 1242 | buffer.Protect(GetInteger(base_addr + patch.addr), patch.size, | 1248 | buffer.Protect(GetInteger(base_addr + patch.addr), patch.size, |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 1030f0c12..f3683cdcc 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -112,7 +112,14 @@ struct KernelCore::Impl { | |||
| 112 | old_process->Close(); | 112 | old_process->Close(); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | process_list.clear(); | 115 | { |
| 116 | std::scoped_lock lk{process_list_lock}; | ||
| 117 | for (auto* const process : process_list) { | ||
| 118 | process->Terminate(); | ||
| 119 | process->Close(); | ||
| 120 | } | ||
| 121 | process_list.clear(); | ||
| 122 | } | ||
| 116 | 123 | ||
| 117 | next_object_id = 0; | 124 | next_object_id = 0; |
| 118 | next_kernel_process_id = KProcess::InitialProcessIdMin; | 125 | next_kernel_process_id = KProcess::InitialProcessIdMin; |
| @@ -770,6 +777,7 @@ struct KernelCore::Impl { | |||
| 770 | std::atomic<u64> next_thread_id{1}; | 777 | std::atomic<u64> next_thread_id{1}; |
| 771 | 778 | ||
| 772 | // Lists all processes that exist in the current session. | 779 | // Lists all processes that exist in the current session. |
| 780 | std::mutex process_list_lock; | ||
| 773 | std::vector<KProcess*> process_list; | 781 | std::vector<KProcess*> process_list; |
| 774 | std::atomic<KProcess*> application_process{}; | 782 | std::atomic<KProcess*> application_process{}; |
| 775 | std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; | 783 | std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; |
| @@ -869,9 +877,19 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() { | |||
| 869 | } | 877 | } |
| 870 | 878 | ||
| 871 | void KernelCore::AppendNewProcess(KProcess* process) { | 879 | void KernelCore::AppendNewProcess(KProcess* process) { |
| 880 | process->Open(); | ||
| 881 | |||
| 882 | std::scoped_lock lk{impl->process_list_lock}; | ||
| 872 | impl->process_list.push_back(process); | 883 | impl->process_list.push_back(process); |
| 873 | } | 884 | } |
| 874 | 885 | ||
| 886 | void KernelCore::RemoveProcess(KProcess* process) { | ||
| 887 | std::scoped_lock lk{impl->process_list_lock}; | ||
| 888 | if (std::erase(impl->process_list, process)) { | ||
| 889 | process->Close(); | ||
| 890 | } | ||
| 891 | } | ||
| 892 | |||
| 875 | void KernelCore::MakeApplicationProcess(KProcess* process) { | 893 | void KernelCore::MakeApplicationProcess(KProcess* process) { |
| 876 | impl->MakeApplicationProcess(process); | 894 | impl->MakeApplicationProcess(process); |
| 877 | } | 895 | } |
| @@ -884,8 +902,15 @@ const KProcess* KernelCore::ApplicationProcess() const { | |||
| 884 | return impl->application_process; | 902 | return impl->application_process; |
| 885 | } | 903 | } |
| 886 | 904 | ||
| 887 | const std::vector<KProcess*>& KernelCore::GetProcessList() const { | 905 | std::list<KScopedAutoObject<KProcess>> KernelCore::GetProcessList() { |
| 888 | return impl->process_list; | 906 | std::list<KScopedAutoObject<KProcess>> processes; |
| 907 | std::scoped_lock lk{impl->process_list_lock}; | ||
| 908 | |||
| 909 | for (auto* const process : impl->process_list) { | ||
| 910 | processes.emplace_back(process); | ||
| 911 | } | ||
| 912 | |||
| 913 | return processes; | ||
| 889 | } | 914 | } |
| 890 | 915 | ||
| 891 | Kernel::GlobalSchedulerContext& KernelCore::GlobalSchedulerContext() { | 916 | Kernel::GlobalSchedulerContext& KernelCore::GlobalSchedulerContext() { |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 5d4102145..8ea5bed1c 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <functional> | 7 | #include <functional> |
| 8 | #include <list> | ||
| 8 | #include <memory> | 9 | #include <memory> |
| 9 | #include <string> | 10 | #include <string> |
| 10 | #include <unordered_map> | 11 | #include <unordered_map> |
| @@ -116,8 +117,9 @@ public: | |||
| 116 | /// Retrieves a shared pointer to the system resource limit instance. | 117 | /// Retrieves a shared pointer to the system resource limit instance. |
| 117 | KResourceLimit* GetSystemResourceLimit(); | 118 | KResourceLimit* GetSystemResourceLimit(); |
| 118 | 119 | ||
| 119 | /// Adds the given shared pointer to an internal list of active processes. | 120 | /// Adds/removes the given pointer to an internal list of active processes. |
| 120 | void AppendNewProcess(KProcess* process); | 121 | void AppendNewProcess(KProcess* process); |
| 122 | void RemoveProcess(KProcess* process); | ||
| 121 | 123 | ||
| 122 | /// Makes the given process the new application process. | 124 | /// Makes the given process the new application process. |
| 123 | void MakeApplicationProcess(KProcess* process); | 125 | void MakeApplicationProcess(KProcess* process); |
| @@ -129,7 +131,7 @@ public: | |||
| 129 | const KProcess* ApplicationProcess() const; | 131 | const KProcess* ApplicationProcess() const; |
| 130 | 132 | ||
| 131 | /// Retrieves the list of processes. | 133 | /// Retrieves the list of processes. |
| 132 | const std::vector<KProcess*>& GetProcessList() const; | 134 | std::list<KScopedAutoObject<KProcess>> GetProcessList(); |
| 133 | 135 | ||
| 134 | /// Gets the sole instance of the global scheduler | 136 | /// Gets the sole instance of the global scheduler |
| 135 | Kernel::GlobalSchedulerContext& GlobalSchedulerContext(); | 137 | Kernel::GlobalSchedulerContext& GlobalSchedulerContext(); |
diff --git a/src/core/hle/kernel/svc/svc_process.cpp b/src/core/hle/kernel/svc/svc_process.cpp index caa8bee9a..5c3e8829f 100644 --- a/src/core/hle/kernel/svc/svc_process.cpp +++ b/src/core/hle/kernel/svc/svc_process.cpp | |||
| @@ -74,13 +74,15 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc | |||
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | auto& memory = GetCurrentMemory(kernel); | 76 | auto& memory = GetCurrentMemory(kernel); |
| 77 | const auto& process_list = kernel.GetProcessList(); | 77 | auto process_list = kernel.GetProcessList(); |
| 78 | auto it = process_list.begin(); | ||
| 79 | |||
| 78 | const auto num_processes = process_list.size(); | 80 | const auto num_processes = process_list.size(); |
| 79 | const auto copy_amount = | 81 | const auto copy_amount = |
| 80 | std::min(static_cast<std::size_t>(out_process_ids_size), num_processes); | 82 | std::min(static_cast<std::size_t>(out_process_ids_size), num_processes); |
| 81 | 83 | ||
| 82 | for (std::size_t i = 0; i < copy_amount; ++i) { | 84 | for (std::size_t i = 0; i < copy_amount && it != process_list.end(); ++i, ++it) { |
| 83 | memory.Write64(out_process_ids, process_list[i]->GetProcessId()); | 85 | memory.Write64(out_process_ids, (*it)->GetProcessId()); |
| 84 | out_process_ids += sizeof(u64); | 86 | out_process_ids += sizeof(u64); |
| 85 | } | 87 | } |
| 86 | 88 | ||