summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/kernel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r--src/core/hle/kernel/kernel.cpp207
1 files changed, 103 insertions, 104 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 2ff253183..ce94d3605 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -34,14 +34,15 @@
34#include "core/hle/kernel/k_process.h" 34#include "core/hle/kernel/k_process.h"
35#include "core/hle/kernel/k_resource_limit.h" 35#include "core/hle/kernel/k_resource_limit.h"
36#include "core/hle/kernel/k_scheduler.h" 36#include "core/hle/kernel/k_scheduler.h"
37#include "core/hle/kernel/k_scoped_resource_reservation.h"
37#include "core/hle/kernel/k_shared_memory.h" 38#include "core/hle/kernel/k_shared_memory.h"
38#include "core/hle/kernel/k_system_resource.h" 39#include "core/hle/kernel/k_system_resource.h"
39#include "core/hle/kernel/k_thread.h" 40#include "core/hle/kernel/k_thread.h"
40#include "core/hle/kernel/k_worker_task_manager.h" 41#include "core/hle/kernel/k_worker_task_manager.h"
41#include "core/hle/kernel/kernel.h" 42#include "core/hle/kernel/kernel.h"
42#include "core/hle/kernel/physical_core.h" 43#include "core/hle/kernel/physical_core.h"
43#include "core/hle/kernel/service_thread.h"
44#include "core/hle/result.h" 44#include "core/hle/result.h"
45#include "core/hle/service/server_manager.h"
45#include "core/hle/service/sm/sm.h" 46#include "core/hle/service/sm/sm.h"
46#include "core/memory.h" 47#include "core/memory.h"
47 48
@@ -55,9 +56,7 @@ struct KernelCore::Impl {
55 static constexpr size_t BlockInfoSlabHeapSize = 4000; 56 static constexpr size_t BlockInfoSlabHeapSize = 4000;
56 static constexpr size_t ReservedDynamicPageCount = 64; 57 static constexpr size_t ReservedDynamicPageCount = 64;
57 58
58 explicit Impl(Core::System& system_, KernelCore& kernel_) 59 explicit Impl(Core::System& system_, KernelCore& kernel_) : system{system_} {}
59 : service_threads_manager{1, "ServiceThreadsManager"},
60 service_thread_barrier{2}, system{system_} {}
61 60
62 void SetMulticore(bool is_multi) { 61 void SetMulticore(bool is_multi) {
63 is_multicore = is_multi; 62 is_multicore = is_multi;
@@ -98,8 +97,6 @@ struct KernelCore::Impl {
98 97
99 InitializeHackSharedMemory(); 98 InitializeHackSharedMemory();
100 RegisterHostThread(nullptr); 99 RegisterHostThread(nullptr);
101
102 default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread");
103 } 100 }
104 101
105 void InitializeCores() { 102 void InitializeCores() {
@@ -140,11 +137,6 @@ struct KernelCore::Impl {
140 137
141 preemption_event = nullptr; 138 preemption_event = nullptr;
142 139
143 for (auto& iter : named_ports) {
144 iter.second->Close();
145 }
146 named_ports.clear();
147
148 exclusive_monitor.reset(); 140 exclusive_monitor.reset();
149 141
150 // Cleanup persistent kernel objects 142 // Cleanup persistent kernel objects
@@ -207,8 +199,9 @@ struct KernelCore::Impl {
207 } 199 }
208 200
209 void CloseServices() { 201 void CloseServices() {
210 // Ensures all service threads gracefully shutdown. 202 // Ensures all servers gracefully shutdown.
211 ClearServiceThreads(); 203 std::scoped_lock lk{server_lock};
204 server_managers.clear();
212 } 205 }
213 206
214 void InitializePhysicalCores() { 207 void InitializePhysicalCores() {
@@ -761,55 +754,6 @@ struct KernelCore::Impl {
761 "HidBus:SharedMemory"); 754 "HidBus:SharedMemory");
762 } 755 }
763 756
764 KClientPort* CreateNamedServicePort(std::string name) {
765 auto search = service_interface_factory.find(name);
766 if (search == service_interface_factory.end()) {
767 UNIMPLEMENTED();
768 return {};
769 }
770
771 return &search->second(system.ServiceManager(), system);
772 }
773
774 void RegisterNamedServiceHandler(std::string name, KServerPort* server_port) {
775 auto search = service_interface_handlers.find(name);
776 if (search == service_interface_handlers.end()) {
777 return;
778 }
779
780 search->second(system.ServiceManager(), server_port);
781 }
782
783 Kernel::ServiceThread& CreateServiceThread(KernelCore& kernel, const std::string& name) {
784 auto* ptr = new ServiceThread(kernel, name);
785
786 service_threads_manager.QueueWork(
787 [this, ptr]() { service_threads.emplace(ptr, std::unique_ptr<ServiceThread>(ptr)); });
788
789 return *ptr;
790 }
791
792 void ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
793 auto* ptr = &service_thread;
794
795 if (ptr == default_service_thread) {
796 // Nothing to do here, the service is using default_service_thread, which will be
797 // released on shutdown.
798 return;
799 }
800
801 service_threads_manager.QueueWork([this, ptr]() { service_threads.erase(ptr); });
802 }
803
804 void ClearServiceThreads() {
805 service_threads_manager.QueueWork([this] {
806 service_threads.clear();
807 default_service_thread = nullptr;
808 service_thread_barrier.Sync();
809 });
810 service_thread_barrier.Sync();
811 }
812
813 std::mutex registered_objects_lock; 757 std::mutex registered_objects_lock;
814 std::mutex registered_in_use_objects_lock; 758 std::mutex registered_in_use_objects_lock;
815 759
@@ -839,14 +783,12 @@ struct KernelCore::Impl {
839 783
840 std::unique_ptr<KObjectNameGlobalData> object_name_global_data; 784 std::unique_ptr<KObjectNameGlobalData> object_name_global_data;
841 785
842 /// Map of named ports managed by the kernel, which can be retrieved using
843 /// the ConnectToPort SVC.
844 std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory;
845 std::unordered_map<std::string, ServiceInterfaceHandlerFn> service_interface_handlers;
846 NamedPortTable named_ports;
847 std::unordered_set<KAutoObject*> registered_objects; 786 std::unordered_set<KAutoObject*> registered_objects;
848 std::unordered_set<KAutoObject*> registered_in_use_objects; 787 std::unordered_set<KAutoObject*> registered_in_use_objects;
849 788
789 std::mutex server_lock;
790 std::vector<std::unique_ptr<Service::ServerManager>> server_managers;
791
850 std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; 792 std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
851 std::array<std::unique_ptr<Kernel::PhysicalCore>, Core::Hardware::NUM_CPU_CORES> cores; 793 std::array<std::unique_ptr<Kernel::PhysicalCore>, Core::Hardware::NUM_CPU_CORES> cores;
852 794
@@ -881,12 +823,6 @@ struct KernelCore::Impl {
881 // Memory layout 823 // Memory layout
882 std::unique_ptr<KMemoryLayout> memory_layout; 824 std::unique_ptr<KMemoryLayout> memory_layout;
883 825
884 // Threads used for services
885 std::unordered_map<ServiceThread*, std::unique_ptr<ServiceThread>> service_threads;
886 ServiceThread* default_service_thread{};
887 Common::ThreadWorker service_threads_manager;
888 Common::Barrier service_thread_barrier;
889
890 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads{}; 826 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads{};
891 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; 827 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
892 828
@@ -1050,23 +986,6 @@ void KernelCore::PrepareReschedule(std::size_t id) {
1050 // TODO: Reimplement, this 986 // TODO: Reimplement, this
1051} 987}
1052 988
1053void KernelCore::RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory) {
1054 impl->service_interface_factory.emplace(std::move(name), factory);
1055}
1056
1057void KernelCore::RegisterInterfaceForNamedService(std::string name,
1058 ServiceInterfaceHandlerFn&& handler) {
1059 impl->service_interface_handlers.emplace(std::move(name), handler);
1060}
1061
1062KClientPort* KernelCore::CreateNamedServicePort(std::string name) {
1063 return impl->CreateNamedServicePort(std::move(name));
1064}
1065
1066void KernelCore::RegisterNamedServiceHandler(std::string name, KServerPort* server_port) {
1067 impl->RegisterNamedServiceHandler(std::move(name), server_port);
1068}
1069
1070void KernelCore::RegisterKernelObject(KAutoObject* object) { 989void KernelCore::RegisterKernelObject(KAutoObject* object) {
1071 std::scoped_lock lk{impl->registered_objects_lock}; 990 std::scoped_lock lk{impl->registered_objects_lock};
1072 impl->registered_objects.insert(object); 991 impl->registered_objects.insert(object);
@@ -1087,8 +1006,19 @@ void KernelCore::UnregisterInUseObject(KAutoObject* object) {
1087 impl->registered_in_use_objects.erase(object); 1006 impl->registered_in_use_objects.erase(object);
1088} 1007}
1089 1008
1090bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { 1009void KernelCore::RunServer(std::unique_ptr<Service::ServerManager>&& server_manager) {
1091 return port != impl->named_ports.cend(); 1010 auto* manager = server_manager.get();
1011
1012 {
1013 std::scoped_lock lk{impl->server_lock};
1014 if (impl->is_shutting_down) {
1015 return;
1016 }
1017
1018 impl->server_managers.emplace_back(std::move(server_manager));
1019 }
1020
1021 manager->LoopProcess();
1092} 1022}
1093 1023
1094u32 KernelCore::CreateNewObjectID() { 1024u32 KernelCore::CreateNewObjectID() {
@@ -1127,6 +1057,87 @@ void KernelCore::RegisterHostThread(KThread* existing_thread) {
1127 } 1057 }
1128} 1058}
1129 1059
1060static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process,
1061 std::string&& thread_name, std::function<void()>&& func) {
1062 // Reserve a new thread from the process resource limit.
1063 KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax);
1064 ASSERT(thread_reservation.Succeeded());
1065
1066 // Initialize the thread.
1067 KThread* thread = KThread::Create(kernel);
1068 ASSERT(R_SUCCEEDED(KThread::InitializeDummyThread(thread, process)));
1069
1070 // Commit the thread reservation.
1071 thread_reservation.Commit();
1072
1073 return std::jthread(
1074 [&kernel, thread, thread_name{std::move(thread_name)}, func{std::move(func)}] {
1075 // Set the thread name.
1076 Common::SetCurrentThreadName(thread_name.c_str());
1077
1078 // Register the thread.
1079 kernel.RegisterHostThread(thread);
1080
1081 // Run the callback.
1082 func();
1083
1084 // Close the thread.
1085 // This will free the process if it is the last reference.
1086 thread->Close();
1087 });
1088}
1089
1090std::jthread KernelCore::RunOnHostCoreProcess(std::string&& process_name,
1091 std::function<void()> func) {
1092 // Make a new process.
1093 KProcess* process = KProcess::Create(*this);
1094 ASSERT(R_SUCCEEDED(KProcess::Initialize(process, System(), "", KProcess::ProcessType::Userland,
1095 GetSystemResourceLimit())));
1096
1097 // Ensure that we don't hold onto any extra references.
1098 SCOPE_EXIT({ process->Close(); });
1099
1100 // Run the host thread.
1101 return RunHostThreadFunc(*this, process, std::move(process_name), std::move(func));
1102}
1103
1104std::jthread KernelCore::RunOnHostCoreThread(std::string&& thread_name,
1105 std::function<void()> func) {
1106 // Get the current process.
1107 KProcess* process = GetCurrentProcessPointer(*this);
1108
1109 // Run the host thread.
1110 return RunHostThreadFunc(*this, process, std::move(thread_name), std::move(func));
1111}
1112
1113void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function<void()> func) {
1114 constexpr s32 ServiceThreadPriority = 16;
1115 constexpr s32 ServiceThreadCore = 3;
1116
1117 // Make a new process.
1118 KProcess* process = KProcess::Create(*this);
1119 ASSERT(R_SUCCEEDED(KProcess::Initialize(process, System(), "", KProcess::ProcessType::Userland,
1120 GetSystemResourceLimit())));
1121
1122 // Ensure that we don't hold onto any extra references.
1123 SCOPE_EXIT({ process->Close(); });
1124
1125 // Reserve a new thread from the process resource limit.
1126 KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax);
1127 ASSERT(thread_reservation.Succeeded());
1128
1129 // Initialize the thread.
1130 KThread* thread = KThread::Create(*this);
1131 ASSERT(R_SUCCEEDED(KThread::InitializeServiceThread(
1132 System(), thread, std::move(func), ServiceThreadPriority, ServiceThreadCore, process)));
1133
1134 // Commit the thread reservation.
1135 thread_reservation.Commit();
1136
1137 // Begin running the thread.
1138 ASSERT(R_SUCCEEDED(thread->Run()));
1139}
1140
1130u32 KernelCore::GetCurrentHostThreadID() const { 1141u32 KernelCore::GetCurrentHostThreadID() const {
1131 return impl->GetCurrentHostThreadID(); 1142 return impl->GetCurrentHostThreadID();
1132} 1143}
@@ -1271,18 +1282,6 @@ void KernelCore::ExitSVCProfile() {
1271 MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]); 1282 MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]);
1272} 1283}
1273 1284
1274Kernel::ServiceThread& KernelCore::CreateServiceThread(const std::string& name) {
1275 return impl->CreateServiceThread(*this, name);
1276}
1277
1278Kernel::ServiceThread& KernelCore::GetDefaultServiceThread() const {
1279 return *impl->default_service_thread;
1280}
1281
1282void KernelCore::ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
1283 impl->ReleaseServiceThread(service_thread);
1284}
1285
1286Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() { 1285Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() {
1287 return impl->slab_resource_counts; 1286 return impl->slab_resource_counts;
1288} 1287}