summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp3
-rw-r--r--src/core/hle/kernel/k_server_session.cpp5
-rw-r--r--src/core/hle/kernel/kernel.cpp78
-rw-r--r--src/core/hle/kernel/kernel.h9
4 files changed, 82 insertions, 13 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
59void SessionRequestHandler::ClientConnected(KServerSession* session) { 59void 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
63void SessionRequestHandler::ClientDisconnected(KServerSession* session) { 66void SessionRequestHandler::ClientDisconnected(KServerSession* session) {
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
29KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} 29KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {}
30 30
31KServerSession::~KServerSession() {} 31KServerSession::~KServerSession() {
32 // Ensure that the global list tracking server sessions does not hold on to a reference.
33 kernel.UnregisterServerSession(this);
34}
32 35
33void KServerSession::Initialize(KSession* parent_session_, std::string&& name_, 36void 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 2d5525839..92fbc5532 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -91,15 +91,39 @@ struct KernelCore::Impl {
91 } 91 }
92 92
93 void Shutdown() { 93 void Shutdown() {
94 // Shutdown all processes.
94 if (current_process) { 95 if (current_process) {
95 current_process->Finalize(); 96 current_process->Finalize();
96 current_process->Close(); 97 current_process->Close();
97 current_process = nullptr; 98 current_process = nullptr;
98 } 99 }
99
100 process_list.clear(); 100 process_list.clear();
101 101
102 // 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.
103 service_threads.clear(); 127 service_threads.clear();
104 128
105 next_object_id = 0; 129 next_object_id = 0;
@@ -147,10 +171,13 @@ struct KernelCore::Impl {
147 next_host_thread_id = Core::Hardware::NUM_CPU_CORES; 171 next_host_thread_id = Core::Hardware::NUM_CPU_CORES;
148 172
149 // Track kernel objects that were not freed on shutdown 173 // Track kernel objects that were not freed on shutdown
150 if (registered_objects.size()) { 174 {
151 LOG_WARNING(Kernel, "{} kernel objects were dangling on shutdown!", 175 std::lock_guard lk(registered_objects_lock);
152 registered_objects.size()); 176 if (registered_objects.size()) {
153 registered_objects.clear(); 177 LOG_WARNING(Kernel, "{} kernel objects were dangling on shutdown!",
178 registered_objects.size());
179 registered_objects.clear();
180 }
154 } 181 }
155 } 182 }
156 183
@@ -640,6 +667,21 @@ struct KernelCore::Impl {
640 user_slab_heap_size); 667 user_slab_heap_size);
641 } 668 }
642 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
643 std::atomic<u32> next_object_id{0}; 685 std::atomic<u32> next_object_id{0};
644 std::atomic<u64> next_kernel_process_id{KProcess::InitialKIPIDMin}; 686 std::atomic<u64> next_kernel_process_id{KProcess::InitialKIPIDMin};
645 std::atomic<u64> next_user_process_id{KProcess::ProcessIDMin}; 687 std::atomic<u64> next_user_process_id{KProcess::ProcessIDMin};
@@ -666,7 +708,12 @@ struct KernelCore::Impl {
666 /// the ConnectToPort SVC. 708 /// the ConnectToPort SVC.
667 std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory; 709 std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory;
668 NamedPortTable named_ports; 710 NamedPortTable named_ports;
711 std::unordered_set<KServerPort*> server_ports;
712 std::unordered_set<KServerSession*> server_sessions;
669 std::unordered_set<KAutoObject*> registered_objects; 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;
670 717
671 std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; 718 std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
672 std::vector<Kernel::PhysicalCore> cores; 719 std::vector<Kernel::PhysicalCore> cores;
@@ -855,19 +902,26 @@ void KernelCore::RegisterNamedService(std::string name, ServiceInterfaceFactory&
855} 902}
856 903
857KClientPort* KernelCore::CreateNamedServicePort(std::string name) { 904KClientPort* KernelCore::CreateNamedServicePort(std::string name) {
858 auto search = impl->service_interface_factory.find(name); 905 return impl->CreateNamedServicePort(std::move(name));
859 if (search == impl->service_interface_factory.end()) { 906}
860 UNIMPLEMENTED(); 907
861 return {}; 908void KernelCore::RegisterServerSession(KServerSession* server_session) {
862 } 909 std::lock_guard lk(impl->server_sessions_lock);
863 return &search->second(impl->system.ServiceManager(), impl->system); 910 impl->server_sessions.insert(server_session);
911}
912
913void KernelCore::UnregisterServerSession(KServerSession* server_session) {
914 std::lock_guard lk(impl->server_sessions_lock);
915 impl->server_sessions.erase(server_session);
864} 916}
865 917
866void KernelCore::RegisterKernelObject(KAutoObject* object) { 918void KernelCore::RegisterKernelObject(KAutoObject* object) {
919 std::lock_guard lk(impl->registered_objects_lock);
867 impl->registered_objects.insert(object); 920 impl->registered_objects.insert(object);
868} 921}
869 922
870void KernelCore::UnregisterKernelObject(KAutoObject* object) { 923void KernelCore::UnregisterKernelObject(KAutoObject* object) {
924 std::lock_guard lk(impl->registered_objects_lock);
871 impl->registered_objects.erase(object); 925 impl->registered_objects.erase(object);
872} 926}
873 927
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index b669ca74e..3a6db0b1c 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -45,6 +45,7 @@ class KPort;
45class KProcess; 45class KProcess;
46class KResourceLimit; 46class KResourceLimit;
47class KScheduler; 47class KScheduler;
48class KServerSession;
48class KSession; 49class KSession;
49class KSharedMemory; 50class KSharedMemory;
50class KThread; 51class KThread;
@@ -185,6 +186,14 @@ 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
188 /// Registers all kernel objects with the global emulation state, this is purely for tracking 197 /// Registers all kernel objects with the global emulation state, this is purely for tracking
189 /// leaks after emulation has been shutdown. 198 /// leaks after emulation has been shutdown.
190 void RegisterKernelObject(KAutoObject* object); 199 void RegisterKernelObject(KAutoObject* object);