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/k_memory_block_manager.cpp4
-rw-r--r--src/core/hle/kernel/k_memory_block_manager.h4
-rw-r--r--src/core/hle/kernel/k_page_table_base.cpp34
-rw-r--r--src/core/hle/kernel/k_page_table_base.h1
-rw-r--r--src/core/hle/kernel/k_process.cpp10
-rw-r--r--src/core/hle/kernel/kernel.cpp31
-rw-r--r--src/core/hle/kernel/kernel.h6
-rw-r--r--src/core/hle/kernel/svc/svc_process.cpp8
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
30void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager, 30void 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:
85public: 85public:
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
434Result 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
434void KPageTableBase::Finalize() { 450void 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
871void KernelCore::AppendNewProcess(KProcess* process) { 879void 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
886void 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
875void KernelCore::MakeApplicationProcess(KProcess* process) { 893void 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
887const std::vector<KProcess*>& KernelCore::GetProcessList() const { 905std::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
891Kernel::GlobalSchedulerContext& KernelCore::GlobalSchedulerContext() { 916Kernel::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