diff options
-rwxr-xr-x | README.md | 2 | ||||
-rwxr-xr-x | src/core/core.cpp | 16 | ||||
-rwxr-xr-x | src/core/hle/kernel/k_handle_table.cpp | 1 | ||||
-rwxr-xr-x | src/core/hle/kernel/k_process.cpp | 11 | ||||
-rwxr-xr-x | src/core/hle/kernel/kernel.cpp | 36 | ||||
-rwxr-xr-x | src/core/hle/kernel/kernel.h | 8 | ||||
-rwxr-xr-x | src/core/hle/kernel/svc.cpp | 6 | ||||
-rwxr-xr-x | src/core/hle/result.h | 24 |
8 files changed, 77 insertions, 27 deletions
@@ -1,7 +1,7 @@ | |||
1 | yuzu emulator early access | 1 | yuzu emulator early access |
2 | ============= | 2 | ============= |
3 | 3 | ||
4 | This is the source code for early-access 2165. | 4 | This is the source code for early-access 2166. |
5 | 5 | ||
6 | ## Legal Notice | 6 | ## Legal Notice |
7 | 7 | ||
diff --git a/src/core/core.cpp b/src/core/core.cpp index 3c75f42ae..c3a0f9dae 100755 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
@@ -83,12 +83,6 @@ FileSys::StorageId GetStorageIdForFrontendSlot( | |||
83 | } | 83 | } |
84 | } | 84 | } |
85 | 85 | ||
86 | void KProcessDeleter(Kernel::KProcess* process) { | ||
87 | process->Destroy(); | ||
88 | } | ||
89 | |||
90 | using KProcessPtr = std::unique_ptr<Kernel::KProcess, decltype(&KProcessDeleter)>; | ||
91 | |||
92 | } // Anonymous namespace | 86 | } // Anonymous namespace |
93 | 87 | ||
94 | FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | 88 | FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, |
@@ -261,11 +255,10 @@ struct System::Impl { | |||
261 | } | 255 | } |
262 | 256 | ||
263 | telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); | 257 | telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); |
264 | main_process = KProcessPtr{Kernel::KProcess::Create(system.Kernel()), KProcessDeleter}; | 258 | auto main_process = Kernel::KProcess::Create(system.Kernel()); |
265 | ASSERT(Kernel::KProcess::Initialize(main_process.get(), system, "main", | 259 | ASSERT(Kernel::KProcess::Initialize(main_process, system, "main", |
266 | Kernel::KProcess::ProcessType::Userland) | 260 | Kernel::KProcess::ProcessType::Userland) |
267 | .IsSuccess()); | 261 | .IsSuccess()); |
268 | main_process->Open(); | ||
269 | const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); | 262 | const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); |
270 | if (load_result != Loader::ResultStatus::Success) { | 263 | if (load_result != Loader::ResultStatus::Success) { |
271 | LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); | 264 | LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); |
@@ -275,7 +268,7 @@ struct System::Impl { | |||
275 | static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result)); | 268 | static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result)); |
276 | } | 269 | } |
277 | AddGlueRegistrationForProcess(*app_loader, *main_process); | 270 | AddGlueRegistrationForProcess(*app_loader, *main_process); |
278 | kernel.MakeCurrentProcess(main_process.get()); | 271 | kernel.MakeCurrentProcess(main_process); |
279 | kernel.InitializeCores(); | 272 | kernel.InitializeCores(); |
280 | 273 | ||
281 | // Initialize cheat engine | 274 | // Initialize cheat engine |
@@ -340,8 +333,6 @@ struct System::Impl { | |||
340 | kernel.Shutdown(); | 333 | kernel.Shutdown(); |
341 | memory.Reset(); | 334 | memory.Reset(); |
342 | applet_manager.ClearAll(); | 335 | applet_manager.ClearAll(); |
343 | // TODO: The main process should be freed based on KAutoObject ref counting. | ||
344 | main_process.reset(); | ||
345 | 336 | ||
346 | LOG_DEBUG(Core, "Shutdown OK"); | 337 | LOG_DEBUG(Core, "Shutdown OK"); |
347 | } | 338 | } |
@@ -403,7 +394,6 @@ struct System::Impl { | |||
403 | std::unique_ptr<Tegra::GPU> gpu_core; | 394 | std::unique_ptr<Tegra::GPU> gpu_core; |
404 | std::unique_ptr<Hardware::InterruptManager> interrupt_manager; | 395 | std::unique_ptr<Hardware::InterruptManager> interrupt_manager; |
405 | std::unique_ptr<Core::DeviceMemory> device_memory; | 396 | std::unique_ptr<Core::DeviceMemory> device_memory; |
406 | KProcessPtr main_process{nullptr, KProcessDeleter}; | ||
407 | Core::Memory::Memory memory; | 397 | Core::Memory::Memory memory; |
408 | CpuManager cpu_manager; | 398 | CpuManager cpu_manager; |
409 | std::atomic_bool is_powered_on{}; | 399 | std::atomic_bool is_powered_on{}; |
diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp index 44d13169f..e90fc0628 100755 --- a/src/core/hle/kernel/k_handle_table.cpp +++ b/src/core/hle/kernel/k_handle_table.cpp | |||
@@ -56,6 +56,7 @@ bool KHandleTable::Remove(Handle handle) { | |||
56 | } | 56 | } |
57 | 57 | ||
58 | // Close the object. | 58 | // Close the object. |
59 | kernel.UnregisterInUseObject(obj); | ||
59 | obj->Close(); | 60 | obj->Close(); |
60 | return true; | 61 | return true; |
61 | } | 62 | } |
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 211157ccc..76fd8c285 100755 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
@@ -434,11 +434,6 @@ void KProcess::PrepareForTermination() { | |||
434 | } | 434 | } |
435 | 435 | ||
436 | void KProcess::Finalize() { | 436 | void KProcess::Finalize() { |
437 | // Release memory to the resource limit. | ||
438 | if (resource_limit != nullptr) { | ||
439 | resource_limit->Close(); | ||
440 | } | ||
441 | |||
442 | // Finalize the handle table and close any open handles. | 437 | // Finalize the handle table and close any open handles. |
443 | handle_table.Finalize(); | 438 | handle_table.Finalize(); |
444 | 439 | ||
@@ -460,6 +455,12 @@ void KProcess::Finalize() { | |||
460 | } | 455 | } |
461 | } | 456 | } |
462 | 457 | ||
458 | // Release memory to the resource limit. | ||
459 | if (resource_limit != nullptr) { | ||
460 | resource_limit->Close(); | ||
461 | resource_limit = nullptr; | ||
462 | } | ||
463 | |||
463 | // Perform inherited finalization. | 464 | // Perform inherited finalization. |
464 | KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize(); | 465 | KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize(); |
465 | } | 466 | } |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index bea945301..4a139c5e7 100755 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
@@ -91,12 +91,6 @@ struct KernelCore::Impl { | |||
91 | } | 91 | } |
92 | 92 | ||
93 | void Shutdown() { | 93 | void Shutdown() { |
94 | // Shutdown all processes. | ||
95 | if (current_process) { | ||
96 | current_process->Finalize(); | ||
97 | current_process->Close(); | ||
98 | current_process = nullptr; | ||
99 | } | ||
100 | process_list.clear(); | 94 | process_list.clear(); |
101 | 95 | ||
102 | // Close all open server ports. | 96 | // Close all open server ports. |
@@ -170,6 +164,24 @@ struct KernelCore::Impl { | |||
170 | // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others | 164 | // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others |
171 | next_host_thread_id = Core::Hardware::NUM_CPU_CORES; | 165 | next_host_thread_id = Core::Hardware::NUM_CPU_CORES; |
172 | 166 | ||
167 | // Close kernel objects that were not freed on shutdown | ||
168 | { | ||
169 | std::lock_guard lk(registered_in_use_objects_lock); | ||
170 | if (registered_in_use_objects.size()) { | ||
171 | for (auto& object : registered_in_use_objects) { | ||
172 | object->Close(); | ||
173 | } | ||
174 | registered_in_use_objects.clear(); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | // Shutdown all processes. | ||
179 | if (current_process) { | ||
180 | current_process->Finalize(); | ||
181 | current_process->Close(); | ||
182 | current_process = nullptr; | ||
183 | } | ||
184 | |||
173 | // Track kernel objects that were not freed on shutdown | 185 | // Track kernel objects that were not freed on shutdown |
174 | { | 186 | { |
175 | std::lock_guard lk(registered_objects_lock); | 187 | std::lock_guard lk(registered_objects_lock); |
@@ -714,9 +726,11 @@ struct KernelCore::Impl { | |||
714 | std::unordered_set<KServerPort*> server_ports; | 726 | std::unordered_set<KServerPort*> server_ports; |
715 | std::unordered_set<KServerSession*> server_sessions; | 727 | std::unordered_set<KServerSession*> server_sessions; |
716 | std::unordered_set<KAutoObject*> registered_objects; | 728 | std::unordered_set<KAutoObject*> registered_objects; |
729 | std::unordered_set<KAutoObject*> registered_in_use_objects; | ||
717 | std::mutex server_ports_lock; | 730 | std::mutex server_ports_lock; |
718 | std::mutex server_sessions_lock; | 731 | std::mutex server_sessions_lock; |
719 | std::mutex registered_objects_lock; | 732 | std::mutex registered_objects_lock; |
733 | std::mutex registered_in_use_objects_lock; | ||
720 | 734 | ||
721 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | 735 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; |
722 | std::vector<Kernel::PhysicalCore> cores; | 736 | std::vector<Kernel::PhysicalCore> cores; |
@@ -928,6 +942,16 @@ void KernelCore::UnregisterKernelObject(KAutoObject* object) { | |||
928 | impl->registered_objects.erase(object); | 942 | impl->registered_objects.erase(object); |
929 | } | 943 | } |
930 | 944 | ||
945 | void KernelCore::RegisterInUseObject(KAutoObject* object) { | ||
946 | std::lock_guard lk(impl->registered_in_use_objects_lock); | ||
947 | impl->registered_in_use_objects.insert(object); | ||
948 | } | ||
949 | |||
950 | void KernelCore::UnregisterInUseObject(KAutoObject* object) { | ||
951 | std::lock_guard lk(impl->registered_in_use_objects_lock); | ||
952 | impl->registered_in_use_objects.erase(object); | ||
953 | } | ||
954 | |||
931 | bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { | 955 | bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { |
932 | return port != impl->named_ports.cend(); | 956 | return port != impl->named_ports.cend(); |
933 | } | 957 | } |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index b6658b437..d2ceae950 100755 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
@@ -204,6 +204,14 @@ public: | |||
204 | /// destroyed during the current emulation session. | 204 | /// destroyed during the current emulation session. |
205 | void UnregisterKernelObject(KAutoObject* object); | 205 | void UnregisterKernelObject(KAutoObject* object); |
206 | 206 | ||
207 | /// Registers kernel objects with guest in use state, this is purely for close | ||
208 | /// after emulation has been shutdown. | ||
209 | void RegisterInUseObject(KAutoObject* object); | ||
210 | |||
211 | /// Unregisters a kernel object previously registered with RegisterInUseObject when it was | ||
212 | /// destroyed during the current emulation session. | ||
213 | void UnregisterInUseObject(KAutoObject* object); | ||
214 | |||
207 | /// Determines whether or not the given port is a valid named port. | 215 | /// Determines whether or not the given port is a valid named port. |
208 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; | 216 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; |
209 | 217 | ||
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 7f38ade1c..c43135856 100755 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
@@ -427,11 +427,15 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha | |||
427 | R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, | 427 | R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, |
428 | num_handles), | 428 | num_handles), |
429 | ResultInvalidHandle); | 429 | ResultInvalidHandle); |
430 | for (const auto& obj : objs) { | ||
431 | kernel.RegisterInUseObject(obj); | ||
432 | } | ||
430 | } | 433 | } |
431 | 434 | ||
432 | // Ensure handles are closed when we're done. | 435 | // Ensure handles are closed when we're done. |
433 | SCOPE_EXIT({ | 436 | SCOPE_EXIT({ |
434 | for (u64 i = 0; i < num_handles; ++i) { | 437 | for (u64 i = 0; i < num_handles; ++i) { |
438 | kernel.UnregisterInUseObject(objs[i]); | ||
435 | objs[i]->Close(); | 439 | objs[i]->Close(); |
436 | } | 440 | } |
437 | }); | 441 | }); |
@@ -1561,6 +1565,7 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) { | |||
1561 | 1565 | ||
1562 | // If we succeeded, persist a reference to the thread. | 1566 | // If we succeeded, persist a reference to the thread. |
1563 | thread->Open(); | 1567 | thread->Open(); |
1568 | system.Kernel().RegisterInUseObject(thread.GetPointerUnsafe()); | ||
1564 | 1569 | ||
1565 | return ResultSuccess; | 1570 | return ResultSuccess; |
1566 | } | 1571 | } |
@@ -1576,6 +1581,7 @@ static void ExitThread(Core::System& system) { | |||
1576 | auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); | 1581 | auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); |
1577 | system.GlobalSchedulerContext().RemoveThread(current_thread); | 1582 | system.GlobalSchedulerContext().RemoveThread(current_thread); |
1578 | current_thread->Exit(); | 1583 | current_thread->Exit(); |
1584 | system.Kernel().UnregisterInUseObject(current_thread); | ||
1579 | } | 1585 | } |
1580 | 1586 | ||
1581 | static void ExitThread32(Core::System& system) { | 1587 | static void ExitThread32(Core::System& system) { |
diff --git a/src/core/hle/result.h b/src/core/hle/result.h index a755008d5..00fe70998 100755 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h | |||
@@ -206,7 +206,7 @@ public: | |||
206 | return result; | 206 | return result; |
207 | } | 207 | } |
208 | 208 | ||
209 | ResultVal(const ResultVal& o) : result_code(o.result_code) { | 209 | ResultVal(const ResultVal& o) noexcept : result_code(o.result_code) { |
210 | if (!o.empty()) { | 210 | if (!o.empty()) { |
211 | new (&object) T(o.object); | 211 | new (&object) T(o.object); |
212 | } | 212 | } |
@@ -224,7 +224,7 @@ public: | |||
224 | } | 224 | } |
225 | } | 225 | } |
226 | 226 | ||
227 | ResultVal& operator=(const ResultVal& o) { | 227 | ResultVal& operator=(const ResultVal& o) noexcept { |
228 | if (this == &o) { | 228 | if (this == &o) { |
229 | return *this; | 229 | return *this; |
230 | } | 230 | } |
@@ -244,6 +244,26 @@ public: | |||
244 | return *this; | 244 | return *this; |
245 | } | 245 | } |
246 | 246 | ||
247 | ResultVal& operator=(ResultVal&& o) noexcept { | ||
248 | if (this == &o) { | ||
249 | return *this; | ||
250 | } | ||
251 | if (!empty()) { | ||
252 | if (!o.empty()) { | ||
253 | object = std::move(o.object); | ||
254 | } else { | ||
255 | object.~T(); | ||
256 | } | ||
257 | } else { | ||
258 | if (!o.empty()) { | ||
259 | new (&object) T(std::move(o.object)); | ||
260 | } | ||
261 | } | ||
262 | result_code = o.result_code; | ||
263 | |||
264 | return *this; | ||
265 | } | ||
266 | |||
247 | /** | 267 | /** |
248 | * Replaces the current result with a new constructed result value in-place. The code must not | 268 | * Replaces the current result with a new constructed result value in-place. The code must not |
249 | * be an error code. | 269 | * be an error code. |