diff options
Diffstat (limited to 'src/core/hle')
49 files changed, 719 insertions, 280 deletions
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index d631c0357..0cc26a211 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -152,7 +152,8 @@ public: Kernel::LimitableResource::Sessions, 1); auto* session = Kernel::KSession::Create(kernel); - session->Initialize(nullptr, iface->GetServiceName()); + session->Initialize(nullptr, iface->GetServiceName(), + std::make_shared<Kernel::SessionRequestManager>(kernel)); context->AddMoveObject(&session->GetClientSession()); iface->ClientConnected(&session->GetServerSession()); diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 99265ce90..e258e2cdf 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -43,13 +43,13 @@ class Domain; class HLERequestContext; class KAutoObject; class KernelCore; +class KEvent; class KHandleTable; class KProcess; class KServerSession; class KThread; class KReadableEvent; class KSession; -class KWritableEvent; class ServiceThread; enum class ThreadWakeupReason; diff --git a/src/core/hle/kernel/k_class_token.cpp b/src/core/hle/kernel/k_class_token.cpp index cc2a0f7ca..10265c23c 100644 --- a/src/core/hle/kernel/k_class_token.cpp +++ b/src/core/hle/kernel/k_class_token.cpp @@ -18,7 +18,6 @@ #include "core/hle/kernel/k_synchronization_object.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_transfer_memory.h" -#include "core/hle/kernel/k_writable_event.h" namespace Kernel { @@ -42,13 +41,12 @@ static_assert(ClassToken<KPort> == 0b10000101'00000000); static_assert(ClassToken<KSession> == 0b00011001'00000000); static_assert(ClassToken<KSharedMemory> == 0b00101001'00000000); static_assert(ClassToken<KEvent> == 0b01001001'00000000); -static_assert(ClassToken<KWritableEvent> == 0b10001001'00000000); // static_assert(ClassToken<KLightClientSession> == 0b00110001'00000000); // static_assert(ClassToken<KLightServerSession> == 0b01010001'00000000); -static_assert(ClassToken<KTransferMemory> == 0b10010001'00000000); +static_assert(ClassToken<KTransferMemory> == 0b01010001'00000000); // static_assert(ClassToken<KDeviceAddressSpace> == 0b01100001'00000000); // static_assert(ClassToken<KSessionRequest> == 0b10100001'00000000); -static_assert(ClassToken<KCodeMemory> == 0b11000001'00000000); +static_assert(ClassToken<KCodeMemory> == 0b10100001'00000000); // Ensure that the token hierarchy is correct. @@ -73,13 +71,12 @@ static_assert(ClassToken<KPort> == ((0b10000101 << 8) | ClassToken<KAutoObject>) static_assert(ClassToken<KSession> == ((0b00011001 << 8) | ClassToken<KAutoObject>)); static_assert(ClassToken<KSharedMemory> == ((0b00101001 << 8) | ClassToken<KAutoObject>)); static_assert(ClassToken<KEvent> == ((0b01001001 << 8) | ClassToken<KAutoObject>)); -static_assert(ClassToken<KWritableEvent> == ((0b10001001 << 8) | ClassToken<KAutoObject>)); // static_assert(ClassToken<KLightClientSession> == ((0b00110001 << 8) | ClassToken<KAutoObject>)); // static_assert(ClassToken<KLightServerSession> == ((0b01010001 << 8) | ClassToken<KAutoObject>)); -static_assert(ClassToken<KTransferMemory> == ((0b10010001 << 8) | ClassToken<KAutoObject>)); +static_assert(ClassToken<KTransferMemory> == ((0b01010001 << 8) | ClassToken<KAutoObject>)); // static_assert(ClassToken<KDeviceAddressSpace> == ((0b01100001 << 8) | ClassToken<KAutoObject>)); // static_assert(ClassToken<KSessionRequest> == ((0b10100001 << 8) | ClassToken<KAutoObject>)); -static_assert(ClassToken<KCodeMemory> == ((0b11000001 << 8) | ClassToken<KAutoObject>)); +static_assert(ClassToken<KCodeMemory> == ((0b10100001 << 8) | ClassToken<KAutoObject>)); // Ensure that the token hierarchy reflects the class hierarchy. @@ -110,7 +107,6 @@ static_assert(std::is_final_v<KPort> && std::is_base_of_v<KAutoObject, KPort>); static_assert(std::is_final_v<KSession> && std::is_base_of_v<KAutoObject, KSession>); static_assert(std::is_final_v<KSharedMemory> && std::is_base_of_v<KAutoObject, KSharedMemory>); static_assert(std::is_final_v<KEvent> && std::is_base_of_v<KAutoObject, KEvent>); -static_assert(std::is_final_v<KWritableEvent> && std::is_base_of_v<KAutoObject, KWritableEvent>); // static_assert(std::is_final_v<KLightClientSession> && // std::is_base_of_v<KAutoObject, KLightClientSession>); // static_assert(std::is_final_v<KLightServerSession> && diff --git a/src/core/hle/kernel/k_class_token.h b/src/core/hle/kernel/k_class_token.h index c9001ae3d..ab20e00ff 100644 --- a/src/core/hle/kernel/k_class_token.h +++ b/src/core/hle/kernel/k_class_token.h @@ -101,7 +101,6 @@ public: KSession, KSharedMemory, KEvent, - KWritableEvent, KLightClientSession, KLightServerSession, KTransferMemory, diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp index b2a887b14..8892c5b7c 100644 --- a/src/core/hle/kernel/k_client_session.cpp +++ b/src/core/hle/kernel/k_client_session.cpp @@ -21,10 +21,9 @@ void KClientSession::Destroy() { void KClientSession::OnServerClosed() {} -Result KClientSession::SendSyncRequest(KThread* thread, Core::Memory::Memory& memory, - Core::Timing::CoreTiming& core_timing) { +Result KClientSession::SendSyncRequest() { // Signal the server session that new data is available - return parent->GetServerSession().HandleSyncRequest(thread, memory, core_timing); + return parent->GetServerSession().OnRequest(); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h index 0c750d756..b4a19c546 100644 --- a/src/core/hle/kernel/k_client_session.h +++ b/src/core/hle/kernel/k_client_session.h @@ -46,8 +46,7 @@ public: return parent; } - Result SendSyncRequest(KThread* thread, Core::Memory::Memory& memory, - Core::Timing::CoreTiming& core_timing); + Result SendSyncRequest(); void OnServerClosed(); diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp index e52fafbc7..78ca59463 100644 --- a/src/core/hle/kernel/k_event.cpp +++ b/src/core/hle/kernel/k_event.cpp @@ -8,39 +8,45 @@ namespace Kernel { KEvent::KEvent(KernelCore& kernel_) - : KAutoObjectWithSlabHeapAndContainer{kernel_}, readable_event{kernel_}, writable_event{ - kernel_} {} + : KAutoObjectWithSlabHeapAndContainer{kernel_}, m_readable_event{kernel_} {} KEvent::~KEvent() = default; -void KEvent::Initialize(std::string&& name_, KProcess* owner_) { - // Increment reference count. - // Because reference count is one on creation, this will result - // in a reference count of two. Thus, when both readable and - // writable events are closed this object will be destroyed. - Open(); +void KEvent::Initialize(KProcess* owner) { + // Create our readable event. + KAutoObject::Create(std::addressof(m_readable_event)); - // Create our sub events. - KAutoObject::Create(std::addressof(readable_event)); - KAutoObject::Create(std::addressof(writable_event)); - - // Initialize our sub sessions. - readable_event.Initialize(this, name_ + ":Readable"); - writable_event.Initialize(this, name_ + ":Writable"); + // Initialize our readable event. + m_readable_event.Initialize(this); // Set our owner process. - owner = owner_; - owner->Open(); + m_owner = owner; + m_owner->Open(); // Mark initialized. - name = std::move(name_); - initialized = true; + m_initialized = true; } void KEvent::Finalize() { KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObjectWithList>::Finalize(); } +Result KEvent::Signal() { + KScopedSchedulerLock sl{kernel}; + + R_SUCCEED_IF(m_readable_event_destroyed); + + return m_readable_event.Signal(); +} + +Result KEvent::Clear() { + KScopedSchedulerLock sl{kernel}; + + R_SUCCEED_IF(m_readable_event_destroyed); + + return m_readable_event.Clear(); +} + void KEvent::PostDestroy(uintptr_t arg) { // Release the event count resource the owner process holds. KProcess* owner = reinterpret_cast<KProcess*>(arg); diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h index 2ff828feb..48ce7d9a0 100644 --- a/src/core/hle/kernel/k_event.h +++ b/src/core/hle/kernel/k_event.h @@ -4,14 +4,12 @@ #pragma once #include "core/hle/kernel/k_readable_event.h" -#include "core/hle/kernel/k_writable_event.h" #include "core/hle/kernel/slab_helpers.h" namespace Kernel { class KernelCore; class KReadableEvent; -class KWritableEvent; class KProcess; class KEvent final : public KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObjectWithList> { @@ -21,37 +19,40 @@ public: explicit KEvent(KernelCore& kernel_); ~KEvent() override; - void Initialize(std::string&& name, KProcess* owner_); + void Initialize(KProcess* owner); void Finalize() override; bool IsInitialized() const override { - return initialized; + return m_initialized; } uintptr_t GetPostDestroyArgument() const override { - return reinterpret_cast<uintptr_t>(owner); + return reinterpret_cast<uintptr_t>(m_owner); } KProcess* GetOwner() const override { - return owner; + return m_owner; } KReadableEvent& GetReadableEvent() { - return readable_event; - } - - KWritableEvent& GetWritableEvent() { - return writable_event; + return m_readable_event; } static void PostDestroy(uintptr_t arg); + Result Signal(); + Result Clear(); + + void OnReadableEventDestroyed() { + m_readable_event_destroyed = true; + } + private: - KReadableEvent readable_event; - KWritableEvent writable_event; - KProcess* owner{}; - bool initialized{}; + KReadableEvent m_readable_event; + KProcess* m_owner{}; + bool m_initialized{}; + bool m_readable_event_destroyed{}; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_readable_event.cpp b/src/core/hle/kernel/k_readable_event.cpp index 94c5464fe..5c942d47c 100644 --- a/src/core/hle/kernel/k_readable_event.cpp +++ b/src/core/hle/kernel/k_readable_event.cpp @@ -15,31 +15,44 @@ KReadableEvent::KReadableEvent(KernelCore& kernel_) : KSynchronizationObject{ker KReadableEvent::~KReadableEvent() = default; +void KReadableEvent::Initialize(KEvent* parent) { + m_is_signaled = false; + m_parent = parent; + + if (m_parent != nullptr) { + m_parent->Open(); + } +} + bool KReadableEvent::IsSignaled() const { - ASSERT(kernel.GlobalSchedulerContext().IsLocked()); + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); - return is_signaled; + return m_is_signaled; } void KReadableEvent::Destroy() { - if (parent) { - parent->Close(); + if (m_parent) { + { + KScopedSchedulerLock sl{kernel}; + m_parent->OnReadableEventDestroyed(); + } + m_parent->Close(); } } Result KReadableEvent::Signal() { KScopedSchedulerLock lk{kernel}; - if (!is_signaled) { - is_signaled = true; - NotifyAvailable(); + if (!m_is_signaled) { + m_is_signaled = true; + this->NotifyAvailable(); } return ResultSuccess; } Result KReadableEvent::Clear() { - Reset(); + this->Reset(); return ResultSuccess; } @@ -47,11 +60,11 @@ Result KReadableEvent::Clear() { Result KReadableEvent::Reset() { KScopedSchedulerLock lk{kernel}; - if (!is_signaled) { + if (!m_is_signaled) { return ResultInvalidState; } - is_signaled = false; + m_is_signaled = false; return ResultSuccess; } diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h index 18dcad289..743f96bf5 100644 --- a/src/core/hle/kernel/k_readable_event.h +++ b/src/core/hle/kernel/k_readable_event.h @@ -20,26 +20,23 @@ public: explicit KReadableEvent(KernelCore& kernel_); ~KReadableEvent() override; - void Initialize(KEvent* parent_event_, std::string&& name_) { - is_signaled = false; - parent = parent_event_; - name = std::move(name_); - } + void Initialize(KEvent* parent); KEvent* GetParent() const { - return parent; + return m_parent; } + Result Signal(); + Result Clear(); + bool IsSignaled() const override; void Destroy() override; - Result Signal(); - Result Clear(); Result Reset(); private: - bool is_signaled{}; - KEvent* parent{}; + bool m_is_signaled{}; + KEvent* m_parent{}; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index 802c646a6..4252c9adb 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp @@ -7,6 +7,8 @@ #include "common/assert.h" #include "common/common_types.h" #include "common/logging/log.h" +#include "common/scope_exit.h" +#include "core/core.h" #include "core/core_timing.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/hle_ipc.h" @@ -18,13 +20,19 @@ #include "core/hle/kernel/k_server_session.h" #include "core/hle/kernel/k_session.h" #include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/k_thread_queue.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/service_thread.h" #include "core/memory.h" namespace Kernel { -KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} +using ThreadQueueImplForKServerSessionRequest = KThreadQueue; + +static constexpr u32 MessageBufferSize = 0x100; + +KServerSession::KServerSession(KernelCore& kernel_) + : KSynchronizationObject{kernel_}, m_lock{kernel_} {} KServerSession::~KServerSession() = default; @@ -33,17 +41,14 @@ void KServerSession::Initialize(KSession* parent_session_, std::string&& name_, // Set member variables. parent = parent_session_; name = std::move(name_); - - if (manager_) { - manager = manager_; - } else { - manager = std::make_shared<SessionRequestManager>(kernel); - } + manager = manager_; } void KServerSession::Destroy() { parent->OnServerClosed(); + this->CleanupRequests(); + parent->Close(); // Release host emulation members. @@ -54,13 +59,13 @@ void KServerSession::Destroy() { } void KServerSession::OnClientClosed() { - if (manager->HasSessionHandler()) { + if (manager && manager->HasSessionHandler()) { manager->SessionHandler().ClientDisconnected(this); } } bool KServerSession::IsSignaled() const { - ASSERT(kernel.GlobalSchedulerContext().IsLocked()); + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // If the client is closed, we're always signaled. if (parent->IsClientClosed()) { @@ -68,7 +73,7 @@ bool KServerSession::IsSignaled() const { } // Otherwise, we're signaled if we have a request and aren't handling one. - return false; + return !m_thread_request_list.empty() && m_current_thread_request == nullptr; } void KServerSession::AppendDomainHandler(SessionRequestHandlerPtr handler) { @@ -173,9 +178,221 @@ Result KServerSession::CompleteSyncRequest(HLERequestContext& context) { return result; } -Result KServerSession::HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory, - Core::Timing::CoreTiming& core_timing) { - return QueueSyncRequest(thread, memory); +Result KServerSession::OnRequest() { + // Create the wait queue. + ThreadQueueImplForKServerSessionRequest wait_queue{kernel}; + + { + // Lock the scheduler. + KScopedSchedulerLock sl{kernel}; + + // Ensure that we can handle new requests. + R_UNLESS(!parent->IsServerClosed(), ResultSessionClosed); + + // Check that we're not terminating. + R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); + + if (manager) { + // HLE request. + auto& memory{kernel.System().Memory()}; + this->QueueSyncRequest(GetCurrentThreadPointer(kernel), memory); + } else { + // Non-HLE request. + auto* thread{GetCurrentThreadPointer(kernel)}; + + // Get whether we're empty. + const bool was_empty = m_thread_request_list.empty(); + + // Add the thread to the list. + thread->Open(); + m_thread_request_list.push_back(thread); + + // If we were empty, signal. + if (was_empty) { + this->NotifyAvailable(); + } + } + + // This is a synchronous request, so we should wait for our request to complete. + GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); + GetCurrentThread(kernel).BeginWait(&wait_queue); + } + + return GetCurrentThread(kernel).GetWaitResult(); +} + +Result KServerSession::SendReply() { + // Lock the session. + KScopedLightLock lk(m_lock); + + // Get the request. + KThread* client_thread; + { + KScopedSchedulerLock sl{kernel}; + + // Get the current request. + client_thread = m_current_thread_request; + R_UNLESS(client_thread != nullptr, ResultInvalidState); + + // Clear the current request, since we're processing it. + m_current_thread_request = nullptr; + if (!m_thread_request_list.empty()) { + this->NotifyAvailable(); + } + } + + // Close reference to the request once we're done processing it. + SCOPE_EXIT({ client_thread->Close(); }); + + // Extract relevant information from the request. + // const uintptr_t client_message = request->GetAddress(); + // const size_t client_buffer_size = request->GetSize(); + // KThread *client_thread = request->GetThread(); + // KEvent *event = request->GetEvent(); + + // Check whether we're closed. + const bool closed = (client_thread == nullptr || parent->IsClientClosed()); + + Result result = ResultSuccess; + if (!closed) { + // If we're not closed, send the reply. + Core::Memory::Memory& memory{kernel.System().Memory()}; + KThread* server_thread{GetCurrentThreadPointer(kernel)}; + UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess()); + + auto* src_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress()); + auto* dst_msg_buffer = memory.GetPointer(client_thread->GetTLSAddress()); + std::memcpy(dst_msg_buffer, src_msg_buffer, MessageBufferSize); + } else { + result = ResultSessionClosed; + } + + // Select a result for the client. + Result client_result = result; + if (closed && R_SUCCEEDED(result)) { + result = ResultSessionClosed; + client_result = ResultSessionClosed; + } else { + result = ResultSuccess; + } + + // If there's a client thread, update it. + if (client_thread != nullptr) { + // End the client thread's wait. + KScopedSchedulerLock sl{kernel}; + + if (!client_thread->IsTerminationRequested()) { + client_thread->EndWait(client_result); + } + } + + return result; +} + +Result KServerSession::ReceiveRequest() { + // Lock the session. + KScopedLightLock lk(m_lock); + + // Get the request and client thread. + // KSessionRequest *request; + KThread* client_thread; + + { + KScopedSchedulerLock sl{kernel}; + + // Ensure that we can service the request. + R_UNLESS(!parent->IsClientClosed(), ResultSessionClosed); + + // Ensure we aren't already servicing a request. + R_UNLESS(m_current_thread_request == nullptr, ResultNotFound); + + // Ensure we have a request to service. + R_UNLESS(!m_thread_request_list.empty(), ResultNotFound); + + // Pop the first request from the list. + client_thread = m_thread_request_list.front(); + m_thread_request_list.pop_front(); + + // Get the thread for the request. + R_UNLESS(client_thread != nullptr, ResultSessionClosed); + + // Open the client thread. + client_thread->Open(); + } + + // SCOPE_EXIT({ client_thread->Close(); }); + + // Set the request as our current. + m_current_thread_request = client_thread; + + // Receive the message. + Core::Memory::Memory& memory{kernel.System().Memory()}; + KThread* server_thread{GetCurrentThreadPointer(kernel)}; + UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess()); + + auto* src_msg_buffer = memory.GetPointer(client_thread->GetTLSAddress()); + auto* dst_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress()); + std::memcpy(dst_msg_buffer, src_msg_buffer, MessageBufferSize); + + // We succeeded. + return ResultSuccess; +} + +void KServerSession::CleanupRequests() { + KScopedLightLock lk(m_lock); + + // Clean up any pending requests. + while (true) { + // Get the next request. + // KSessionRequest *request = nullptr; + KThread* client_thread = nullptr; + { + KScopedSchedulerLock sl{kernel}; + + if (m_current_thread_request) { + // Choose the current request if we have one. + client_thread = m_current_thread_request; + m_current_thread_request = nullptr; + } else if (!m_thread_request_list.empty()) { + // Pop the request from the front of the list. + client_thread = m_thread_request_list.front(); + m_thread_request_list.pop_front(); + } + } + + // If there's no request, we're done. + if (client_thread == nullptr) { + break; + } + + // Close a reference to the request once it's cleaned up. + SCOPE_EXIT({ client_thread->Close(); }); + + // Extract relevant information from the request. + // const uintptr_t client_message = request->GetAddress(); + // const size_t client_buffer_size = request->GetSize(); + // KThread *client_thread = request->GetThread(); + // KEvent *event = request->GetEvent(); + + // KProcess *server_process = request->GetServerProcess(); + // KProcess *client_process = (client_thread != nullptr) ? + // client_thread->GetOwnerProcess() : nullptr; + // KProcessPageTable *client_page_table = (client_process != nullptr) ? + // &client_process->GetPageTable() : nullptr; + + // Cleanup the mappings. + // Result result = CleanupMap(request, server_process, client_page_table); + + // If there's a client thread, update it. + if (client_thread != nullptr) { + // End the client thread's wait. + KScopedSchedulerLock sl{kernel}; + + if (!client_thread->IsTerminationRequested()) { + client_thread->EndWait(ResultSessionClosed); + } + } + } } } // namespace Kernel diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h index 6d0821945..748d52826 100644 --- a/src/core/hle/kernel/k_server_session.h +++ b/src/core/hle/kernel/k_server_session.h @@ -3,6 +3,7 @@ #pragma once +#include <list> #include <memory> #include <string> #include <utility> @@ -10,6 +11,7 @@ #include <boost/intrusive/list.hpp> #include "core/hle/kernel/hle_ipc.h" +#include "core/hle/kernel/k_light_lock.h" #include "core/hle/kernel/k_synchronization_object.h" #include "core/hle/result.h" @@ -59,25 +61,15 @@ public: void OnClientClosed(); void ClientConnected(SessionRequestHandlerPtr handler) { - manager->SetSessionHandler(std::move(handler)); + if (manager) { + manager->SetSessionHandler(std::move(handler)); + } } void ClientDisconnected() { manager = nullptr; } - /** - * Handle a sync request from the emulated application. - * - * @param thread Thread that initiated the request. - * @param memory Memory context to handle the sync request under. - * @param core_timing Core timing context to schedule the request event under. - * - * @returns Result from the operation. - */ - Result HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory, - Core::Timing::CoreTiming& core_timing); - /// Adds a new domain request handler to the collection of request handlers within /// this ServerSession instance. void AppendDomainHandler(SessionRequestHandlerPtr handler); @@ -88,7 +80,7 @@ public: /// Returns true if the session has been converted to a domain, otherwise False bool IsDomain() const { - return manager->IsDomain(); + return manager && manager->IsDomain(); } /// Converts the session to a domain at the end of the current command @@ -101,7 +93,15 @@ public: return manager; } + /// TODO: flesh these out to match the real kernel + Result OnRequest(); + Result SendReply(); + Result ReceiveRequest(); + private: + /// Frees up waiting client sessions when this server session is about to die + void CleanupRequests(); + /// Queues a sync request from the emulated application. Result QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory); @@ -112,7 +112,7 @@ private: /// object handle. Result HandleDomainSyncRequest(Kernel::HLERequestContext& context); - /// This session's HLE request handlers + /// This session's HLE request handlers; if nullptr, this is not an HLE server std::shared_ptr<SessionRequestManager> manager; /// When set to True, converts the session to a domain at the end of the command @@ -120,6 +120,13 @@ private: /// KSession that owns this KServerSession KSession* parent{}; + + /// List of threads which are pending a reply. + /// FIXME: KSessionRequest + std::list<KThread*> m_thread_request_list; + KThread* m_current_thread_request{}; + + KLightLock m_lock; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_writable_event.cpp b/src/core/hle/kernel/k_writable_event.cpp deleted file mode 100644 index ff88c5acd..000000000 --- a/src/core/hle/kernel/k_writable_event.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/kernel/k_writable_event.h" - -namespace Kernel { - -KWritableEvent::KWritableEvent(KernelCore& kernel_) - : KAutoObjectWithSlabHeapAndContainer{kernel_} {} - -KWritableEvent::~KWritableEvent() = default; - -void KWritableEvent::Initialize(KEvent* parent_event_, std::string&& name_) { - parent = parent_event_; - name = std::move(name_); - parent->GetReadableEvent().Open(); -} - -Result KWritableEvent::Signal() { - return parent->GetReadableEvent().Signal(); -} - -Result KWritableEvent::Clear() { - return parent->GetReadableEvent().Clear(); -} - -void KWritableEvent::Destroy() { - // Close our references. - parent->GetReadableEvent().Close(); - parent->Close(); -} - -} // namespace Kernel diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h deleted file mode 100644 index 3fd0c7d0a..000000000 --- a/src/core/hle/kernel/k_writable_event.h +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/kernel/k_auto_object.h" -#include "core/hle/kernel/slab_helpers.h" -#include "core/hle/result.h" - -namespace Kernel { - -class KernelCore; -class KEvent; - -class KWritableEvent final - : public KAutoObjectWithSlabHeapAndContainer<KWritableEvent, KAutoObjectWithList> { - KERNEL_AUTOOBJECT_TRAITS(KWritableEvent, KAutoObject); - -public: - explicit KWritableEvent(KernelCore& kernel_); - ~KWritableEvent() override; - - void Destroy() override; - - static void PostDestroy([[maybe_unused]] uintptr_t arg) {} - - void Initialize(KEvent* parent_, std::string&& name_); - Result Signal(); - Result Clear(); - - KEvent* GetParent() const { - return parent; - } - -private: - KEvent* parent{}; -}; - -} // namespace Kernel diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index bcf016a97..0847cbcbf 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -52,7 +52,6 @@ class KThread; class KThreadLocalPage; class KTransferMemory; class KWorkerTaskManager; -class KWritableEvent; class KCodeMemory; class PhysicalCore; class ServiceThread; @@ -345,8 +344,6 @@ public: 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, KWritableEvent>) { - return slab_heap_container->writeable_event; } else if constexpr (std::is_same_v<T, KCodeMemory>) { return slab_heap_container->code_memory; } else if constexpr (std::is_same_v<T, KPageBuffer>) { @@ -412,7 +409,6 @@ private: KSlabHeap<KSharedMemoryInfo> shared_memory_info; KSlabHeap<KThread> thread; KSlabHeap<KTransferMemory> transfer_memory; - KSlabHeap<KWritableEvent> writeable_event; KSlabHeap<KCodeMemory> code_memory; KSlabHeap<KPageBuffer> page_buffer; KSlabHeap<KThreadLocalPage> thread_local_page; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 27e5a805d..1d145ea91 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -29,12 +29,12 @@ #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_session.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_synchronization_object.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_thread_queue.h" #include "core/hle/kernel/k_transfer_memory.h" -#include "core/hle/kernel/k_writable_event.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/svc.h" @@ -256,6 +256,93 @@ static Result UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u3 return UnmapMemory(system, dst_addr, src_addr, size); } +template <typename T> +Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, u64 name) { + auto& process = *system.CurrentProcess(); + auto& handle_table = process.GetHandleTable(); + + // Declare the session we're going to allocate. + T* session; + + // Reserve a new session from the process resource limit. + // FIXME: LimitableResource_SessionCountMax + KScopedResourceReservation session_reservation(&process, LimitableResource::Sessions); + if (session_reservation.Succeeded()) { + session = T::Create(system.Kernel()); + } else { + return ResultLimitReached; + + // // We couldn't reserve a session. Check that we support dynamically expanding the + // // resource limit. + // R_UNLESS(process.GetResourceLimit() == + // &system.Kernel().GetSystemResourceLimit(), ResultLimitReached); + // R_UNLESS(KTargetSystem::IsDynamicResourceLimitsEnabled(), ResultLimitReached()); + + // // Try to allocate a session from unused slab memory. + // session = T::CreateFromUnusedSlabMemory(); + // R_UNLESS(session != nullptr, ResultLimitReached); + // ON_RESULT_FAILURE { session->Close(); }; + + // // If we're creating a KSession, we want to add two KSessionRequests to the heap, to + // // prevent request exhaustion. + // // NOTE: Nintendo checks if session->DynamicCast<KSession *>() != nullptr, but there's + // // no reason to not do this statically. + // if constexpr (std::same_as<T, KSession>) { + // for (size_t i = 0; i < 2; i++) { + // KSessionRequest* request = KSessionRequest::CreateFromUnusedSlabMemory(); + // R_UNLESS(request != nullptr, ResultLimitReached); + // request->Close(); + // } + // } + + // We successfully allocated a session, so add the object we allocated to the resource + // limit. + // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::Sessions, 1); + } + + // Check that we successfully created a session. + R_UNLESS(session != nullptr, ResultOutOfResource); + + // Initialize the session. + session->Initialize(nullptr, fmt::format("{}", name)); + + // Commit the session reservation. + session_reservation.Commit(); + + // Ensure that we clean up the session (and its only references are handle table) on function + // end. + SCOPE_EXIT({ + session->GetClientSession().Close(); + session->GetServerSession().Close(); + }); + + // Register the session. + T::Register(system.Kernel(), session); + + // Add the server session to the handle table. + R_TRY(handle_table.Add(out_server, &session->GetServerSession())); + + // Add the client session to the handle table. + const auto result = handle_table.Add(out_client, &session->GetClientSession()); + + if (!R_SUCCEEDED(result)) { + // Ensure that we maintaing a clean handle state on exit. + handle_table.Remove(*out_server); + } + + return result; +} + +static Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, + u32 is_light, u64 name) { + if (is_light) { + // return CreateSession<KLightSession>(system, out_server, out_client, name); + return ResultUnknown; + } else { + return CreateSession<KSession>(system, out_server, out_client, name); + } +} + /// Connect to an OS service given the port name, returns the handle to the port to out static Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address) { auto& memory = system.Memory(); @@ -295,7 +382,8 @@ static Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_n // Create a session. KClientSession* session{}; - R_TRY(port->CreateSession(std::addressof(session))); + R_TRY(port->CreateSession(std::addressof(session), + std::make_shared<SessionRequestManager>(kernel))); port->Close(); // Register the session in the table, close the extra reference. @@ -313,7 +401,7 @@ static Result ConnectToNamedPort32(Core::System& system, Handle* out_handle, return ConnectToNamedPort(system, out_handle, port_name_address); } -/// Makes a blocking IPC call to an OS service. +/// Makes a blocking IPC call to a service. static Result SendSyncRequest(Core::System& system, Handle handle) { auto& kernel = system.Kernel(); @@ -327,22 +415,75 @@ static Result SendSyncRequest(Core::System& system, Handle handle) { LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); - { - KScopedSchedulerLock lock(kernel); - - // This is a synchronous request, so we should wait for our request to complete. - GetCurrentThread(kernel).BeginWait(std::addressof(wait_queue)); - GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); - session->SendSyncRequest(&GetCurrentThread(kernel), system.Memory(), system.CoreTiming()); - } - - return GetCurrentThread(kernel).GetWaitResult(); + return session->SendSyncRequest(); } static Result SendSyncRequest32(Core::System& system, Handle handle) { return SendSyncRequest(system, handle); } +static Result ReplyAndReceive(Core::System& system, s32* out_index, Handle* handles, + s32 num_handles, Handle reply_target, s64 timeout_ns) { + auto& kernel = system.Kernel(); + auto& handle_table = GetCurrentThread(kernel).GetOwnerProcess()->GetHandleTable(); + + // Convert handle list to object table. + std::vector<KSynchronizationObject*> objs(num_handles); + R_UNLESS( + handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, num_handles), + ResultInvalidHandle); + + // Ensure handles are closed when we're done. + SCOPE_EXIT({ + for (auto i = 0; i < num_handles; ++i) { + objs[i]->Close(); + } + }); + + // Reply to the target, if one is specified. + if (reply_target != InvalidHandle) { + KScopedAutoObject session = handle_table.GetObject<KServerSession>(reply_target); + R_UNLESS(session.IsNotNull(), ResultInvalidHandle); + + // If we fail to reply, we want to set the output index to -1. + // ON_RESULT_FAILURE { *out_index = -1; }; + + // Send the reply. + // R_TRY(session->SendReply()); + + Result rc = session->SendReply(); + if (!R_SUCCEEDED(rc)) { + *out_index = -1; + return rc; + } + } + + // Wait for a message. + while (true) { + // Wait for an object. + s32 index; + Result result = KSynchronizationObject::Wait(kernel, &index, objs.data(), + static_cast<s32>(objs.size()), timeout_ns); + if (result == ResultTimedOut) { + return result; + } + + // Receive the request. + if (R_SUCCEEDED(result)) { + KServerSession* session = objs[index]->DynamicCast<KServerSession*>(); + if (session != nullptr) { + result = session->ReceiveRequest(); + if (result == ResultNotFound) { + continue; + } + } + } + + *out_index = index; + return result; + } +} + /// Get the ID for the specified thread. static Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) { // Get the thread from its handle. @@ -2303,11 +2444,11 @@ static Result SignalEvent(Core::System& system, Handle event_handle) { // Get the current handle table. const KHandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - // Get the writable event. - KScopedAutoObject writable_event = handle_table.GetObject<KWritableEvent>(event_handle); - R_UNLESS(writable_event.IsNotNull(), ResultInvalidHandle); + // Get the event. + KScopedAutoObject event = handle_table.GetObject<KEvent>(event_handle); + R_UNLESS(event.IsNotNull(), ResultInvalidHandle); - return writable_event->Signal(); + return event->Signal(); } static Result SignalEvent32(Core::System& system, Handle event_handle) { @@ -2322,9 +2463,9 @@ static Result ClearEvent(Core::System& system, Handle event_handle) { // Try to clear the writable event. { - KScopedAutoObject writable_event = handle_table.GetObject<KWritableEvent>(event_handle); - if (writable_event.IsNotNull()) { - return writable_event->Clear(); + KScopedAutoObject event = handle_table.GetObject<KEvent>(event_handle); + if (event.IsNotNull()) { + return event->Clear(); } } @@ -2362,24 +2503,24 @@ static Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_r R_UNLESS(event != nullptr, ResultOutOfResource); // Initialize the event. - event->Initialize("CreateEvent", kernel.CurrentProcess()); + event->Initialize(kernel.CurrentProcess()); // Commit the thread reservation. event_reservation.Commit(); // Ensure that we clean up the event (and its only references are handle table) on function end. SCOPE_EXIT({ - event->GetWritableEvent().Close(); event->GetReadableEvent().Close(); + event->Close(); }); // Register the event. KEvent::Register(kernel, event); - // Add the writable event to the handle table. - R_TRY(handle_table.Add(out_write, std::addressof(event->GetWritableEvent()))); + // Add the event to the handle table. + R_TRY(handle_table.Add(out_write, event)); - // Add the writable event to the handle table. + // Ensure that we maintaing a clean handle state on exit. auto handle_guard = SCOPE_GUARD({ handle_table.Remove(*out_write); }); // Add the readable event to the handle table. @@ -2860,10 +3001,10 @@ static const FunctionDef SVC_Table_64[] = { {0x3D, SvcWrap64<ChangeKernelTraceState>, "ChangeKernelTraceState"}, {0x3E, nullptr, "Unknown3e"}, {0x3F, nullptr, "Unknown3f"}, - {0x40, nullptr, "CreateSession"}, + {0x40, SvcWrap64<CreateSession>, "CreateSession"}, {0x41, nullptr, "AcceptSession"}, {0x42, nullptr, "ReplyAndReceiveLight"}, - {0x43, nullptr, "ReplyAndReceive"}, + {0x43, SvcWrap64<ReplyAndReceive>, "ReplyAndReceive"}, {0x44, nullptr, "ReplyAndReceiveWithUserBuffer"}, {0x45, SvcWrap64<CreateEvent>, "CreateEvent"}, {0x46, nullptr, "MapIoRegion"}, diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 4bc49087e..272c54cf7 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h @@ -8,6 +8,7 @@ #include "core/core.h" #include "core/hle/kernel/svc_types.h" #include "core/hle/result.h" +#include "core/memory.h" namespace Kernel { @@ -346,6 +347,37 @@ void SvcWrap64(Core::System& system) { FuncReturn(system, retval); } +// Used by CreateSession +template <Result func(Core::System&, Handle*, Handle*, u32, u64)> +void SvcWrap64(Core::System& system) { + Handle param_1 = 0; + Handle param_2 = 0; + const u32 retval = func(system, ¶m_1, ¶m_2, static_cast<u32>(Param(system, 2)), + static_cast<u32>(Param(system, 3))) + .raw; + + system.CurrentArmInterface().SetReg(1, param_1); + system.CurrentArmInterface().SetReg(2, param_2); + FuncReturn(system, retval); +} + +// Used by ReplyAndReceive +template <Result func(Core::System&, s32*, Handle*, s32, Handle, s64)> +void SvcWrap64(Core::System& system) { + s32 param_1 = 0; + s32 num_handles = static_cast<s32>(Param(system, 2)); + + std::vector<Handle> handles(num_handles); + system.Memory().ReadBlock(Param(system, 1), handles.data(), num_handles * sizeof(Handle)); + + const u32 retval = func(system, ¶m_1, handles.data(), num_handles, + static_cast<s32>(Param(system, 3)), static_cast<s64>(Param(system, 4))) + .raw; + + system.CurrentArmInterface().SetReg(1, param_1); + FuncReturn(system, retval); +} + // Used by WaitForAddress template <Result func(Core::System&, u64, Svc::ArbitrationType, s32, s64)> void SvcWrap64(Core::System& system) { diff --git a/src/core/hle/service/acc/async_context.cpp b/src/core/hle/service/acc/async_context.cpp index c85b2e43a..713689d8f 100644 --- a/src/core/hle/service/acc/async_context.cpp +++ b/src/core/hle/service/acc/async_context.cpp @@ -64,7 +64,7 @@ void IAsyncContext::GetResult(Kernel::HLERequestContext& ctx) { void IAsyncContext::MarkComplete() { is_complete.store(true); - completion_event->GetWritableEvent().Signal(); + completion_event->Signal(); } } // namespace Service::Account diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 6fb7e198e..e55233054 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -316,7 +316,7 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv accumulated_suspended_tick_changed_event = service_context.CreateEvent("ISelfController:AccumulatedSuspendedTickChangedEvent"); - accumulated_suspended_tick_changed_event->GetWritableEvent().Signal(); + accumulated_suspended_tick_changed_event->Signal(); } ISelfController::~ISelfController() { @@ -378,7 +378,7 @@ void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) { void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); - launchable_event->GetWritableEvent().Signal(); + launchable_event->Signal(); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); @@ -618,18 +618,18 @@ Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() { void AppletMessageQueue::PushMessage(AppletMessage msg) { messages.push(msg); - on_new_message->GetWritableEvent().Signal(); + on_new_message->Signal(); } AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { if (messages.empty()) { - on_new_message->GetWritableEvent().Clear(); + on_new_message->Clear(); return AppletMessage::None; } auto msg = messages.front(); messages.pop(); if (messages.empty()) { - on_new_message->GetWritableEvent().Clear(); + on_new_message->Clear(); } return msg; } @@ -653,7 +653,7 @@ void AppletMessageQueue::FocusStateChanged() { void AppletMessageQueue::OperationModeChanged() { PushMessage(AppletMessage::OperationModeChanged); PushMessage(AppletMessage::PerformanceModeChanged); - on_operation_mode_changed->GetWritableEvent().Signal(); + on_operation_mode_changed->Signal(); } ICommonStateGetter::ICommonStateGetter(Core::System& system_, diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index b5b8e4cad..7062df21c 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -65,7 +65,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() { auto out = std::move(out_channel.front()); out_channel.pop_front(); - pop_out_data_event->GetWritableEvent().Clear(); + pop_out_data_event->Clear(); return out; } @@ -84,7 +84,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() { auto out = std::move(out_interactive_channel.front()); out_interactive_channel.pop_front(); - pop_interactive_out_data_event->GetWritableEvent().Clear(); + pop_interactive_out_data_event->Clear(); return out; } @@ -103,7 +103,7 @@ void AppletDataBroker::PushNormalDataFromGame(std::shared_ptr<IStorage>&& storag void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) { out_channel.emplace_back(std::move(storage)); - pop_out_data_event->GetWritableEvent().Signal(); + pop_out_data_event->Signal(); } void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) { @@ -112,11 +112,11 @@ void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& s void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) { out_interactive_channel.emplace_back(std::move(storage)); - pop_interactive_out_data_event->GetWritableEvent().Signal(); + pop_interactive_out_data_event->Signal(); } void AppletDataBroker::SignalStateChanged() { - state_changed_event->GetWritableEvent().Signal(); + state_changed_event->Signal(); switch (applet_mode) { case LibraryAppletMode::AllForeground: diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 6fb07c37d..60c30cd5b 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -239,7 +239,7 @@ public: }; RegisterHandlers(functions); - event->GetWritableEvent().Signal(); + event->Signal(); } ~IAudioDevice() override { @@ -325,7 +325,7 @@ private: void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "(STUBBED) called"); - event->GetWritableEvent().Signal(); + event->Signal(); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/bcat/backend/backend.cpp b/src/core/hle/service/bcat/backend/backend.cpp index cd0b405ff..847f76987 100644 --- a/src/core/hle/service/bcat/backend/backend.cpp +++ b/src/core/hle/service/bcat/backend/backend.cpp @@ -82,7 +82,7 @@ void ProgressServiceBackend::FinishDownload(Result result) { } void ProgressServiceBackend::SignalUpdate() { - update_event->GetWritableEvent().Signal(); + update_event->Signal(); } Backend::Backend(DirectoryGetter getter) : dir_getter(std::move(getter)) {} diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index f8972ec7a..98e4f2af7 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -16,7 +16,6 @@ #include "core/hid/hid_core.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" -#include "core/hle/kernel/k_writable_event.h" #include "core/hle/service/hid/controllers/npad.h" #include "core/hle/service/hid/errors.h" #include "core/hle/service/kernel_helpers.h" @@ -167,7 +166,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { const auto& battery_level = controller.device->GetBattery(); auto* shared_memory = controller.shared_memory; if (controller_type == Core::HID::NpadStyleIndex::None) { - controller.styleset_changed_event->GetWritableEvent().Signal(); + controller.styleset_changed_event->Signal(); return; } @@ -1033,7 +1032,7 @@ Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::Npad void Controller_NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const { const auto& controller = GetControllerFromNpadIdType(npad_id); - controller.styleset_changed_event->GetWritableEvent().Signal(); + controller.styleset_changed_event->Signal(); } void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller, diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp index 575d4e626..4564ea1e2 100644 --- a/src/core/hle/service/hid/controllers/palma.cpp +++ b/src/core/hle/service/hid/controllers/palma.cpp @@ -73,7 +73,7 @@ Result Controller_Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle, operation.operation = PalmaOperationType::PlayActivity; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->GetWritableEvent().Signal(); + operation_complete_event->Signal(); return ResultSuccess; } @@ -93,7 +93,7 @@ Result Controller_Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) { operation.operation = PalmaOperationType::ReadStep; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->GetWritableEvent().Signal(); + operation_complete_event->Signal(); return ResultSuccess; } @@ -122,7 +122,7 @@ Result Controller_Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle operation.operation = PalmaOperationType::ReadUniqueCode; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->GetWritableEvent().Signal(); + operation_complete_event->Signal(); return ResultSuccess; } @@ -133,7 +133,7 @@ Result Controller_Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& operation.operation = PalmaOperationType::SetUniqueCodeInvalid; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->GetWritableEvent().Signal(); + operation_complete_event->Signal(); return ResultSuccess; } @@ -147,7 +147,7 @@ Result Controller_Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandl operation.operation = PalmaOperationType::WriteRgbLedPatternEntry; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->GetWritableEvent().Signal(); + operation_complete_event->Signal(); return ResultSuccess; } @@ -159,7 +159,7 @@ Result Controller_Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle operation.operation = PalmaOperationType::WriteWaveEntry; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->GetWritableEvent().Signal(); + operation_complete_event->Signal(); return ResultSuccess; } @@ -172,7 +172,7 @@ Result Controller_Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnec operation.operation = PalmaOperationType::ReadDataBaseIdentificationVersion; operation.result = PalmaResultSuccess; operation.data[0] = {}; - operation_complete_event->GetWritableEvent().Signal(); + operation_complete_event->Signal(); return ResultSuccess; } @@ -185,7 +185,7 @@ Result Controller_Palma::GetPalmaDataBaseIdentificationVersion( operation.result = PalmaResultSuccess; operation.data = {}; operation.data[0] = static_cast<u8>(database_id_version); - operation_complete_event->GetWritableEvent().Signal(); + operation_complete_event->Signal(); return ResultSuccess; } diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 46bad7871..79375bd2f 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -2118,7 +2118,7 @@ void Hid::WritePalmaWaveEntry(Kernel::HLERequestContext& ctx) { ASSERT_MSG(t_mem->GetSize() == 0x3000, "t_mem has incorrect size"); LOG_WARNING(Service_HID, - "(STUBBED) called, connection_handle={}, wave_set={}, unkown={}, " + "(STUBBED) called, connection_handle={}, wave_set={}, unknown={}, " "t_mem_handle=0x{:08X}, t_mem_size={}, size={}", connection_handle.npad_id, wave_set, unknown, t_mem_handle, t_mem_size, size); diff --git a/src/core/hle/service/hid/hidbus/ringcon.cpp b/src/core/hle/service/hid/hidbus/ringcon.cpp index ad223d649..57f1a2a26 100644 --- a/src/core/hle/service/hid/hidbus/ringcon.cpp +++ b/src/core/hle/service/hid/hidbus/ringcon.cpp @@ -131,12 +131,12 @@ bool RingController::SetCommand(const std::vector<u8>& data) { case RingConCommands::ReadRepCount: case RingConCommands::ReadTotalPushCount: ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); - send_command_async_event->GetWritableEvent().Signal(); + send_command_async_event->Signal(); return true; case RingConCommands::ResetRepCount: ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); total_rep_count = 0; - send_command_async_event->GetWritableEvent().Signal(); + send_command_async_event->Signal(); return true; case RingConCommands::SaveCalData: { ASSERT_MSG(data.size() == 0x14, "data.size is not 0x14 bytes"); @@ -144,14 +144,14 @@ bool RingController::SetCommand(const std::vector<u8>& data) { SaveCalData save_info{}; std::memcpy(&save_info, data.data(), sizeof(SaveCalData)); user_calibration = save_info.calibration; - send_command_async_event->GetWritableEvent().Signal(); + send_command_async_event->Signal(); return true; } default: LOG_ERROR(Service_HID, "Command not implemented {}", command); command = RingConCommands::Error; // Signal a reply to avoid softlocking the game - send_command_async_event->GetWritableEvent().Signal(); + send_command_async_event->Signal(); return false; } } diff --git a/src/core/hle/service/hid/irsensor/pointing_processor.h b/src/core/hle/service/hid/irsensor/pointing_processor.h index cf4930794..d63423aff 100644 --- a/src/core/hle/service/hid/irsensor/pointing_processor.h +++ b/src/core/hle/service/hid/irsensor/pointing_processor.h @@ -37,10 +37,10 @@ private: u8 pointing_status; INSERT_PADDING_BYTES(3); u32 unknown; - float unkown_float1; + float unknown_float1; float position_x; float position_y; - float unkown_float2; + float unknown_float2; Core::IrSensor::IrsRect window_of_interest; }; static_assert(sizeof(PointingProcessorMarkerData) == 0x20, diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp index 3e317367b..af133af93 100644 --- a/src/core/hle/service/kernel_helpers.cpp +++ b/src/core/hle/service/kernel_helpers.cpp @@ -9,7 +9,6 @@ #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_scoped_resource_reservation.h" -#include "core/hle/kernel/k_writable_event.h" #include "core/hle/service/kernel_helpers.h" namespace Service::KernelHelpers { @@ -46,7 +45,7 @@ Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { } // Initialize the event. - event->Initialize(std::move(name), process); + event->Initialize(process); // Commit the thread reservation. event_reservation.Commit(); @@ -59,7 +58,7 @@ Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { void ServiceContext::CloseEvent(Kernel::KEvent* event) { event->GetReadableEvent().Close(); - event->GetWritableEvent().Close(); + event->Close(); } } // namespace Service::KernelHelpers diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp index ea3e7e55a..6df563136 100644 --- a/src/core/hle/service/ldn/ldn.cpp +++ b/src/core/hle/service/ldn/ldn.cpp @@ -165,7 +165,7 @@ public: } void OnEventFired() { - state_change_event->GetWritableEvent().Signal(); + state_change_event->Signal(); } void GetState(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp index ec895ac01..76f8a267a 100644 --- a/src/core/hle/service/nfp/nfp_device.cpp +++ b/src/core/hle/service/nfp/nfp_device.cpp @@ -58,7 +58,7 @@ NfpDevice::~NfpDevice() { void NfpDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { if (type == Core::HID::ControllerTriggerType::Connected || type == Core::HID::ControllerTriggerType::Disconnected) { - availability_change_event->GetWritableEvent().Signal(); + availability_change_event->Signal(); return; } @@ -100,7 +100,7 @@ bool NfpDevice::LoadAmiibo(std::span<const u8> data) { device_state = DeviceState::TagFound; deactivate_event->GetReadableEvent().Clear(); - activate_event->GetWritableEvent().Signal(); + activate_event->Signal(); return true; } @@ -115,7 +115,7 @@ void NfpDevice::CloseAmiibo() { encrypted_tag_data = {}; tag_data = {}; activate_event->GetReadableEvent().Clear(); - deactivate_event->GetWritableEvent().Signal(); + deactivate_event->Signal(); } Kernel::KReadableEvent& NfpDevice::GetActivateEvent() const { diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index b2bb7426d..5a8a91e0b 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp @@ -328,7 +328,7 @@ private: void StartTask(Kernel::HLERequestContext& ctx) { // No need to connect to the internet, just finish the task straight away. LOG_DEBUG(Service_NIM, "called"); - finished_event->GetWritableEvent().Signal(); + finished_event->Signal(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -350,7 +350,7 @@ private: void Cancel(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_NIM, "called"); - finished_event->GetWritableEvent().Clear(); + finished_event->Clear(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index f7318c3cb..f59a1a63d 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -8,6 +8,7 @@ #include "core/file_sys/patch_manager.h" #include "core/file_sys/vfs.h" #include "core/hle/ipc_helpers.h" +#include "core/hle/service/glue/glue_manager.h" #include "core/hle/service/ns/errors.h" #include "core/hle/service/ns/iplatform_service_manager.h" #include "core/hle/service/ns/language.h" @@ -581,7 +582,7 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "GetApplicationControlData"}, + {0, &IReadOnlyApplicationControlDataInterface::GetApplicationControlData, "GetApplicationControlData"}, {1, nullptr, "GetApplicationDesiredLanguage"}, {2, nullptr, "ConvertApplicationLanguageToLanguageCode"}, {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, @@ -594,6 +595,33 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default; +void IReadOnlyApplicationControlDataInterface::GetApplicationControlData( + Kernel::HLERequestContext& ctx) { + enum class ApplicationControlSource : u8 { + CacheOnly, + Storage, + StorageOnly, + }; + + struct RequestParameters { + ApplicationControlSource source; + u64 application_id; + }; + static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size."); + + IPC::RequestParser rp{ctx}; + const auto parameters{rp.PopRaw<RequestParameters>()}; + const auto nacp_data{system.GetARPManager().GetControlProperty(parameters.application_id)}; + const auto result = nacp_data ? ResultSuccess : ResultUnknown; + + if (nacp_data) { + ctx.WriteBuffer(nacp_data->data(), nacp_data->size()); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} { // clang-format off static const FunctionInfo functions[] = { diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index 4dc191518..9c18e935c 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h @@ -78,6 +78,9 @@ class IReadOnlyApplicationControlDataInterface final public: explicit IReadOnlyApplicationControlDataInterface(Core::System& system_); ~IReadOnlyApplicationControlDataInterface() override; + +private: + void GetApplicationControlData(Kernel::HLERequestContext& ctx); }; class NS final : public ServiceFramework<NS> { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 5bee4a3d3..eee11fab8 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -12,7 +12,6 @@ #include "common/scope_exit.h" #include "core/core.h" #include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_writable_event.h" #include "core/hle/service/nvdrv/core/container.h" #include "core/hle/service/nvdrv/core/syncpoint_manager.h" #include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" @@ -206,7 +205,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector auto& event_ = events[slot]; if (event_.status.exchange(EventState::Signalling, std::memory_order_acq_rel) == EventState::Waiting) { - event_.kevent->GetWritableEvent().Signal(); + event_.kevent->Signal(); } event_.status.store(EventState::Signalled, std::memory_order_release); }); @@ -306,7 +305,7 @@ NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::v } event.fails++; event.status.store(EventState::Cancelled, std::memory_order_release); - event.kevent->GetWritableEvent().Clear(); + event.kevent->Clear(); return NvResult::Success; } diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 5e7b7468f..9d9924395 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -8,7 +8,6 @@ #include "core/core.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_writable_event.h" #include "core/hle/service/nvdrv/core/container.h" #include "core/hle/service/nvdrv/devices/nvdevice.h" #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h index cd58a4f35..5ac06ee30 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.h +++ b/src/core/hle/service/nvdrv/nvdrv_interface.h @@ -7,10 +7,6 @@ #include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/service.h" -namespace Kernel { -class KWritableEvent; -} - namespace Service::Nvidia { class NVDRV final : public ServiceFramework<NVDRV> { diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp index d4ab23a10..77ddbb6ef 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp @@ -11,7 +11,6 @@ #include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" -#include "core/hle/kernel/k_writable_event.h" #include "core/hle/kernel/kernel.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/nvdrv/core/nvmap.h" @@ -110,7 +109,7 @@ Status BufferQueueProducer::SetBufferCount(s32 buffer_count) { core->override_max_buffer_count = buffer_count; core->SignalDequeueCondition(); - buffer_wait_event->GetWritableEvent().Signal(); + buffer_wait_event->Signal(); listener = core->consumer_listener; } @@ -623,7 +622,7 @@ void BufferQueueProducer::CancelBuffer(s32 slot, const Fence& fence) { slots[slot].fence = fence; core->SignalDequeueCondition(); - buffer_wait_event->GetWritableEvent().Signal(); + buffer_wait_event->Signal(); } Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) { @@ -753,7 +752,7 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) { core->connected_producer_listener = nullptr; core->connected_api = NativeWindowApi::NoConnectedApi; core->SignalDequeueCondition(); - buffer_wait_event->GetWritableEvent().Signal(); + buffer_wait_event->Signal(); listener = core->consumer_listener; } else { LOG_ERROR(Service_NVFlinger, "still connected to another api (cur = {} req = {})", @@ -802,7 +801,7 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, } core->SignalDequeueCondition(); - buffer_wait_event->GetWritableEvent().Signal(); + buffer_wait_event->Signal(); return Status::NoError; } diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.h b/src/core/hle/service/nvflinger/buffer_queue_producer.h index 0ba03a568..7526bf8ec 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvflinger/buffer_queue_producer.h @@ -24,7 +24,6 @@ namespace Kernel { class KernelCore; class KEvent; class KReadableEvent; -class KWritableEvent; } // namespace Kernel namespace Service::KernelHelpers { diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index b62615de2..99509bc5b 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h @@ -25,7 +25,6 @@ struct EventType; namespace Kernel { class KReadableEvent; -class KWritableEvent; } // namespace Kernel namespace Service::Nvidia { diff --git a/src/core/hle/service/ptm/psm.cpp b/src/core/hle/service/ptm/psm.cpp index 2c31e9485..1ac97fe31 100644 --- a/src/core/hle/service/ptm/psm.cpp +++ b/src/core/hle/service/ptm/psm.cpp @@ -37,19 +37,19 @@ public: void SignalChargerTypeChanged() { if (should_signal && should_signal_charger_type) { - state_change_event->GetWritableEvent().Signal(); + state_change_event->Signal(); } } void SignalPowerSupplyChanged() { if (should_signal && should_signal_power_supply) { - state_change_event->GetWritableEvent().Signal(); + state_change_event->Signal(); } } void SignalBatteryVoltageStateChanged() { if (should_signal && should_signal_battery_voltage) { - state_change_event->GetWritableEvent().Signal(); + state_change_event->Signal(); } } diff --git a/src/core/hle/service/ptm/ts.cpp b/src/core/hle/service/ptm/ts.cpp index 65c3f135f..b1a0a5544 100644 --- a/src/core/hle/service/ptm/ts.cpp +++ b/src/core/hle/service/ptm/ts.cpp @@ -15,7 +15,7 @@ TS::TS(Core::System& system_) : ServiceFramework{system_, "ts"} { {0, nullptr, "GetTemperatureRange"}, {1, &TS::GetTemperature, "GetTemperature"}, {2, nullptr, "SetMeasurementMode"}, - {3, nullptr, "GetTemperatureMilliC"}, + {3, &TS::GetTemperatureMilliC, "GetTemperatureMilliC"}, {4, nullptr, "OpenSession"}, }; // clang-format on @@ -29,8 +29,6 @@ void TS::GetTemperature(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto location{rp.PopEnum<Location>()}; - LOG_WARNING(Service_HID, "(STUBBED) called. location={}", location); - const s32 temperature = location == Location::Internal ? 35 : 20; IPC::ResponseBuilder rb{ctx, 3}; @@ -38,4 +36,15 @@ void TS::GetTemperature(Kernel::HLERequestContext& ctx) { rb.Push(temperature); } +void TS::GetTemperatureMilliC(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto location{rp.PopEnum<Location>()}; + + const s32 temperature = location == Location::Internal ? 35000 : 20000; + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(temperature); +} + } // namespace Service::PTM diff --git a/src/core/hle/service/ptm/ts.h b/src/core/hle/service/ptm/ts.h index 39a734ef7..39d51847e 100644 --- a/src/core/hle/service/ptm/ts.h +++ b/src/core/hle/service/ptm/ts.h @@ -20,6 +20,7 @@ private: }; void GetTemperature(Kernel::HLERequestContext& ctx); + void GetTemperatureMilliC(Kernel::HLERequestContext& ctx); }; } // namespace Service::PTM diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp index 2a0b812c1..d7cea6aac 100644 --- a/src/core/hle/service/set/set_sys.cpp +++ b/src/core/hle/service/set/set_sys.cpp @@ -101,6 +101,81 @@ void SET_SYS::SetColorSetId(Kernel::HLERequestContext& ctx) { rb.Push(ResultSuccess); } +// FIXME: implement support for the real system_settings.ini + +template <typename T> +static std::vector<u8> ToBytes(const T& value) { + static_assert(std::is_trivially_copyable_v<T>); + + const auto* begin = reinterpret_cast<const u8*>(&value); + const auto* end = begin + sizeof(T); + + return std::vector<u8>(begin, end); +} + +using Settings = + std::map<std::string, std::map<std::string, std::vector<u8>, std::less<>>, std::less<>>; + +static Settings GetSettings() { + Settings ret; + + ret["hbloader"]["applet_heap_size"] = ToBytes(u64{0x0}); + ret["hbloader"]["applet_heap_reservation_size"] = ToBytes(u64{0x8600000}); + + return ret; +} + +void SET_SYS::GetSettingsItemValueSize(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_SET, "called"); + + // The category of the setting. This corresponds to the top-level keys of + // system_settings.ini. + const auto setting_category_buf{ctx.ReadBuffer(0)}; + const std::string setting_category{setting_category_buf.begin(), setting_category_buf.end()}; + + // The name of the setting. This corresponds to the second-level keys of + // system_settings.ini. + const auto setting_name_buf{ctx.ReadBuffer(1)}; + const std::string setting_name{setting_name_buf.begin(), setting_name_buf.end()}; + + auto settings{GetSettings()}; + u64 response_size{0}; + + if (settings.contains(setting_category) && settings[setting_category].contains(setting_name)) { + response_size = settings[setting_category][setting_name].size(); + } + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(response_size == 0 ? ResultUnknown : ResultSuccess); + rb.Push(response_size); +} + +void SET_SYS::GetSettingsItemValue(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_SET, "called"); + + // The category of the setting. This corresponds to the top-level keys of + // system_settings.ini. + const auto setting_category_buf{ctx.ReadBuffer(0)}; + const std::string setting_category{setting_category_buf.begin(), setting_category_buf.end()}; + + // The name of the setting. This corresponds to the second-level keys of + // system_settings.ini. + const auto setting_name_buf{ctx.ReadBuffer(1)}; + const std::string setting_name{setting_name_buf.begin(), setting_name_buf.end()}; + + auto settings{GetSettings()}; + Result response{ResultUnknown}; + + if (settings.contains(setting_category) && settings[setting_category].contains(setting_name)) { + auto setting_value = settings[setting_category][setting_name]; + ctx.WriteBuffer(setting_value.data(), setting_value.size()); + response = ResultSuccess; + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(response); +} + SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { // clang-format off static const FunctionInfo functions[] = { @@ -138,8 +213,8 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { {32, nullptr, "SetAccountNotificationSettings"}, {35, nullptr, "GetVibrationMasterVolume"}, {36, nullptr, "SetVibrationMasterVolume"}, - {37, nullptr, "GetSettingsItemValueSize"}, - {38, nullptr, "GetSettingsItemValue"}, + {37, &SET_SYS::GetSettingsItemValueSize, "GetSettingsItemValueSize"}, + {38, &SET_SYS::GetSettingsItemValue, "GetSettingsItemValue"}, {39, nullptr, "GetTvSettings"}, {40, nullptr, "SetTvSettings"}, {41, nullptr, "GetEdid"}, diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h index ac97772b7..258ef8c57 100644 --- a/src/core/hle/service/set/set_sys.h +++ b/src/core/hle/service/set/set_sys.h @@ -23,6 +23,8 @@ private: BasicBlack = 1, }; + void GetSettingsItemValueSize(Kernel::HLERequestContext& ctx); + void GetSettingsItemValue(Kernel::HLERequestContext& ctx); void GetFirmwareVersion(Kernel::HLERequestContext& ctx); void GetFirmwareVersion2(Kernel::HLERequestContext& ctx); void GetColorSetId(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 246c94623..48e70f93c 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -156,7 +156,8 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& // Create a new session. Kernel::KClientSession* session{}; - if (const auto result = port->GetClientPort().CreateSession(std::addressof(session)); + if (const auto result = port->GetClientPort().CreateSession( + std::addressof(session), std::make_shared<Kernel::SessionRequestManager>(kernel)); result.IsError()) { LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw); return result; diff --git a/src/core/hle/service/time/system_clock_context_update_callback.cpp b/src/core/hle/service/time/system_clock_context_update_callback.cpp index a649bed3a..cafc04ee7 100644 --- a/src/core/hle/service/time/system_clock_context_update_callback.cpp +++ b/src/core/hle/service/time/system_clock_context_update_callback.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/hle/kernel/k_writable_event.h" +#include "core/hle/kernel/k_event.h" #include "core/hle/service/time/errors.h" #include "core/hle/service/time/system_clock_context_update_callback.h" @@ -20,13 +20,13 @@ bool SystemClockContextUpdateCallback::NeedUpdate(const SystemClockContext& valu } void SystemClockContextUpdateCallback::RegisterOperationEvent( - std::shared_ptr<Kernel::KWritableEvent>&& writable_event) { - operation_event_list.emplace_back(std::move(writable_event)); + std::shared_ptr<Kernel::KEvent>&& event) { + operation_event_list.emplace_back(std::move(event)); } void SystemClockContextUpdateCallback::BroadcastOperationEvent() { - for (const auto& writable_event : operation_event_list) { - writable_event->Signal(); + for (const auto& event : operation_event_list) { + event->Signal(); } } diff --git a/src/core/hle/service/time/system_clock_context_update_callback.h b/src/core/hle/service/time/system_clock_context_update_callback.h index 9c6caf196..bf657acd9 100644 --- a/src/core/hle/service/time/system_clock_context_update_callback.h +++ b/src/core/hle/service/time/system_clock_context_update_callback.h @@ -9,7 +9,7 @@ #include "core/hle/service/time/clock_types.h" namespace Kernel { -class KWritableEvent; +class KEvent; } namespace Service::Time::Clock { @@ -24,7 +24,7 @@ public: bool NeedUpdate(const SystemClockContext& value) const; - void RegisterOperationEvent(std::shared_ptr<Kernel::KWritableEvent>&& writable_event); + void RegisterOperationEvent(std::shared_ptr<Kernel::KEvent>&& event); void BroadcastOperationEvent(); @@ -37,7 +37,7 @@ protected: private: bool has_context{}; - std::vector<std::shared_ptr<Kernel::KWritableEvent>> operation_event_list; + std::vector<std::shared_ptr<Kernel::KEvent>> operation_event_list; }; } // namespace Service::Time::Clock diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index 288aafaaf..8ef74f1f0 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp @@ -10,7 +10,6 @@ #include "core/core.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" -#include "core/hle/kernel/k_writable_event.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/nvdrv/core/container.h" #include "core/hle/service/nvflinger/buffer_item_consumer.h" @@ -74,7 +73,7 @@ Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() { } void Display::SignalVSyncEvent() { - vsync_event->GetWritableEvent().Signal(); + vsync_event->Signal(); } void Display::CreateLayer(u64 layer_id, u32 binder_id, diff --git a/src/core/hle/service/vi/vi_results.h b/src/core/hle/service/vi/vi_results.h index a46c247d2..22bac799f 100644 --- a/src/core/hle/service/vi/vi_results.h +++ b/src/core/hle/service/vi/vi_results.h @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + #include "core/hle/result.h" namespace Service::VI { |