From f565ea80f00e153607f15fcd864037606c1b7ebf Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Tue, 2 Apr 2019 12:30:03 -0400 Subject: [PATCH] HLE/IPC: HLEContext can memorize the client thread and use it for SleepClientThread This reduces the boilerplate that services have to write out the current thread explicitly. Using current thread instead of client thread is also semantically incorrect, and will be a problem when we implement multicore (at which time there will be multiple current threads) --- src/core/hle/kernel/hle_ipc.cpp | 10 +++++----- src/core/hle/kernel/hle_ipc.h | 7 +++---- src/core/hle/kernel/server_session.cpp | 2 +- src/core/hle/service/fs/file.cpp | 3 +-- src/core/hle/service/fs/fs_user.cpp | 6 ++---- src/core/hle/service/nwm/nwm_uds.cpp | 1 - src/core/hle/service/sm/srv.cpp | 5 ++--- src/tests/core/hle/kernel/hle_ipc.cpp | 4 ++-- 8 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index a78a64bbf..cd2f9fc87 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -32,8 +32,7 @@ void SessionRequestHandler::ClientDisconnected(std::shared_ptr se connected_sessions.end()); } -std::shared_ptr HLERequestContext::SleepClientThread(std::shared_ptr thread, - const std::string& reason, +std::shared_ptr HLERequestContext::SleepClientThread(const std::string& reason, std::chrono::nanoseconds timeout, WakeupCallback&& callback) { // Put the client thread to sleep until the wait event is signaled or the timeout expires. @@ -60,7 +59,7 @@ std::shared_ptr HLERequestContext::SleepClientThread(std::shared_ptrstatus = ThreadStatus::WaitHleEvent; thread->wait_objects = {event}; - event->AddWaitingThread(thread); + event->AddWaitingThread(SharedFrom(thread)); if (timeout.count() > 0) thread->WakeAfterDelay(timeout.count()); @@ -68,8 +67,9 @@ std::shared_ptr HLERequestContext::SleepClientThread(std::shared_ptr session) - : kernel(kernel), session(std::move(session)) { +HLERequestContext::HLERequestContext(KernelSystem& kernel, std::shared_ptr session, + Thread* thread) + : kernel(kernel), session(std::move(session)), thread(thread) { cmd_buf[0] = 0; } diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 655165f8c..6b6415832 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -158,7 +158,7 @@ private: */ class HLERequestContext { public: - HLERequestContext(KernelSystem& kernel, std::shared_ptr session); + HLERequestContext(KernelSystem& kernel, std::shared_ptr session, Thread* thread); ~HLERequestContext(); /// Returns a pointer to the IPC command buffer for this request. @@ -180,7 +180,6 @@ public: /** * Puts the specified guest thread to sleep until the returned event is signaled or until the * specified timeout expires. - * @param thread Thread to be put to sleep. * @param reason Reason for pausing the thread, to be used for debugging purposes. * @param timeout Timeout in nanoseconds after which the thread will be awoken and the callback * invoked with a Timeout reason. @@ -189,8 +188,7 @@ public: * was called. * @returns Event that when signaled will resume the thread and call the callback function. */ - std::shared_ptr SleepClientThread(std::shared_ptr thread, - const std::string& reason, + std::shared_ptr SleepClientThread(const std::string& reason, std::chrono::nanoseconds timeout, WakeupCallback&& callback); @@ -240,6 +238,7 @@ private: KernelSystem& kernel; std::array cmd_buf; std::shared_ptr session; + Thread* thread; // TODO(yuriks): Check common usage of this and optimize size accordingly boost::container::small_vector, 8> request_handles; // The static buffers will be created when the IPC request is translated. diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 2989fa3f9..66db5500d 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -72,7 +72,7 @@ ResultCode ServerSession::HandleSyncRequest(std::shared_ptr thread) { kernel.memory.ReadBlock(*current_process, thread->GetCommandBufferAddress(), cmd_buf.data(), cmd_buf.size() * sizeof(u32)); - Kernel::HLERequestContext context(kernel, SharedFrom(this)); + Kernel::HLERequestContext context(kernel, SharedFrom(this), thread.get()); context.PopulateFromIncomingCommandBuffer(cmd_buf.data(), *current_process); hle_handler->HandleSyncRequest(context); diff --git a/src/core/hle/service/fs/file.cpp b/src/core/hle/service/fs/file.cpp index 9efd88dd3..fc98afc39 100644 --- a/src/core/hle/service/fs/file.cpp +++ b/src/core/hle/service/fs/file.cpp @@ -71,8 +71,7 @@ void File::Read(Kernel::HLERequestContext& ctx) { rb.PushMappedBuffer(buffer); std::chrono::nanoseconds read_timeout_ns{backend->GetReadDelayNs(length)}; - ctx.SleepClientThread(Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()), - "file::read", read_timeout_ns, + ctx.SleepClientThread("file::read", read_timeout_ns, [](std::shared_ptr /*thread*/, Kernel::HLERequestContext& /*ctx*/, Kernel::ThreadWakeupReason /*reason*/) { diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index ec1e1b851..9e57fa1c4 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -71,8 +71,7 @@ void FS_USER::OpenFile(Kernel::HLERequestContext& ctx) { LOG_ERROR(Service_FS, "failed to get a handle for file {}", file_path.DebugStr()); } - ctx.SleepClientThread(Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()), - "fs_user::open", open_timeout_ns, + ctx.SleepClientThread("fs_user::open", open_timeout_ns, [](std::shared_ptr /*thread*/, Kernel::HLERequestContext& /*ctx*/, Kernel::ThreadWakeupReason /*reason*/) { @@ -130,8 +129,7 @@ void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) { file_path.DebugStr(), mode.hex, attributes); } - ctx.SleepClientThread(Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()), - "fs_user::open_directly", open_timeout_ns, + ctx.SleepClientThread("fs_user::open_directly", open_timeout_ns, [](std::shared_ptr /*thread*/, Kernel::HLERequestContext& /*ctx*/, Kernel::ThreadWakeupReason /*reason*/) { diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp index d8bad3686..79fc3b829 100644 --- a/src/core/hle/service/nwm/nwm_uds.cpp +++ b/src/core/hle/service/nwm/nwm_uds.cpp @@ -1179,7 +1179,6 @@ void NWM_UDS::ConnectToNetwork(Kernel::HLERequestContext& ctx, u16 command_id, static constexpr std::chrono::nanoseconds UDSConnectionTimeout{300000000}; connection_event = ctx.SleepClientThread( - Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()), "uds::ConnectToNetwork", UDSConnectionTimeout, [command_id](std::shared_ptr thread, Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { diff --git a/src/core/hle/service/sm/srv.cpp b/src/core/hle/service/sm/srv.cpp index ab6585b6b..396bd3559 100644 --- a/src/core/hle/service/sm/srv.cpp +++ b/src/core/hle/service/sm/srv.cpp @@ -127,9 +127,8 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) { if (client_port.Failed()) { if (wait_until_available && client_port.Code() == ERR_SERVICE_NOT_REGISTERED) { LOG_INFO(Service_SRV, "called service={} delayed", name); - std::shared_ptr get_service_handle_event = ctx.SleepClientThread( - Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()), - "GetServiceHandle", std::chrono::nanoseconds(-1), get_handle); + std::shared_ptr get_service_handle_event = + ctx.SleepClientThread("GetServiceHandle", std::chrono::nanoseconds(-1), get_handle); get_service_handle_delayed_map[name] = std::move(get_service_handle_event); return; } else { diff --git a/src/tests/core/hle/kernel/hle_ipc.cpp b/src/tests/core/hle/kernel/hle_ipc.cpp index 455f50883..2dd3a0424 100644 --- a/src/tests/core/hle/kernel/hle_ipc.cpp +++ b/src/tests/core/hle/kernel/hle_ipc.cpp @@ -25,7 +25,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel Memory::MemorySystem memory; Kernel::KernelSystem kernel(memory, timing, [] {}, 0); auto session = std::get>(kernel.CreateSessionPair()); - HLERequestContext context(kernel, std::move(session)); + HLERequestContext context(kernel, std::move(session), nullptr); auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0)); @@ -237,7 +237,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { Memory::MemorySystem memory; Kernel::KernelSystem kernel(memory, timing, [] {}, 0); auto session = std::get>(kernel.CreateSessionPair()); - HLERequestContext context(kernel, std::move(session)); + HLERequestContext context(kernel, std::move(session), nullptr); auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0)); auto* input = context.CommandBuffer();