Merge pull request #9182 from liamwhite/services-are-processes
kernel: assign KProcess to service threads
This commit is contained in:
commit
770f23db34
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue