diff options
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 300 |
1 files changed, 196 insertions, 104 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 2ff253183..ef7057ff7 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -34,14 +34,15 @@ #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_scheduler.h" +#include "core/hle/kernel/k_scoped_resource_reservation.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_system_resource.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_worker_task_manager.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_core.h" -#include "core/hle/kernel/service_thread.h" #include "core/hle/result.h" +#include "core/hle/service/server_manager.h" #include "core/hle/service/sm/sm.h" #include "core/memory.h" @@ -55,9 +56,7 @@ struct KernelCore::Impl { static constexpr size_t BlockInfoSlabHeapSize = 4000; static constexpr size_t ReservedDynamicPageCount = 64; - explicit Impl(Core::System& system_, KernelCore& kernel_) - : service_threads_manager{1, "ServiceThreadsManager"}, - service_thread_barrier{2}, system{system_} {} + explicit Impl(Core::System& system_, KernelCore& kernel_) : system{system_} {} void SetMulticore(bool is_multi) { is_multicore = is_multi; @@ -98,8 +97,6 @@ struct KernelCore::Impl { InitializeHackSharedMemory(); RegisterHostThread(nullptr); - - default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread"); } void InitializeCores() { @@ -140,11 +137,6 @@ struct KernelCore::Impl { preemption_event = nullptr; - for (auto& iter : named_ports) { - iter.second->Close(); - } - named_ports.clear(); - exclusive_monitor.reset(); // Cleanup persistent kernel objects @@ -207,8 +199,9 @@ struct KernelCore::Impl { } void CloseServices() { - // Ensures all service threads gracefully shutdown. - ClearServiceThreads(); + // Ensures all servers gracefully shutdown. + std::scoped_lock lk{server_lock}; + server_managers.clear(); } void InitializePhysicalCores() { @@ -761,55 +754,6 @@ struct KernelCore::Impl { "HidBus:SharedMemory"); } - KClientPort* CreateNamedServicePort(std::string name) { - auto search = service_interface_factory.find(name); - if (search == service_interface_factory.end()) { - UNIMPLEMENTED(); - return {}; - } - - return &search->second(system.ServiceManager(), system); - } - - void RegisterNamedServiceHandler(std::string name, KServerPort* server_port) { - auto search = service_interface_handlers.find(name); - if (search == service_interface_handlers.end()) { - return; - } - - search->second(system.ServiceManager(), server_port); - } - - Kernel::ServiceThread& CreateServiceThread(KernelCore& kernel, const std::string& name) { - auto* ptr = new ServiceThread(kernel, name); - - service_threads_manager.QueueWork( - [this, ptr]() { service_threads.emplace(ptr, std::unique_ptr<ServiceThread>(ptr)); }); - - return *ptr; - } - - void ReleaseServiceThread(Kernel::ServiceThread& service_thread) { - auto* ptr = &service_thread; - - if (ptr == default_service_thread) { - // Nothing to do here, the service is using default_service_thread, which will be - // released on shutdown. - return; - } - - service_threads_manager.QueueWork([this, ptr]() { service_threads.erase(ptr); }); - } - - void ClearServiceThreads() { - service_threads_manager.QueueWork([this] { - service_threads.clear(); - default_service_thread = nullptr; - service_thread_barrier.Sync(); - }); - service_thread_barrier.Sync(); - } - std::mutex registered_objects_lock; std::mutex registered_in_use_objects_lock; @@ -839,14 +783,12 @@ struct KernelCore::Impl { std::unique_ptr<KObjectNameGlobalData> object_name_global_data; - /// Map of named ports managed by the kernel, which can be retrieved using - /// the ConnectToPort SVC. - std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory; - std::unordered_map<std::string, ServiceInterfaceHandlerFn> service_interface_handlers; - NamedPortTable named_ports; std::unordered_set<KAutoObject*> registered_objects; std::unordered_set<KAutoObject*> registered_in_use_objects; + std::mutex server_lock; + std::vector<std::unique_ptr<Service::ServerManager>> server_managers; + std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; std::array<std::unique_ptr<Kernel::PhysicalCore>, Core::Hardware::NUM_CPU_CORES> cores; @@ -881,12 +823,6 @@ struct KernelCore::Impl { // Memory layout std::unique_ptr<KMemoryLayout> memory_layout; - // Threads used for services - std::unordered_map<ServiceThread*, std::unique_ptr<ServiceThread>> service_threads; - ServiceThread* default_service_thread{}; - Common::ThreadWorker service_threads_manager; - Common::Barrier service_thread_barrier; - std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads{}; std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; @@ -1050,23 +986,6 @@ void KernelCore::PrepareReschedule(std::size_t id) { // TODO: Reimplement, this } -void KernelCore::RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory) { - impl->service_interface_factory.emplace(std::move(name), factory); -} - -void KernelCore::RegisterInterfaceForNamedService(std::string name, - ServiceInterfaceHandlerFn&& handler) { - impl->service_interface_handlers.emplace(std::move(name), handler); -} - -KClientPort* KernelCore::CreateNamedServicePort(std::string name) { - return impl->CreateNamedServicePort(std::move(name)); -} - -void KernelCore::RegisterNamedServiceHandler(std::string name, KServerPort* server_port) { - impl->RegisterNamedServiceHandler(std::move(name), server_port); -} - void KernelCore::RegisterKernelObject(KAutoObject* object) { std::scoped_lock lk{impl->registered_objects_lock}; impl->registered_objects.insert(object); @@ -1087,8 +1006,19 @@ void KernelCore::UnregisterInUseObject(KAutoObject* object) { impl->registered_in_use_objects.erase(object); } -bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { - return port != impl->named_ports.cend(); +void KernelCore::RunServer(std::unique_ptr<Service::ServerManager>&& server_manager) { + auto* manager = server_manager.get(); + + { + std::scoped_lock lk{impl->server_lock}; + if (impl->is_shutting_down) { + return; + } + + impl->server_managers.emplace_back(std::move(server_manager)); + } + + manager->LoopProcess(); } u32 KernelCore::CreateNewObjectID() { @@ -1127,6 +1057,87 @@ void KernelCore::RegisterHostThread(KThread* existing_thread) { } } +static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process, + std::string&& thread_name, std::function<void()>&& func) { + // Reserve a new thread from the process resource limit. + KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax); + ASSERT(thread_reservation.Succeeded()); + + // Initialize the thread. + KThread* thread = KThread::Create(kernel); + ASSERT(R_SUCCEEDED(KThread::InitializeDummyThread(thread, process))); + + // Commit the thread reservation. + thread_reservation.Commit(); + + return std::jthread( + [&kernel, thread, thread_name{std::move(thread_name)}, func{std::move(func)}] { + // Set the thread name. + Common::SetCurrentThreadName(thread_name.c_str()); + + // Register the thread. + kernel.RegisterHostThread(thread); + + // Run the callback. + func(); + + // Close the thread. + // This will free the process if it is the last reference. + thread->Close(); + }); +} + +std::jthread KernelCore::RunOnHostCoreProcess(std::string&& process_name, + std::function<void()> func) { + // Make a new process. + KProcess* process = KProcess::Create(*this); + ASSERT(R_SUCCEEDED(KProcess::Initialize(process, System(), "", KProcess::ProcessType::Userland, + GetSystemResourceLimit()))); + + // Ensure that we don't hold onto any extra references. + SCOPE_EXIT({ process->Close(); }); + + // Run the host thread. + return RunHostThreadFunc(*this, process, std::move(process_name), std::move(func)); +} + +std::jthread KernelCore::RunOnHostCoreThread(std::string&& thread_name, + std::function<void()> func) { + // Get the current process. + KProcess* process = GetCurrentProcessPointer(*this); + + // Run the host thread. + return RunHostThreadFunc(*this, process, std::move(thread_name), std::move(func)); +} + +void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function<void()> func) { + constexpr s32 ServiceThreadPriority = 16; + constexpr s32 ServiceThreadCore = 3; + + // Make a new process. + KProcess* process = KProcess::Create(*this); + ASSERT(R_SUCCEEDED(KProcess::Initialize(process, System(), "", KProcess::ProcessType::Userland, + GetSystemResourceLimit()))); + + // Ensure that we don't hold onto any extra references. + SCOPE_EXIT({ process->Close(); }); + + // Reserve a new thread from the process resource limit. + KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax); + ASSERT(thread_reservation.Succeeded()); + + // Initialize the thread. + KThread* thread = KThread::Create(*this); + ASSERT(R_SUCCEEDED(KThread::InitializeServiceThread( + System(), thread, std::move(func), ServiceThreadPriority, ServiceThreadCore, process))); + + // Commit the thread reservation. + thread_reservation.Commit(); + + // Begin running the thread. + ASSERT(R_SUCCEEDED(thread->Run())); +} + u32 KernelCore::GetCurrentHostThreadID() const { return impl->GetCurrentHostThreadID(); } @@ -1271,18 +1282,6 @@ void KernelCore::ExitSVCProfile() { MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]); } -Kernel::ServiceThread& KernelCore::CreateServiceThread(const std::string& name) { - return impl->CreateServiceThread(*this, name); -} - -Kernel::ServiceThread& KernelCore::GetDefaultServiceThread() const { - return *impl->default_service_thread; -} - -void KernelCore::ReleaseServiceThread(Kernel::ServiceThread& service_thread) { - impl->ReleaseServiceThread(service_thread); -} - Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() { return impl->slab_resource_counts; } @@ -1319,4 +1318,97 @@ const Core::System& KernelCore::System() const { return impl->system; } +struct KernelCore::SlabHeapContainer { + KSlabHeap<KClientSession> client_session; + KSlabHeap<KEvent> event; + KSlabHeap<KLinkedListNode> linked_list_node; + KSlabHeap<KPort> port; + KSlabHeap<KProcess> process; + KSlabHeap<KResourceLimit> resource_limit; + KSlabHeap<KSession> session; + KSlabHeap<KSharedMemory> shared_memory; + KSlabHeap<KSharedMemoryInfo> shared_memory_info; + KSlabHeap<KThread> thread; + KSlabHeap<KTransferMemory> transfer_memory; + KSlabHeap<KCodeMemory> code_memory; + KSlabHeap<KDeviceAddressSpace> device_address_space; + KSlabHeap<KPageBuffer> page_buffer; + KSlabHeap<KThreadLocalPage> thread_local_page; + KSlabHeap<KObjectName> object_name; + KSlabHeap<KSessionRequest> session_request; + KSlabHeap<KSecureSystemResource> secure_system_resource; + KSlabHeap<KThread::LockWithPriorityInheritanceInfo> lock_info; + KSlabHeap<KEventInfo> event_info; + KSlabHeap<KDebug> debug; +}; + +template <typename T> +KSlabHeap<T>& KernelCore::SlabHeap() { + if constexpr (std::is_same_v<T, KClientSession>) { + return slab_heap_container->client_session; + } else if constexpr (std::is_same_v<T, KEvent>) { + return slab_heap_container->event; + } else if constexpr (std::is_same_v<T, KLinkedListNode>) { + return slab_heap_container->linked_list_node; + } else if constexpr (std::is_same_v<T, KPort>) { + return slab_heap_container->port; + } else if constexpr (std::is_same_v<T, KProcess>) { + return slab_heap_container->process; + } else if constexpr (std::is_same_v<T, KResourceLimit>) { + return slab_heap_container->resource_limit; + } else if constexpr (std::is_same_v<T, KSession>) { + return slab_heap_container->session; + } else if constexpr (std::is_same_v<T, KSharedMemory>) { + return slab_heap_container->shared_memory; + } else if constexpr (std::is_same_v<T, KSharedMemoryInfo>) { + return slab_heap_container->shared_memory_info; + } else if constexpr (std::is_same_v<T, KThread>) { + return slab_heap_container->thread; + } else if constexpr (std::is_same_v<T, KTransferMemory>) { + return slab_heap_container->transfer_memory; + } else if constexpr (std::is_same_v<T, KCodeMemory>) { + return slab_heap_container->code_memory; + } else if constexpr (std::is_same_v<T, KDeviceAddressSpace>) { + return slab_heap_container->device_address_space; + } else if constexpr (std::is_same_v<T, KPageBuffer>) { + return slab_heap_container->page_buffer; + } else if constexpr (std::is_same_v<T, KThreadLocalPage>) { + return slab_heap_container->thread_local_page; + } else if constexpr (std::is_same_v<T, KObjectName>) { + return slab_heap_container->object_name; + } else if constexpr (std::is_same_v<T, KSessionRequest>) { + return slab_heap_container->session_request; + } else if constexpr (std::is_same_v<T, KSecureSystemResource>) { + return slab_heap_container->secure_system_resource; + } else if constexpr (std::is_same_v<T, KThread::LockWithPriorityInheritanceInfo>) { + return slab_heap_container->lock_info; + } else if constexpr (std::is_same_v<T, KEventInfo>) { + return slab_heap_container->event_info; + } else if constexpr (std::is_same_v<T, KDebug>) { + return slab_heap_container->debug; + } +} + +template KSlabHeap<KClientSession>& KernelCore::SlabHeap(); +template KSlabHeap<KEvent>& KernelCore::SlabHeap(); +template KSlabHeap<KLinkedListNode>& KernelCore::SlabHeap(); +template KSlabHeap<KPort>& KernelCore::SlabHeap(); +template KSlabHeap<KProcess>& KernelCore::SlabHeap(); +template KSlabHeap<KResourceLimit>& KernelCore::SlabHeap(); +template KSlabHeap<KSession>& KernelCore::SlabHeap(); +template KSlabHeap<KSharedMemory>& KernelCore::SlabHeap(); +template KSlabHeap<KSharedMemoryInfo>& KernelCore::SlabHeap(); +template KSlabHeap<KThread>& KernelCore::SlabHeap(); +template KSlabHeap<KTransferMemory>& KernelCore::SlabHeap(); +template KSlabHeap<KCodeMemory>& KernelCore::SlabHeap(); +template KSlabHeap<KDeviceAddressSpace>& KernelCore::SlabHeap(); +template KSlabHeap<KPageBuffer>& KernelCore::SlabHeap(); +template KSlabHeap<KThreadLocalPage>& KernelCore::SlabHeap(); +template KSlabHeap<KObjectName>& KernelCore::SlabHeap(); +template KSlabHeap<KSessionRequest>& KernelCore::SlabHeap(); +template KSlabHeap<KSecureSystemResource>& KernelCore::SlabHeap(); +template KSlabHeap<KThread::LockWithPriorityInheritanceInfo>& KernelCore::SlabHeap(); +template KSlabHeap<KEventInfo>& KernelCore::SlabHeap(); +template KSlabHeap<KDebug>& KernelCore::SlabHeap(); + } // namespace Kernel |