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 a78a64bbf8..cd2f9fc87c 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 655165f8cf..6b6415832a 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 2989fa3f94..66db5500dc 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 9efd88dd3f..fc98afc39c 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 ec1e1b8519..9e57fa1c4e 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 d8bad3686a..79fc3b8297 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 ab6585b6b5..396bd3559e 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 455f50883a..2dd3a0424a 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();