Merge pull request #9182 from liamwhite/services-are-processes

kernel: assign KProcess to service threads
This commit is contained in:
bunnei 2022-11-09 15:52:23 -08:00 committed by GitHub
commit 770f23db34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 25 deletions

View File

@ -263,9 +263,9 @@ Result KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_
R_SUCCEED(); R_SUCCEED();
} }
Result KThread::InitializeDummyThread(KThread* thread) { Result KThread::InitializeDummyThread(KThread* thread, KProcess* owner) {
// Initialize the thread. // Initialize the thread.
R_TRY(thread->Initialize({}, {}, {}, DummyThreadPriority, 3, {}, ThreadType::Dummy)); R_TRY(thread->Initialize({}, {}, {}, DummyThreadPriority, 3, owner, ThreadType::Dummy));
// Initialize emulation parameters. // Initialize emulation parameters.
thread->stack_parameters.disable_count = 0; thread->stack_parameters.disable_count = 0;

View File

@ -415,7 +415,7 @@ public:
static void PostDestroy(uintptr_t arg); static void PostDestroy(uintptr_t arg);
[[nodiscard]] static Result InitializeDummyThread(KThread* thread); [[nodiscard]] static Result InitializeDummyThread(KThread* thread, KProcess* owner);
[[nodiscard]] static Result InitializeMainThread(Core::System& system, KThread* thread, [[nodiscard]] static Result InitializeMainThread(Core::System& system, KThread* thread,
s32 virt_core); s32 virt_core);

View File

@ -91,7 +91,7 @@ struct KernelCore::Impl {
pt_heap_region.GetSize()); pt_heap_region.GetSize());
} }
RegisterHostThread(); RegisterHostThread(nullptr);
default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread"); default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread");
} }
@ -373,15 +373,18 @@ struct KernelCore::Impl {
} }
// Gets the dummy KThread for the caller, allocating a new one if this is the first time // Gets the dummy KThread for the caller, allocating a new one if this is the first time
KThread* GetHostDummyThread() { KThread* GetHostDummyThread(KThread* existing_thread) {
auto initialize = [this](KThread* thread) { auto initialize = [this](KThread* thread) {
ASSERT(KThread::InitializeDummyThread(thread).IsSuccess()); ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess());
thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId())); thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId()));
return thread; return thread;
}; };
thread_local auto raw_thread = KThread(system.Kernel()); thread_local KThread raw_thread{system.Kernel()};
thread_local auto thread = initialize(&raw_thread); thread_local KThread* thread = nullptr;
if (thread == nullptr) {
thread = (existing_thread == nullptr) ? initialize(&raw_thread) : existing_thread;
}
return thread; return thread;
} }
@ -396,9 +399,9 @@ struct KernelCore::Impl {
} }
/// Registers a new host thread by allocating a host thread ID for it /// Registers a new host thread by allocating a host thread ID for it
void RegisterHostThread() { void RegisterHostThread(KThread* existing_thread) {
[[maybe_unused]] const auto this_id = GetHostThreadId(); [[maybe_unused]] const auto this_id = GetHostThreadId();
[[maybe_unused]] const auto dummy_thread = GetHostDummyThread(); [[maybe_unused]] const auto dummy_thread = GetHostDummyThread(existing_thread);
} }
[[nodiscard]] u32 GetCurrentHostThreadID() { [[nodiscard]] u32 GetCurrentHostThreadID() {
@ -429,7 +432,7 @@ struct KernelCore::Impl {
KThread* GetCurrentEmuThread() { KThread* GetCurrentEmuThread() {
const auto thread_id = GetCurrentHostThreadID(); const auto thread_id = GetCurrentHostThreadID();
if (thread_id >= Core::Hardware::NUM_CPU_CORES) { if (thread_id >= Core::Hardware::NUM_CPU_CORES) {
return GetHostDummyThread(); return GetHostDummyThread(nullptr);
} }
return current_thread; return current_thread;
@ -1120,8 +1123,12 @@ void KernelCore::RegisterCoreThread(std::size_t core_id) {
impl->RegisterCoreThread(core_id); impl->RegisterCoreThread(core_id);
} }
void KernelCore::RegisterHostThread() { void KernelCore::RegisterHostThread(KThread* existing_thread) {
impl->RegisterHostThread(); impl->RegisterHostThread(existing_thread);
if (existing_thread != nullptr) {
ASSERT(GetCurrentEmuThread() == existing_thread);
}
} }
u32 KernelCore::GetCurrentHostThreadID() const { u32 KernelCore::GetCurrentHostThreadID() const {
@ -1196,17 +1203,29 @@ void KernelCore::Suspend(bool suspended) {
const bool should_suspend{exception_exited || suspended}; const bool should_suspend{exception_exited || suspended};
const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable; const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable;
for (auto* process : GetProcessList()) { std::vector<KScopedAutoObject<KThread>> process_threads;
{
KScopedSchedulerLock sl{*this};
if (auto* process = CurrentProcess(); process != nullptr) {
process->SetActivity(activity); process->SetActivity(activity);
if (should_suspend) { if (!should_suspend) {
// Wait for execution to stop // Runnable now; no need to wait.
return;
}
for (auto* thread : process->GetThreadList()) { for (auto* thread : process->GetThreadList()) {
process_threads.emplace_back(thread);
}
}
}
// Wait for execution to stop.
for (auto& thread : process_threads) {
thread->WaitUntilSuspended(); thread->WaitUntilSuspended();
} }
} }
}
}
void KernelCore::ShutdownCores() { void KernelCore::ShutdownCores() {
KScopedSchedulerLock lk{*this}; KScopedSchedulerLock lk{*this};

View File

@ -240,7 +240,7 @@ public:
void RegisterCoreThread(std::size_t core_id); void RegisterCoreThread(std::size_t core_id);
/// Register the current thread as a non CPU core thread. /// Register the current thread as a non CPU core thread.
void RegisterHostThread(); void RegisterHostThread(KThread* existing_thread = nullptr);
/// Gets the virtual memory manager for the kernel. /// Gets the virtual memory manager for the kernel.
KMemoryManager& MemoryManager(); KMemoryManager& MemoryManager();

View File

@ -36,11 +36,12 @@ public:
private: private:
KernelCore& kernel; KernelCore& kernel;
std::jthread m_thread; std::jthread m_host_thread;
std::mutex m_session_mutex; std::mutex m_session_mutex;
std::map<KServerSession*, std::shared_ptr<SessionRequestManager>> m_sessions; std::map<KServerSession*, std::shared_ptr<SessionRequestManager>> m_sessions;
KEvent* m_wakeup_event; KEvent* m_wakeup_event;
KProcess* m_process; KProcess* m_process;
KThread* m_thread;
std::atomic<bool> m_shutdown_requested; std::atomic<bool> m_shutdown_requested;
const std::string m_service_name; const std::string m_service_name;
}; };
@ -132,7 +133,7 @@ void ServiceThread::Impl::SessionClosed(KServerSession* server_session,
void ServiceThread::Impl::LoopProcess() { void ServiceThread::Impl::LoopProcess() {
Common::SetCurrentThreadName(m_service_name.c_str()); Common::SetCurrentThreadName(m_service_name.c_str());
kernel.RegisterHostThread(); kernel.RegisterHostThread(m_thread);
while (!m_shutdown_requested.load()) { while (!m_shutdown_requested.load()) {
WaitAndProcessImpl(); WaitAndProcessImpl();
@ -160,7 +161,7 @@ ServiceThread::Impl::~Impl() {
// Shut down the processing thread. // Shut down the processing thread.
m_shutdown_requested.store(true); m_shutdown_requested.store(true);
m_wakeup_event->Signal(); m_wakeup_event->Signal();
m_thread.join(); m_host_thread.join();
// Lock mutex. // Lock mutex.
m_session_mutex.lock(); m_session_mutex.lock();
@ -177,6 +178,9 @@ ServiceThread::Impl::~Impl() {
m_wakeup_event->GetReadableEvent().Close(); m_wakeup_event->GetReadableEvent().Close();
m_wakeup_event->Close(); m_wakeup_event->Close();
// Close thread.
m_thread->Close();
// Close process. // Close process.
m_process->Close(); m_process->Close();
} }
@ -199,11 +203,19 @@ ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name)
// Commit the event reservation. // Commit the event reservation.
event_reservation.Commit(); event_reservation.Commit();
// Register the event. // Reserve a new thread from the process resource limit
KEvent::Register(kernel, m_wakeup_event); KScopedResourceReservation thread_reservation(m_process, LimitableResource::Threads);
ASSERT(thread_reservation.Succeeded());
// Initialize thread.
m_thread = KThread::Create(kernel);
ASSERT(KThread::InitializeDummyThread(m_thread, m_process).IsSuccess());
// Commit the thread reservation.
thread_reservation.Commit();
// Start thread. // Start thread.
m_thread = std::jthread([this] { LoopProcess(); }); m_host_thread = std::jthread([this] { LoopProcess(); });
} }
ServiceThread::ServiceThread(KernelCore& kernel, const std::string& name) ServiceThread::ServiceThread(KernelCore& kernel, const std::string& name)