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)
This commit is contained in:
parent
daeba65fb4
commit
f565ea80f0
|
@ -32,8 +32,7 @@ void SessionRequestHandler::ClientDisconnected(std::shared_ptr<ServerSession> se
|
||||||
connected_sessions.end());
|
connected_sessions.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Event> HLERequestContext::SleepClientThread(std::shared_ptr<Thread> thread,
|
std::shared_ptr<Event> HLERequestContext::SleepClientThread(const std::string& reason,
|
||||||
const std::string& reason,
|
|
||||||
std::chrono::nanoseconds timeout,
|
std::chrono::nanoseconds timeout,
|
||||||
WakeupCallback&& callback) {
|
WakeupCallback&& callback) {
|
||||||
// Put the client thread to sleep until the wait event is signaled or the timeout expires.
|
// Put the client thread to sleep until the wait event is signaled or the timeout expires.
|
||||||
|
@ -60,7 +59,7 @@ std::shared_ptr<Event> HLERequestContext::SleepClientThread(std::shared_ptr<Thre
|
||||||
auto event = kernel.CreateEvent(Kernel::ResetType::OneShot, "HLE Pause Event: " + reason);
|
auto event = kernel.CreateEvent(Kernel::ResetType::OneShot, "HLE Pause Event: " + reason);
|
||||||
thread->status = ThreadStatus::WaitHleEvent;
|
thread->status = ThreadStatus::WaitHleEvent;
|
||||||
thread->wait_objects = {event};
|
thread->wait_objects = {event};
|
||||||
event->AddWaitingThread(thread);
|
event->AddWaitingThread(SharedFrom(thread));
|
||||||
|
|
||||||
if (timeout.count() > 0)
|
if (timeout.count() > 0)
|
||||||
thread->WakeAfterDelay(timeout.count());
|
thread->WakeAfterDelay(timeout.count());
|
||||||
|
@ -68,8 +67,9 @@ std::shared_ptr<Event> HLERequestContext::SleepClientThread(std::shared_ptr<Thre
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
HLERequestContext::HLERequestContext(KernelSystem& kernel, std::shared_ptr<ServerSession> session)
|
HLERequestContext::HLERequestContext(KernelSystem& kernel, std::shared_ptr<ServerSession> session,
|
||||||
: kernel(kernel), session(std::move(session)) {
|
Thread* thread)
|
||||||
|
: kernel(kernel), session(std::move(session)), thread(thread) {
|
||||||
cmd_buf[0] = 0;
|
cmd_buf[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ private:
|
||||||
*/
|
*/
|
||||||
class HLERequestContext {
|
class HLERequestContext {
|
||||||
public:
|
public:
|
||||||
HLERequestContext(KernelSystem& kernel, std::shared_ptr<ServerSession> session);
|
HLERequestContext(KernelSystem& kernel, std::shared_ptr<ServerSession> session, Thread* thread);
|
||||||
~HLERequestContext();
|
~HLERequestContext();
|
||||||
|
|
||||||
/// Returns a pointer to the IPC command buffer for this request.
|
/// 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
|
* Puts the specified guest thread to sleep until the returned event is signaled or until the
|
||||||
* specified timeout expires.
|
* 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 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
|
* @param timeout Timeout in nanoseconds after which the thread will be awoken and the callback
|
||||||
* invoked with a Timeout reason.
|
* invoked with a Timeout reason.
|
||||||
|
@ -189,8 +188,7 @@ public:
|
||||||
* was called.
|
* was called.
|
||||||
* @returns Event that when signaled will resume the thread and call the callback function.
|
* @returns Event that when signaled will resume the thread and call the callback function.
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<Event> SleepClientThread(std::shared_ptr<Thread> thread,
|
std::shared_ptr<Event> SleepClientThread(const std::string& reason,
|
||||||
const std::string& reason,
|
|
||||||
std::chrono::nanoseconds timeout,
|
std::chrono::nanoseconds timeout,
|
||||||
WakeupCallback&& callback);
|
WakeupCallback&& callback);
|
||||||
|
|
||||||
|
@ -240,6 +238,7 @@ private:
|
||||||
KernelSystem& kernel;
|
KernelSystem& kernel;
|
||||||
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
|
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
|
||||||
std::shared_ptr<ServerSession> session;
|
std::shared_ptr<ServerSession> session;
|
||||||
|
Thread* thread;
|
||||||
// TODO(yuriks): Check common usage of this and optimize size accordingly
|
// TODO(yuriks): Check common usage of this and optimize size accordingly
|
||||||
boost::container::small_vector<std::shared_ptr<Object>, 8> request_handles;
|
boost::container::small_vector<std::shared_ptr<Object>, 8> request_handles;
|
||||||
// The static buffers will be created when the IPC request is translated.
|
// The static buffers will be created when the IPC request is translated.
|
||||||
|
|
|
@ -72,7 +72,7 @@ ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread) {
|
||||||
kernel.memory.ReadBlock(*current_process, thread->GetCommandBufferAddress(), cmd_buf.data(),
|
kernel.memory.ReadBlock(*current_process, thread->GetCommandBufferAddress(), cmd_buf.data(),
|
||||||
cmd_buf.size() * sizeof(u32));
|
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);
|
context.PopulateFromIncomingCommandBuffer(cmd_buf.data(), *current_process);
|
||||||
|
|
||||||
hle_handler->HandleSyncRequest(context);
|
hle_handler->HandleSyncRequest(context);
|
||||||
|
|
|
@ -71,8 +71,7 @@ void File::Read(Kernel::HLERequestContext& ctx) {
|
||||||
rb.PushMappedBuffer(buffer);
|
rb.PushMappedBuffer(buffer);
|
||||||
|
|
||||||
std::chrono::nanoseconds read_timeout_ns{backend->GetReadDelayNs(length)};
|
std::chrono::nanoseconds read_timeout_ns{backend->GetReadDelayNs(length)};
|
||||||
ctx.SleepClientThread(Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()),
|
ctx.SleepClientThread("file::read", read_timeout_ns,
|
||||||
"file::read", read_timeout_ns,
|
|
||||||
[](std::shared_ptr<Kernel::Thread> /*thread*/,
|
[](std::shared_ptr<Kernel::Thread> /*thread*/,
|
||||||
Kernel::HLERequestContext& /*ctx*/,
|
Kernel::HLERequestContext& /*ctx*/,
|
||||||
Kernel::ThreadWakeupReason /*reason*/) {
|
Kernel::ThreadWakeupReason /*reason*/) {
|
||||||
|
|
|
@ -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());
|
LOG_ERROR(Service_FS, "failed to get a handle for file {}", file_path.DebugStr());
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.SleepClientThread(Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()),
|
ctx.SleepClientThread("fs_user::open", open_timeout_ns,
|
||||||
"fs_user::open", open_timeout_ns,
|
|
||||||
[](std::shared_ptr<Kernel::Thread> /*thread*/,
|
[](std::shared_ptr<Kernel::Thread> /*thread*/,
|
||||||
Kernel::HLERequestContext& /*ctx*/,
|
Kernel::HLERequestContext& /*ctx*/,
|
||||||
Kernel::ThreadWakeupReason /*reason*/) {
|
Kernel::ThreadWakeupReason /*reason*/) {
|
||||||
|
@ -130,8 +129,7 @@ void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) {
|
||||||
file_path.DebugStr(), mode.hex, attributes);
|
file_path.DebugStr(), mode.hex, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.SleepClientThread(Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()),
|
ctx.SleepClientThread("fs_user::open_directly", open_timeout_ns,
|
||||||
"fs_user::open_directly", open_timeout_ns,
|
|
||||||
[](std::shared_ptr<Kernel::Thread> /*thread*/,
|
[](std::shared_ptr<Kernel::Thread> /*thread*/,
|
||||||
Kernel::HLERequestContext& /*ctx*/,
|
Kernel::HLERequestContext& /*ctx*/,
|
||||||
Kernel::ThreadWakeupReason /*reason*/) {
|
Kernel::ThreadWakeupReason /*reason*/) {
|
||||||
|
|
|
@ -1179,7 +1179,6 @@ void NWM_UDS::ConnectToNetwork(Kernel::HLERequestContext& ctx, u16 command_id,
|
||||||
static constexpr std::chrono::nanoseconds UDSConnectionTimeout{300000000};
|
static constexpr std::chrono::nanoseconds UDSConnectionTimeout{300000000};
|
||||||
|
|
||||||
connection_event = ctx.SleepClientThread(
|
connection_event = ctx.SleepClientThread(
|
||||||
Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()),
|
|
||||||
"uds::ConnectToNetwork", UDSConnectionTimeout,
|
"uds::ConnectToNetwork", UDSConnectionTimeout,
|
||||||
[command_id](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
|
[command_id](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
|
||||||
Kernel::ThreadWakeupReason reason) {
|
Kernel::ThreadWakeupReason reason) {
|
||||||
|
|
|
@ -127,9 +127,8 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) {
|
||||||
if (client_port.Failed()) {
|
if (client_port.Failed()) {
|
||||||
if (wait_until_available && client_port.Code() == ERR_SERVICE_NOT_REGISTERED) {
|
if (wait_until_available && client_port.Code() == ERR_SERVICE_NOT_REGISTERED) {
|
||||||
LOG_INFO(Service_SRV, "called service={} delayed", name);
|
LOG_INFO(Service_SRV, "called service={} delayed", name);
|
||||||
std::shared_ptr<Kernel::Event> get_service_handle_event = ctx.SleepClientThread(
|
std::shared_ptr<Kernel::Event> get_service_handle_event =
|
||||||
Kernel::SharedFrom(system.Kernel().GetThreadManager().GetCurrentThread()),
|
ctx.SleepClientThread("GetServiceHandle", std::chrono::nanoseconds(-1), get_handle);
|
||||||
"GetServiceHandle", std::chrono::nanoseconds(-1), get_handle);
|
|
||||||
get_service_handle_delayed_map[name] = std::move(get_service_handle_event);
|
get_service_handle_delayed_map[name] = std::move(get_service_handle_event);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -25,7 +25,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
|
||||||
Memory::MemorySystem memory;
|
Memory::MemorySystem memory;
|
||||||
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
||||||
auto session = std::get<std::shared_ptr<ServerSession>>(kernel.CreateSessionPair());
|
auto session = std::get<std::shared_ptr<ServerSession>>(kernel.CreateSessionPair());
|
||||||
HLERequestContext context(kernel, std::move(session));
|
HLERequestContext context(kernel, std::move(session), nullptr);
|
||||||
|
|
||||||
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
|
||||||
Memory::MemorySystem memory;
|
Memory::MemorySystem memory;
|
||||||
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
||||||
auto session = std::get<std::shared_ptr<ServerSession>>(kernel.CreateSessionPair());
|
auto session = std::get<std::shared_ptr<ServerSession>>(kernel.CreateSessionPair());
|
||||||
HLERequestContext context(kernel, std::move(session));
|
HLERequestContext context(kernel, std::move(session), nullptr);
|
||||||
|
|
||||||
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
||||||
auto* input = context.CommandBuffer();
|
auto* input = context.CommandBuffer();
|
||||||
|
|
Reference in New Issue