hle_ipc: Add SleepClientThread to block current thread within HLE routines.

This commit is contained in:
bunnei 2018-03-18 20:22:46 -04:00
parent 2faa83ca13
commit c86af6939c
2 changed files with 47 additions and 0 deletions

View File

@ -7,6 +7,7 @@
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
@ -26,6 +27,32 @@ void SessionRequestHandler::ClientDisconnected(SharedPtr<ServerSession> server_s
boost::range::remove_erase(connected_sessions, server_session); boost::range::remove_erase(connected_sessions, server_session);
} }
SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
const std::string& reason, u64 timeout,
WakeupCallback&& callback) {
// Put the client thread to sleep until the wait event is signaled or the timeout expires.
thread->wakeup_callback =
[context = *this, callback](ThreadWakeupReason reason, SharedPtr<Thread> thread,
SharedPtr<WaitObject> object, size_t index) mutable -> bool {
ASSERT(thread->status == THREADSTATUS_WAIT_HLE_EVENT);
callback(thread, context, reason);
context.WriteToOutgoingCommandBuffer(*thread);
return true;
};
auto event = Kernel::Event::Create(Kernel::ResetType::OneShot, "HLE Pause Event: " + reason);
thread->status = THREADSTATUS_WAIT_HLE_EVENT;
thread->wait_objects = {event};
event->AddWaitingThread(thread);
if (timeout > 0) {
thread->WakeAfterDelay(timeout);
}
return event;
}
HLERequestContext::HLERequestContext(SharedPtr<Kernel::ServerSession> server_session) HLERequestContext::HLERequestContext(SharedPtr<Kernel::ServerSession> server_session)
: server_session(std::move(server_session)) { : server_session(std::move(server_session)) {
cmd_buf[0] = 0; cmd_buf[0] = 0;

View File

@ -6,6 +6,7 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <string>
#include <vector> #include <vector>
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
#include "common/common_types.h" #include "common/common_types.h"
@ -25,6 +26,7 @@ class Domain;
class HandleTable; class HandleTable;
class HLERequestContext; class HLERequestContext;
class Process; class Process;
class Event;
/** /**
* Interface implemented by HLE Session handlers. * Interface implemented by HLE Session handlers.
@ -103,6 +105,24 @@ public:
return server_session; return server_session;
} }
using WakeupCallback = std::function<void(SharedPtr<Thread> thread, HLERequestContext& context,
ThreadWakeupReason reason)>;
/**
* 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.
* @param callback Callback to be invoked when the thread is resumed. This callback must write
* the entire command response once again, regardless of the state of it before this function
* was called.
* @returns Event that when signaled will resume the thread and call the callback function.
*/
SharedPtr<Event> SleepClientThread(SharedPtr<Thread> thread, const std::string& reason,
u64 timeout, WakeupCallback&& callback);
void ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming); void ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming);
/// Populates this context with data from the requesting process/thread. /// Populates this context with data from the requesting process/thread.