diff options
Diffstat (limited to 'src/core/hle/kernel')
22 files changed, 190 insertions, 122 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 2b5c30f7a..28ed6265a 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -30,16 +30,38 @@ namespace Kernel { -SessionRequestHandler::SessionRequestHandler() = default; +SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_) + : kernel{kernel_}, service_thread{kernel.CreateServiceThread(service_name_)} {} -SessionRequestHandler::~SessionRequestHandler() = default; +SessionRequestHandler::~SessionRequestHandler() { + kernel.ReleaseServiceThread(service_thread); +} + +SessionRequestManager::SessionRequestManager(KernelCore& kernel_) : kernel{kernel_} {} + +SessionRequestManager::~SessionRequestManager() = default; + +bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& context) const { + if (IsDomain() && context.HasDomainMessageHeader()) { + const auto& message_header = context.GetDomainMessageHeader(); + const auto object_id = message_header.object_id; + + if (object_id > DomainHandlerCount()) { + LOG_CRITICAL(IPC, "object_id {} is too big!", object_id); + return false; + } + return DomainHandler(object_id - 1) != nullptr; + } else { + return session_handler != nullptr; + } +} void SessionRequestHandler::ClientConnected(KServerSession* session) { - session->SetSessionHandler(shared_from_this()); + session->ClientConnected(shared_from_this()); } void SessionRequestHandler::ClientDisconnected(KServerSession* session) { - session->SetSessionHandler(nullptr); + session->ClientDisconnected(); } HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index b47e363cc..a61870f8b 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -46,6 +46,7 @@ class KThread; class KReadableEvent; class KSession; class KWritableEvent; +class ServiceThread; enum class ThreadWakeupReason; @@ -56,7 +57,7 @@ enum class ThreadWakeupReason; */ class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> { public: - SessionRequestHandler(); + SessionRequestHandler(KernelCore& kernel, const char* service_name_); virtual ~SessionRequestHandler(); /** @@ -83,6 +84,14 @@ public: * @param server_session ServerSession associated with the connection. */ void ClientDisconnected(KServerSession* session); + + std::weak_ptr<ServiceThread> GetServiceThread() const { + return service_thread; + } + +protected: + KernelCore& kernel; + std::weak_ptr<ServiceThread> service_thread; }; using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>; @@ -94,7 +103,8 @@ using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>; */ class SessionRequestManager final { public: - SessionRequestManager() = default; + explicit SessionRequestManager(KernelCore& kernel); + ~SessionRequestManager(); bool IsDomain() const { return is_domain; @@ -142,10 +152,19 @@ public: session_handler = std::move(handler); } + std::weak_ptr<ServiceThread> GetServiceThread() const { + return session_handler->GetServiceThread(); + } + + bool HasSessionRequestHandler(const HLERequestContext& context) const; + private: bool is_domain{}; SessionRequestHandlerPtr session_handler; std::vector<SessionRequestHandlerPtr> domain_handlers; + +private: + KernelCore& kernel; }; /** diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h index bc18582be..88a052f65 100644 --- a/src/core/hle/kernel/k_auto_object.h +++ b/src/core/hle/kernel/k_auto_object.h @@ -7,10 +7,11 @@ #include <atomic> #include <string> +#include <boost/intrusive/rbtree.hpp> + #include "common/assert.h" #include "common/common_funcs.h" #include "common/common_types.h" -#include "common/intrusive_red_black_tree.h" #include "core/hle/kernel/k_class_token.h" namespace Kernel { @@ -175,7 +176,7 @@ private: class KAutoObjectWithListContainer; -class KAutoObjectWithList : public KAutoObject { +class KAutoObjectWithList : public KAutoObject, public boost::intrusive::set_base_hook<> { public: explicit KAutoObjectWithList(KernelCore& kernel_) : KAutoObject(kernel_) {} @@ -192,6 +193,10 @@ public: } } + friend bool operator<(const KAutoObjectWithList& left, const KAutoObjectWithList& right) { + return &left < &right; + } + public: virtual u64 GetId() const { return reinterpret_cast<u64>(this); @@ -203,8 +208,6 @@ public: private: friend class KAutoObjectWithListContainer; - - Common::IntrusiveRedBlackTreeNode list_node; }; template <typename T> diff --git a/src/core/hle/kernel/k_auto_object_container.cpp b/src/core/hle/kernel/k_auto_object_container.cpp index fc0c28874..010006bb7 100644 --- a/src/core/hle/kernel/k_auto_object_container.cpp +++ b/src/core/hle/kernel/k_auto_object_container.cpp @@ -9,13 +9,13 @@ namespace Kernel { void KAutoObjectWithListContainer::Register(KAutoObjectWithList* obj) { KScopedLightLock lk(m_lock); - m_object_list.insert(*obj); + m_object_list.insert_unique(*obj); } void KAutoObjectWithListContainer::Unregister(KAutoObjectWithList* obj) { KScopedLightLock lk(m_lock); - m_object_list.erase(m_object_list.iterator_to(*obj)); + m_object_list.erase(*obj); } size_t KAutoObjectWithListContainer::GetOwnedCount(KProcess* owner) { diff --git a/src/core/hle/kernel/k_auto_object_container.h b/src/core/hle/kernel/k_auto_object_container.h index ff40cf5a7..459953450 100644 --- a/src/core/hle/kernel/k_auto_object_container.h +++ b/src/core/hle/kernel/k_auto_object_container.h @@ -6,6 +6,8 @@ #include <atomic> +#include <boost/intrusive/rbtree.hpp> + #include "common/assert.h" #include "common/common_funcs.h" #include "common/common_types.h" @@ -23,8 +25,7 @@ class KAutoObjectWithListContainer { YUZU_NON_MOVEABLE(KAutoObjectWithListContainer); public: - using ListType = Common::IntrusiveRedBlackTreeMemberTraits< - &KAutoObjectWithList::list_node>::TreeType<KAutoObjectWithList>; + using ListType = boost::intrusive::rbtree<KAutoObjectWithList>; public: class ListAccessor : public KScopedLightLock { diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp index 23d830d1f..ef168fe87 100644 --- a/src/core/hle/kernel/k_client_port.cpp +++ b/src/core/hle/kernel/k_client_port.cpp @@ -16,11 +16,11 @@ namespace Kernel { KClientPort::KClientPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} KClientPort::~KClientPort() = default; -void KClientPort::Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_) { +void KClientPort::Initialize(KPort* parent_port_, s32 max_sessions_, std::string&& name_) { // Set member variables. num_sessions = 0; peak_sessions = 0; - parent = parent_; + parent = parent_port_; max_sessions = max_sessions_; name = std::move(name_); } @@ -28,6 +28,9 @@ void KClientPort::Initialize(KPort* parent_, s32 max_sessions_, std::string&& na void KClientPort::OnSessionFinalized() { KScopedSchedulerLock sl{kernel}; + // This might happen if a session was improperly used with this port. + ASSERT_MSG(num_sessions > 0, "num_sessions is invalid"); + const auto prev = num_sessions--; if (prev == max_sessions) { this->NotifyAvailable(); @@ -56,7 +59,8 @@ bool KClientPort::IsSignaled() const { return num_sessions < max_sessions; } -ResultCode KClientPort::CreateSession(KClientSession** out) { +ResultCode KClientPort::CreateSession(KClientSession** out, + std::shared_ptr<SessionRequestManager> session_manager) { // Reserve a new session from the resource limit. KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(), LimitableResource::Sessions); @@ -65,7 +69,7 @@ ResultCode KClientPort::CreateSession(KClientSession** out) { // Update the session counts. { // Atomically increment the number of sessions. - s32 new_sessions; + s32 new_sessions{}; { const auto max = max_sessions; auto cur_sessions = num_sessions.load(std::memory_order_acquire); @@ -101,7 +105,7 @@ ResultCode KClientPort::CreateSession(KClientSession** out) { } // Initialize the session. - session->Initialize(this, parent->GetName()); + session->Initialize(this, parent->GetName(), session_manager); // Commit the session reservation. session_reservation.Commit(); diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h index f2fff3b01..54bb05e20 100644 --- a/src/core/hle/kernel/k_client_port.h +++ b/src/core/hle/kernel/k_client_port.h @@ -16,6 +16,7 @@ namespace Kernel { class KClientSession; class KernelCore; class KPort; +class SessionRequestManager; class KClientPort final : public KSynchronizationObject { KERNEL_AUTOOBJECT_TRAITS(KClientPort, KSynchronizationObject); @@ -52,7 +53,8 @@ public: void Destroy() override; bool IsSignaled() const override; - ResultCode CreateSession(KClientSession** out); + ResultCode CreateSession(KClientSession** out, + std::shared_ptr<SessionRequestManager> session_manager = nullptr); private: std::atomic<s32> num_sessions{}; diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h index b11d5b4e3..230e3b6b8 100644 --- a/src/core/hle/kernel/k_client_session.h +++ b/src/core/hle/kernel/k_client_session.h @@ -36,9 +36,9 @@ public: explicit KClientSession(KernelCore& kernel_); ~KClientSession() override; - void Initialize(KSession* parent_, std::string&& name_) { + void Initialize(KSession* parent_session_, std::string&& name_) { // Set member variables. - parent = parent_; + parent = parent_session_; name = std::move(name_); } diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h index ca2e539a7..a95fa41f3 100644 --- a/src/core/hle/kernel/k_light_condition_variable.h +++ b/src/core/hle/kernel/k_light_condition_variable.h @@ -18,41 +18,58 @@ class KernelCore; class KLightConditionVariable { public: - explicit KLightConditionVariable(KernelCore& kernel_) - : thread_queue(kernel_), kernel(kernel_) {} + explicit KLightConditionVariable(KernelCore& kernel_) : kernel{kernel_} {} - void Wait(KLightLock* lock, s64 timeout = -1) { - WaitImpl(lock, timeout); - lock->Lock(); + void Wait(KLightLock* lock, s64 timeout = -1, bool allow_terminating_thread = true) { + WaitImpl(lock, timeout, allow_terminating_thread); } void Broadcast() { KScopedSchedulerLock lk{kernel}; - while (thread_queue.WakeupFrontThread() != nullptr) { - // We want to signal all threads, and so should continue waking up until there's nothing - // to wake. + + // Signal all threads. + for (auto& thread : wait_list) { + thread.SetState(ThreadState::Runnable); } } private: - void WaitImpl(KLightLock* lock, s64 timeout) { + void WaitImpl(KLightLock* lock, s64 timeout, bool allow_terminating_thread) { KThread* owner = GetCurrentThreadPointer(kernel); // Sleep the thread. { - KScopedSchedulerLockAndSleep lk(kernel, owner, timeout); - lock->Unlock(); + KScopedSchedulerLockAndSleep lk{kernel, owner, timeout}; - if (!thread_queue.SleepThread(owner)) { + if (!allow_terminating_thread && owner->IsTerminationRequested()) { lk.CancelSleep(); return; } + + lock->Unlock(); + + // Set the thread as waiting. + GetCurrentThread(kernel).SetState(ThreadState::Waiting); + + // Add the thread to the queue. + wait_list.push_back(GetCurrentThread(kernel)); + } + + // Remove the thread from the wait list. + { + KScopedSchedulerLock sl{kernel}; + + wait_list.erase(wait_list.iterator_to(GetCurrentThread(kernel))); } // Cancel the task that the sleep setup. kernel.TimeManager().UnscheduleTimeEvent(owner); + + // Re-acquire the lock. + lock->Lock(); } - KThreadQueue thread_queue; + KernelCore& kernel; + KThread::WaiterList wait_list{}; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_lock.cpp b/src/core/hle/kernel/k_light_lock.cpp index f974022e8..0896e705f 100644 --- a/src/core/hle/kernel/k_light_lock.cpp +++ b/src/core/hle/kernel/k_light_lock.cpp @@ -59,11 +59,7 @@ void KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) { owner_thread->AddWaiter(cur_thread); // Set thread states. - if (cur_thread->GetState() == ThreadState::Runnable) { - cur_thread->SetState(ThreadState::Waiting); - } else { - KScheduler::SetSchedulerUpdateNeeded(kernel); - } + cur_thread->SetState(ThreadState::Waiting); if (owner_thread->IsSuspended()) { owner_thread->ContinueIfHasKernelWaiters(); @@ -73,10 +69,9 @@ void KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) { // We're no longer waiting on the lock owner. { KScopedSchedulerLock sl{kernel}; - KThread* owner_thread = cur_thread->GetLockOwner(); - if (owner_thread) { + + if (KThread* owner_thread = cur_thread->GetLockOwner(); owner_thread != nullptr) { owner_thread->RemoveWaiter(cur_thread); - KScheduler::SetSchedulerUpdateNeeded(kernel); } } } @@ -95,17 +90,13 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) { // Pass the lock to the next owner. uintptr_t next_tag = 0; - if (next_owner) { + if (next_owner != nullptr) { next_tag = reinterpret_cast<uintptr_t>(next_owner); if (num_waiters > 1) { next_tag |= 0x1; } - if (next_owner->GetState() == ThreadState::Waiting) { - next_owner->SetState(ThreadState::Runnable); - } else { - KScheduler::SetSchedulerUpdateNeeded(kernel); - } + next_owner->SetState(ThreadState::Runnable); if (next_owner->IsSuspended()) { next_owner->ContinueIfHasKernelWaiters(); diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 06b8ce151..d1bd98051 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -201,17 +201,15 @@ bool KProcess::ReleaseUserException(KThread* thread) { // Remove waiter thread. s32 num_waiters{}; - KThread* next = thread->RemoveWaiterByKey( - std::addressof(num_waiters), - reinterpret_cast<uintptr_t>(std::addressof(exception_thread))); - if (next != nullptr) { - if (next->GetState() == ThreadState::Waiting) { - next->SetState(ThreadState::Runnable); - } else { - KScheduler::SetSchedulerUpdateNeeded(kernel); - } + if (KThread* next = thread->RemoveWaiterByKey( + std::addressof(num_waiters), + reinterpret_cast<uintptr_t>(std::addressof(exception_thread))); + next != nullptr) { + next->SetState(ThreadState::Runnable); } + KScheduler::SetSchedulerUpdateNeeded(kernel); + return true; } else { return false; diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h index b2850ac7b..149fa78dd 100644 --- a/src/core/hle/kernel/k_readable_event.h +++ b/src/core/hle/kernel/k_readable_event.h @@ -21,9 +21,9 @@ public: explicit KReadableEvent(KernelCore& kernel_); ~KReadableEvent() override; - void Initialize(KEvent* parent_, std::string&& name_) { + void Initialize(KEvent* parent_event_, std::string&& name_) { is_signaled = false; - parent = parent_; + parent = parent_event_; name = std::move(name_); } diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index f91cb65dc..da88f35bc 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -117,7 +117,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { if (current_hints[index] + value <= limit_values[index] && (timeout < 0 || core_timing->GetGlobalTimeNs().count() < timeout)) { waiter_count++; - cond_var.Wait(&lock, timeout); + cond_var.Wait(&lock, timeout, false); waiter_count--; } else { break; diff --git a/src/core/hle/kernel/k_server_port.cpp b/src/core/hle/kernel/k_server_port.cpp index 8cbde177a..c5dc58387 100644 --- a/src/core/hle/kernel/k_server_port.cpp +++ b/src/core/hle/kernel/k_server_port.cpp @@ -17,9 +17,9 @@ namespace Kernel { KServerPort::KServerPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} KServerPort::~KServerPort() = default; -void KServerPort::Initialize(KPort* parent_, std::string&& name_) { +void KServerPort::Initialize(KPort* parent_port_, std::string&& name_) { // Set member variables. - parent = parent_; + parent = parent_port_; name = std::move(name_); } diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h index 55481d63f..67a36da40 100644 --- a/src/core/hle/kernel/k_server_port.h +++ b/src/core/hle/kernel/k_server_port.h @@ -29,7 +29,7 @@ public: explicit KServerPort(KernelCore& kernel_); ~KServerPort() override; - void Initialize(KPort* parent_, std::string&& name_); + void Initialize(KPort* parent_port_, std::string&& name_); /// Whether or not this server port has an HLE handler available. bool HasSessionRequestHandler() const { diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index dbf03b462..5c3c13ce6 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp @@ -8,13 +8,16 @@ #include "common/assert.h" #include "common/common_types.h" #include "common/logging/log.h" +#include "common/scope_exit.h" #include "core/core_timing.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/k_client_port.h" #include "core/hle/kernel/k_handle_table.h" +#include "core/hle/kernel/k_port.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_scheduler.h" +#include "core/hle/kernel/k_server_port.h" #include "core/hle/kernel/k_server_session.h" #include "core/hle/kernel/k_session.h" #include "core/hle/kernel/k_thread.h" @@ -23,18 +26,21 @@ namespace Kernel { -KServerSession::KServerSession(KernelCore& kernel_) - : KSynchronizationObject{kernel_}, manager{std::make_shared<SessionRequestManager>()} {} +KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} -KServerSession::~KServerSession() { - kernel.ReleaseServiceThread(service_thread); -} +KServerSession::~KServerSession() {} -void KServerSession::Initialize(KSession* parent_, std::string&& name_) { +void KServerSession::Initialize(KSession* parent_session_, std::string&& name_, + std::shared_ptr<SessionRequestManager> manager_) { // Set member variables. - parent = parent_; + parent = parent_session_; name = std::move(name_); - service_thread = kernel.CreateServiceThread(name); + + if (manager_) { + manager = manager_; + } else { + manager = std::make_shared<SessionRequestManager>(kernel); + } } void KServerSession::Destroy() { @@ -114,9 +120,25 @@ ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memor context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); - if (auto strong_ptr = service_thread.lock()) { - strong_ptr->QueueSyncRequest(*parent, std::move(context)); - return ResultSuccess; + // In the event that something fails here, stub a result to prevent the game from crashing. + // This is a work-around in the event that somehow we process a service request after the + // session has been closed by the game. This has been observed to happen rarely in Pokemon + // Sword/Shield and is likely a result of us using host threads/scheduling for services. + // TODO(bunnei): Find a better solution here. + auto error_guard = SCOPE_GUARD({ CompleteSyncRequest(*context); }); + + // Ensure we have a session request handler + if (manager->HasSessionRequestHandler(*context)) { + if (auto strong_ptr = manager->GetServiceThread().lock()) { + strong_ptr->QueueSyncRequest(*parent, std::move(context)); + + // We succeeded. + error_guard.Cancel(); + } else { + ASSERT_MSG(false, "strong_ptr is nullptr!"); + } + } else { + ASSERT_MSG(false, "handler is invalid!"); } return ResultSuccess; @@ -124,13 +146,20 @@ ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memor ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) { ResultCode result = ResultSuccess; + // If the session has been converted to a domain, handle the domain request - if (IsDomain() && context.HasDomainMessageHeader()) { - result = HandleDomainSyncRequest(context); - // If there is no domain header, the regular session handler is used - } else if (manager->HasSessionHandler()) { - // If this ServerSession has an associated HLE handler, forward the request to it. - result = manager->SessionHandler().HandleSyncRequest(*this, context); + if (manager->HasSessionRequestHandler(context)) { + if (IsDomain() && context.HasDomainMessageHeader()) { + result = HandleDomainSyncRequest(context); + // If there is no domain header, the regular session handler is used + } else if (manager->HasSessionHandler()) { + // If this ServerSession has an associated HLE handler, forward the request to it. + result = manager->SessionHandler().HandleSyncRequest(*this, context); + } + } else { + ASSERT_MSG(false, "Session handler is invalid, stubbing response!"); + IPC::ResponseBuilder rb(context, 2); + rb.Push(ResultSuccess); } if (convert_to_domain) { diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h index 27b757ad2..d44bc9d4f 100644 --- a/src/core/hle/kernel/k_server_session.h +++ b/src/core/hle/kernel/k_server_session.h @@ -32,6 +32,7 @@ class HLERequestContext; class KernelCore; class KSession; class SessionRequestHandler; +class SessionRequestManager; class KThread; class KServerSession final : public KSynchronizationObject, @@ -46,7 +47,8 @@ public: void Destroy() override; - void Initialize(KSession* parent_, std::string&& name_); + void Initialize(KSession* parent_session_, std::string&& name_, + std::shared_ptr<SessionRequestManager> manager_); KSession* GetParent() { return parent; @@ -60,15 +62,14 @@ public: void OnClientClosed(); - /** - * Sets the HLE handler for the session. This handler will be called to service IPC requests - * instead of the regular IPC machinery. (The regular IPC machinery is currently not - * implemented.) - */ - void SetSessionHandler(SessionRequestHandlerPtr handler) { + void ClientConnected(SessionRequestHandlerPtr handler) { manager->SetSessionHandler(std::move(handler)); } + void ClientDisconnected() { + manager = nullptr; + } + /** * Handle a sync request from the emulated application. * @@ -104,16 +105,6 @@ public: return manager; } - /// Gets the session request manager, which forwards requests to the underlying service - const std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() const { - return manager; - } - - /// Sets the session request manager, which forwards requests to the underlying service - void SetSessionRequestManager(std::shared_ptr<SessionRequestManager> manager_) { - manager = std::move(manager_); - } - private: /// Queues a sync request from the emulated application. ResultCode QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory); @@ -131,9 +122,6 @@ private: /// When set to True, converts the session to a domain at the end of the command bool convert_to_domain{}; - /// Thread to dispatch service requests - std::weak_ptr<ServiceThread> service_thread; - /// KSession that owns this KServerSession KSession* parent{}; }; diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp index 025b8b555..940878e03 100644 --- a/src/core/hle/kernel/k_session.cpp +++ b/src/core/hle/kernel/k_session.cpp @@ -15,7 +15,8 @@ KSession::KSession(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_}, server{kernel_}, client{kernel_} {} KSession::~KSession() = default; -void KSession::Initialize(KClientPort* port_, const std::string& name_) { +void KSession::Initialize(KClientPort* port_, const std::string& name_, + std::shared_ptr<SessionRequestManager> manager_) { // Increment reference count. // Because reference count is one on creation, this will result // in a reference count of two. Thus, when both server and client are closed @@ -27,7 +28,7 @@ void KSession::Initialize(KClientPort* port_, const std::string& name_) { KAutoObject::Create(std::addressof(client)); // Initialize our sub sessions. - server.Initialize(this, name_ + ":Server"); + server.Initialize(this, name_ + ":Server", manager_); client.Initialize(this, name_ + ":Client"); // Set state and name. diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h index 4ddd080d2..62c328a68 100644 --- a/src/core/hle/kernel/k_session.h +++ b/src/core/hle/kernel/k_session.h @@ -13,6 +13,8 @@ namespace Kernel { +class SessionRequestManager; + class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAutoObjectWithList> { KERNEL_AUTOOBJECT_TRAITS(KSession, KAutoObject); @@ -20,7 +22,8 @@ public: explicit KSession(KernelCore& kernel_); ~KSession() override; - void Initialize(KClientPort* port_, const std::string& name_); + void Initialize(KClientPort* port_, const std::string& name_, + std::shared_ptr<SessionRequestManager> manager_ = nullptr); void Finalize() override; diff --git a/src/core/hle/kernel/k_writable_event.cpp b/src/core/hle/kernel/k_writable_event.cpp index b7b83c151..bdb1db6d5 100644 --- a/src/core/hle/kernel/k_writable_event.cpp +++ b/src/core/hle/kernel/k_writable_event.cpp @@ -13,8 +13,8 @@ KWritableEvent::KWritableEvent(KernelCore& kernel_) KWritableEvent::~KWritableEvent() = default; -void KWritableEvent::Initialize(KEvent* parent_, std::string&& name_) { - parent = parent_; +void KWritableEvent::Initialize(KEvent* parent_event_, std::string&& name_) { + parent = parent_event_; name = std::move(name_); parent->GetReadableEvent().Open(); } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 0ffb78d51..2ceeaeb5f 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -63,8 +63,6 @@ struct KernelCore::Impl { global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel); - service_thread_manager = - std::make_unique<Common::ThreadWorker>(1, "yuzu:ServiceThreadManager"); is_phantom_mode_for_singlecore = false; InitializePhysicalCores(); @@ -96,7 +94,6 @@ struct KernelCore::Impl { process_list.clear(); // Ensures all service threads gracefully shutdown - service_thread_manager.reset(); service_threads.clear(); next_object_id = 0; @@ -680,10 +677,6 @@ struct KernelCore::Impl { // Threads used for services std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads; - // Service threads are managed by a worker thread, so that a calling service thread can queue up - // the release of itself - std::unique_ptr<Common::ThreadWorker> service_thread_manager; - std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads; std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{}; std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; @@ -986,17 +979,14 @@ void KernelCore::ExitSVCProfile() { std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) { auto service_thread = std::make_shared<Kernel::ServiceThread>(*this, 1, name); - impl->service_thread_manager->QueueWork( - [this, service_thread] { impl->service_threads.emplace(service_thread); }); + impl->service_threads.emplace(service_thread); return service_thread; } void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) { - impl->service_thread_manager->QueueWork([this, service_thread] { - if (auto strong_ptr = service_thread.lock()) { - impl->service_threads.erase(strong_ptr); - } - }); + if (auto strong_ptr = service_thread.lock()) { + impl->service_threads.erase(strong_ptr); + } } Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() { diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 28bcae6e7..8339e11a0 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -449,8 +449,8 @@ static ResultCode CancelSynchronization(Core::System& system, Handle handle) { // Get the thread from its handle. KScopedAutoObject thread = - system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>( - static_cast<Handle>(handle)); + system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(handle); + R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Cancel the thread's wait. thread->WaitCancel(); |