diff options
| author | 2021-07-25 15:31:33 -0400 | |
|---|---|---|
| committer | 2021-07-25 15:31:33 -0400 | |
| commit | 09d6cc99435322c5f480eaa2b0967e33f4966ba6 (patch) | |
| tree | 72cdf06f6b7d77fdf5826104fea691f3ea450f54 /src/core/hle/kernel | |
| parent | configuration: Use combobox apply template where possible (diff) | |
| parent | Merge pull request #6575 from FernandoS27/new_settings (diff) | |
| download | yuzu-09d6cc99435322c5f480eaa2b0967e33f4966ba6.tar.gz yuzu-09d6cc99435322c5f480eaa2b0967e33f4966ba6.tar.xz yuzu-09d6cc99435322c5f480eaa2b0967e33f4966ba6.zip | |
Merge branch 'master' into fullscreen-enum
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_auto_object.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_auto_object.h | 12 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_server_session.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 97 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 17 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 6 |
8 files changed, 136 insertions, 21 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 28ed6265a..ca68fc325 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -58,6 +58,9 @@ bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& co | |||
| 58 | 58 | ||
| 59 | void SessionRequestHandler::ClientConnected(KServerSession* session) { | 59 | void SessionRequestHandler::ClientConnected(KServerSession* session) { |
| 60 | session->ClientConnected(shared_from_this()); | 60 | session->ClientConnected(shared_from_this()); |
| 61 | |||
| 62 | // Ensure our server session is tracked globally. | ||
| 63 | kernel.RegisterServerSession(session); | ||
| 61 | } | 64 | } |
| 62 | 65 | ||
| 63 | void SessionRequestHandler::ClientDisconnected(KServerSession* session) { | 66 | void SessionRequestHandler::ClientDisconnected(KServerSession* session) { |
diff --git a/src/core/hle/kernel/k_auto_object.cpp b/src/core/hle/kernel/k_auto_object.cpp index dbe237f09..c99a9ebb7 100644 --- a/src/core/hle/kernel/k_auto_object.cpp +++ b/src/core/hle/kernel/k_auto_object.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/hle/kernel/k_auto_object.h" | 5 | #include "core/hle/kernel/k_auto_object.h" |
| 6 | #include "core/hle/kernel/kernel.h" | ||
| 6 | 7 | ||
| 7 | namespace Kernel { | 8 | namespace Kernel { |
| 8 | 9 | ||
| @@ -11,4 +12,12 @@ KAutoObject* KAutoObject::Create(KAutoObject* obj) { | |||
| 11 | return obj; | 12 | return obj; |
| 12 | } | 13 | } |
| 13 | 14 | ||
| 15 | void KAutoObject::RegisterWithKernel() { | ||
| 16 | kernel.RegisterKernelObject(this); | ||
| 17 | } | ||
| 18 | |||
| 19 | void KAutoObject::UnregisterWithKernel() { | ||
| 20 | kernel.UnregisterKernelObject(this); | ||
| 21 | } | ||
| 22 | |||
| 14 | } // namespace Kernel | 23 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h index 88a052f65..e4fcdbc67 100644 --- a/src/core/hle/kernel/k_auto_object.h +++ b/src/core/hle/kernel/k_auto_object.h | |||
| @@ -85,8 +85,12 @@ private: | |||
| 85 | KERNEL_AUTOOBJECT_TRAITS(KAutoObject, KAutoObject); | 85 | KERNEL_AUTOOBJECT_TRAITS(KAutoObject, KAutoObject); |
| 86 | 86 | ||
| 87 | public: | 87 | public: |
| 88 | explicit KAutoObject(KernelCore& kernel_) : kernel(kernel_) {} | 88 | explicit KAutoObject(KernelCore& kernel_) : kernel(kernel_) { |
| 89 | virtual ~KAutoObject() = default; | 89 | RegisterWithKernel(); |
| 90 | } | ||
| 91 | virtual ~KAutoObject() { | ||
| 92 | UnregisterWithKernel(); | ||
| 93 | } | ||
| 90 | 94 | ||
| 91 | static KAutoObject* Create(KAutoObject* ptr); | 95 | static KAutoObject* Create(KAutoObject* ptr); |
| 92 | 96 | ||
| @@ -166,6 +170,10 @@ public: | |||
| 166 | } | 170 | } |
| 167 | } | 171 | } |
| 168 | 172 | ||
| 173 | private: | ||
| 174 | void RegisterWithKernel(); | ||
| 175 | void UnregisterWithKernel(); | ||
| 176 | |||
| 169 | protected: | 177 | protected: |
| 170 | KernelCore& kernel; | 178 | KernelCore& kernel; |
| 171 | std::string name; | 179 | std::string name; |
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index d1bd98051..8ead1a769 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "common/alignment.h" | 10 | #include "common/alignment.h" |
| 11 | #include "common/assert.h" | 11 | #include "common/assert.h" |
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "common/scope_exit.h" | ||
| 13 | #include "common/settings.h" | 14 | #include "common/settings.h" |
| 14 | #include "core/core.h" | 15 | #include "core/core.h" |
| 15 | #include "core/device_memory.h" | 16 | #include "core/device_memory.h" |
| @@ -43,6 +44,8 @@ void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority | |||
| 43 | ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::Threads, 1)); | 44 | ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::Threads, 1)); |
| 44 | 45 | ||
| 45 | KThread* thread = KThread::Create(system.Kernel()); | 46 | KThread* thread = KThread::Create(system.Kernel()); |
| 47 | SCOPE_EXIT({ thread->Close(); }); | ||
| 48 | |||
| 46 | ASSERT(KThread::InitializeUserThread(system, thread, entry_point, 0, stack_top, priority, | 49 | ASSERT(KThread::InitializeUserThread(system, thread, entry_point, 0, stack_top, priority, |
| 47 | owner_process.GetIdealCoreId(), &owner_process) | 50 | owner_process.GetIdealCoreId(), &owner_process) |
| 48 | .IsSuccess()); | 51 | .IsSuccess()); |
| @@ -162,7 +165,7 @@ void KProcess::DecrementThreadCount() { | |||
| 162 | ASSERT(num_threads > 0); | 165 | ASSERT(num_threads > 0); |
| 163 | 166 | ||
| 164 | if (const auto count = --num_threads; count == 0) { | 167 | if (const auto count = --num_threads; count == 0) { |
| 165 | UNIMPLEMENTED_MSG("Process termination is not implemented!"); | 168 | LOG_WARNING(Kernel, "Process termination is not fully implemented."); |
| 166 | } | 169 | } |
| 167 | } | 170 | } |
| 168 | 171 | ||
| @@ -406,6 +409,9 @@ void KProcess::Finalize() { | |||
| 406 | resource_limit->Close(); | 409 | resource_limit->Close(); |
| 407 | } | 410 | } |
| 408 | 411 | ||
| 412 | // Finalize the handle table and close any open handles. | ||
| 413 | handle_table.Finalize(); | ||
| 414 | |||
| 409 | // Perform inherited finalization. | 415 | // Perform inherited finalization. |
| 410 | KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize(); | 416 | KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize(); |
| 411 | } | 417 | } |
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index 5c3c13ce6..b9f24475c 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp | |||
| @@ -28,7 +28,10 @@ namespace Kernel { | |||
| 28 | 28 | ||
| 29 | KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} | 29 | KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} |
| 30 | 30 | ||
| 31 | KServerSession::~KServerSession() {} | 31 | KServerSession::~KServerSession() { |
| 32 | // Ensure that the global list tracking server sessions does not hold on to a reference. | ||
| 33 | kernel.UnregisterServerSession(this); | ||
| 34 | } | ||
| 32 | 35 | ||
| 33 | void KServerSession::Initialize(KSession* parent_session_, std::string&& name_, | 36 | void KServerSession::Initialize(KSession* parent_session_, std::string&& name_, |
| 34 | std::shared_ptr<SessionRequestManager> manager_) { | 37 | std::shared_ptr<SessionRequestManager> manager_) { |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 64bd0c494..92fbc5532 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -61,6 +61,7 @@ struct KernelCore::Impl { | |||
| 61 | void Initialize(KernelCore& kernel) { | 61 | void Initialize(KernelCore& kernel) { |
| 62 | global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); | 62 | global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); |
| 63 | global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel); | 63 | global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel); |
| 64 | global_handle_table->Initialize(KHandleTable::MaxTableSize); | ||
| 64 | 65 | ||
| 65 | is_phantom_mode_for_singlecore = false; | 66 | is_phantom_mode_for_singlecore = false; |
| 66 | 67 | ||
| @@ -90,9 +91,39 @@ struct KernelCore::Impl { | |||
| 90 | } | 91 | } |
| 91 | 92 | ||
| 92 | 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 | } | ||
| 93 | process_list.clear(); | 100 | process_list.clear(); |
| 94 | 101 | ||
| 95 | // Ensures all service threads gracefully shutdown | 102 | // Close all open server ports. |
| 103 | std::unordered_set<KServerPort*> server_ports_; | ||
| 104 | { | ||
| 105 | std::lock_guard lk(server_ports_lock); | ||
| 106 | server_ports_ = server_ports; | ||
| 107 | server_ports.clear(); | ||
| 108 | } | ||
| 109 | for (auto* server_port : server_ports_) { | ||
| 110 | server_port->Close(); | ||
| 111 | } | ||
| 112 | // Close all open server sessions. | ||
| 113 | std::unordered_set<KServerSession*> server_sessions_; | ||
| 114 | { | ||
| 115 | std::lock_guard lk(server_sessions_lock); | ||
| 116 | server_sessions_ = server_sessions; | ||
| 117 | server_sessions.clear(); | ||
| 118 | } | ||
| 119 | for (auto* server_session : server_sessions_) { | ||
| 120 | server_session->Close(); | ||
| 121 | } | ||
| 122 | |||
| 123 | // Ensure that the object list container is finalized and properly shutdown. | ||
| 124 | object_list_container.Finalize(); | ||
| 125 | |||
| 126 | // Ensures all service threads gracefully shutdown. | ||
| 96 | service_threads.clear(); | 127 | service_threads.clear(); |
| 97 | 128 | ||
| 98 | next_object_id = 0; | 129 | next_object_id = 0; |
| @@ -111,11 +142,7 @@ struct KernelCore::Impl { | |||
| 111 | 142 | ||
| 112 | cores.clear(); | 143 | cores.clear(); |
| 113 | 144 | ||
| 114 | if (current_process) { | 145 | global_handle_table->Finalize(); |
| 115 | current_process->Close(); | ||
| 116 | current_process = nullptr; | ||
| 117 | } | ||
| 118 | |||
| 119 | global_handle_table.reset(); | 146 | global_handle_table.reset(); |
| 120 | 147 | ||
| 121 | preemption_event = nullptr; | 148 | preemption_event = nullptr; |
| @@ -142,6 +169,16 @@ struct KernelCore::Impl { | |||
| 142 | 169 | ||
| 143 | // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others | 170 | // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others |
| 144 | next_host_thread_id = Core::Hardware::NUM_CPU_CORES; | 171 | next_host_thread_id = Core::Hardware::NUM_CPU_CORES; |
| 172 | |||
| 173 | // Track kernel objects that were not freed on shutdown | ||
| 174 | { | ||
| 175 | std::lock_guard lk(registered_objects_lock); | ||
| 176 | if (registered_objects.size()) { | ||
| 177 | LOG_WARNING(Kernel, "{} kernel objects were dangling on shutdown!", | ||
| 178 | registered_objects.size()); | ||
| 179 | registered_objects.clear(); | ||
| 180 | } | ||
| 181 | } | ||
| 145 | } | 182 | } |
| 146 | 183 | ||
| 147 | void InitializePhysicalCores() { | 184 | void InitializePhysicalCores() { |
| @@ -630,6 +667,21 @@ struct KernelCore::Impl { | |||
| 630 | user_slab_heap_size); | 667 | user_slab_heap_size); |
| 631 | } | 668 | } |
| 632 | 669 | ||
| 670 | KClientPort* CreateNamedServicePort(std::string name) { | ||
| 671 | auto search = service_interface_factory.find(name); | ||
| 672 | if (search == service_interface_factory.end()) { | ||
| 673 | UNIMPLEMENTED(); | ||
| 674 | return {}; | ||
| 675 | } | ||
| 676 | |||
| 677 | KClientPort* port = &search->second(system.ServiceManager(), system); | ||
| 678 | { | ||
| 679 | std::lock_guard lk(server_ports_lock); | ||
| 680 | server_ports.insert(&port->GetParent()->GetServerPort()); | ||
| 681 | } | ||
| 682 | return port; | ||
| 683 | } | ||
| 684 | |||
| 633 | std::atomic<u32> next_object_id{0}; | 685 | std::atomic<u32> next_object_id{0}; |
| 634 | std::atomic<u64> next_kernel_process_id{KProcess::InitialKIPIDMin}; | 686 | std::atomic<u64> next_kernel_process_id{KProcess::InitialKIPIDMin}; |
| 635 | std::atomic<u64> next_user_process_id{KProcess::ProcessIDMin}; | 687 | std::atomic<u64> next_user_process_id{KProcess::ProcessIDMin}; |
| @@ -656,6 +708,12 @@ struct KernelCore::Impl { | |||
| 656 | /// the ConnectToPort SVC. | 708 | /// the ConnectToPort SVC. |
| 657 | std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory; | 709 | std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory; |
| 658 | NamedPortTable named_ports; | 710 | NamedPortTable named_ports; |
| 711 | std::unordered_set<KServerPort*> server_ports; | ||
| 712 | std::unordered_set<KServerSession*> server_sessions; | ||
| 713 | std::unordered_set<KAutoObject*> registered_objects; | ||
| 714 | std::mutex server_ports_lock; | ||
| 715 | std::mutex server_sessions_lock; | ||
| 716 | std::mutex registered_objects_lock; | ||
| 659 | 717 | ||
| 660 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | 718 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; |
| 661 | std::vector<Kernel::PhysicalCore> cores; | 719 | std::vector<Kernel::PhysicalCore> cores; |
| @@ -844,12 +902,27 @@ void KernelCore::RegisterNamedService(std::string name, ServiceInterfaceFactory& | |||
| 844 | } | 902 | } |
| 845 | 903 | ||
| 846 | KClientPort* KernelCore::CreateNamedServicePort(std::string name) { | 904 | KClientPort* KernelCore::CreateNamedServicePort(std::string name) { |
| 847 | auto search = impl->service_interface_factory.find(name); | 905 | return impl->CreateNamedServicePort(std::move(name)); |
| 848 | if (search == impl->service_interface_factory.end()) { | 906 | } |
| 849 | UNIMPLEMENTED(); | 907 | |
| 850 | return {}; | 908 | void KernelCore::RegisterServerSession(KServerSession* server_session) { |
| 851 | } | 909 | std::lock_guard lk(impl->server_sessions_lock); |
| 852 | return &search->second(impl->system.ServiceManager(), impl->system); | 910 | impl->server_sessions.insert(server_session); |
| 911 | } | ||
| 912 | |||
| 913 | void KernelCore::UnregisterServerSession(KServerSession* server_session) { | ||
| 914 | std::lock_guard lk(impl->server_sessions_lock); | ||
| 915 | impl->server_sessions.erase(server_session); | ||
| 916 | } | ||
| 917 | |||
| 918 | void KernelCore::RegisterKernelObject(KAutoObject* object) { | ||
| 919 | std::lock_guard lk(impl->registered_objects_lock); | ||
| 920 | impl->registered_objects.insert(object); | ||
| 921 | } | ||
| 922 | |||
| 923 | void KernelCore::UnregisterKernelObject(KAutoObject* object) { | ||
| 924 | std::lock_guard lk(impl->registered_objects_lock); | ||
| 925 | impl->registered_objects.erase(object); | ||
| 853 | } | 926 | } |
| 854 | 927 | ||
| 855 | bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { | 928 | bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 2d01e1ae0..3a6db0b1c 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -45,6 +45,7 @@ class KPort; | |||
| 45 | class KProcess; | 45 | class KProcess; |
| 46 | class KResourceLimit; | 46 | class KResourceLimit; |
| 47 | class KScheduler; | 47 | class KScheduler; |
| 48 | class KServerSession; | ||
| 48 | class KSession; | 49 | class KSession; |
| 49 | class KSharedMemory; | 50 | class KSharedMemory; |
| 50 | class KThread; | 51 | class KThread; |
| @@ -185,6 +186,22 @@ public: | |||
| 185 | /// Opens a port to a service previously registered with RegisterNamedService. | 186 | /// Opens a port to a service previously registered with RegisterNamedService. |
| 186 | KClientPort* CreateNamedServicePort(std::string name); | 187 | KClientPort* CreateNamedServicePort(std::string name); |
| 187 | 188 | ||
| 189 | /// Registers a server session with the gobal emulation state, to be freed on shutdown. This is | ||
| 190 | /// necessary because we do not emulate processes for HLE sessions. | ||
| 191 | void RegisterServerSession(KServerSession* server_session); | ||
| 192 | |||
| 193 | /// Unregisters a server session previously registered with RegisterServerSession when it was | ||
| 194 | /// destroyed during the current emulation session. | ||
| 195 | void UnregisterServerSession(KServerSession* server_session); | ||
| 196 | |||
| 197 | /// Registers all kernel objects with the global emulation state, this is purely for tracking | ||
| 198 | /// leaks after emulation has been shutdown. | ||
| 199 | void RegisterKernelObject(KAutoObject* object); | ||
| 200 | |||
| 201 | /// Unregisters a kernel object previously registered with RegisterKernelObject when it was | ||
| 202 | /// destroyed during the current emulation session. | ||
| 203 | void UnregisterKernelObject(KAutoObject* object); | ||
| 204 | |||
| 188 | /// Determines whether or not the given port is a valid named port. | 205 | /// Determines whether or not the given port is a valid named port. |
| 189 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; | 206 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; |
| 190 | 207 | ||
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 8339e11a0..2eb532472 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -298,6 +298,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out, VAddr po | |||
| 298 | // Create a session. | 298 | // Create a session. |
| 299 | KClientSession* session{}; | 299 | KClientSession* session{}; |
| 300 | R_TRY(port->CreateSession(std::addressof(session))); | 300 | R_TRY(port->CreateSession(std::addressof(session))); |
| 301 | port->Close(); | ||
| 301 | 302 | ||
| 302 | // Register the session in the table, close the extra reference. | 303 | // Register the session in the table, close the extra reference. |
| 303 | handle_table.Register(*out, session); | 304 | handle_table.Register(*out, session); |
| @@ -1439,11 +1440,6 @@ static void ExitProcess(Core::System& system) { | |||
| 1439 | LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessID()); | 1440 | LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessID()); |
| 1440 | ASSERT_MSG(current_process->GetStatus() == ProcessStatus::Running, | 1441 | ASSERT_MSG(current_process->GetStatus() == ProcessStatus::Running, |
| 1441 | "Process has already exited"); | 1442 | "Process has already exited"); |
| 1442 | |||
| 1443 | current_process->PrepareForTermination(); | ||
| 1444 | |||
| 1445 | // Kill the current thread | ||
| 1446 | system.Kernel().CurrentScheduler()->GetCurrentThread()->Exit(); | ||
| 1447 | } | 1443 | } |
| 1448 | 1444 | ||
| 1449 | static void ExitProcess32(Core::System& system) { | 1445 | static void ExitProcess32(Core::System& system) { |