summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2019-11-26 00:28:48 +0100
committerbunnei <bunneidev@gmail.com>2019-11-28 18:01:53 +0100
commitc3d3b173d39b7c12fa9b3d5d34040e9377f2888e (patch)
tree61ff05239fe2b3d08bcf775f1528263cffc9aff4 /src/core/hle/kernel
parentMerge pull request #3169 from lioncash/memory (diff)
downloadyuzu-c3d3b173d39b7c12fa9b3d5d34040e9377f2888e.tar
yuzu-c3d3b173d39b7c12fa9b3d5d34040e9377f2888e.tar.gz
yuzu-c3d3b173d39b7c12fa9b3d5d34040e9377f2888e.tar.bz2
yuzu-c3d3b173d39b7c12fa9b3d5d34040e9377f2888e.tar.lz
yuzu-c3d3b173d39b7c12fa9b3d5d34040e9377f2888e.tar.xz
yuzu-c3d3b173d39b7c12fa9b3d5d34040e9377f2888e.tar.zst
yuzu-c3d3b173d39b7c12fa9b3d5d34040e9377f2888e.zip
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/client_port.cpp14
-rw-r--r--src/core/hle/kernel/client_session.cpp40
-rw-r--r--src/core/hle/kernel/client_session.h21
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp2
-rw-r--r--src/core/hle/kernel/hle_ipc.h13
-rw-r--r--src/core/hle/kernel/object.cpp1
-rw-r--r--src/core/hle/kernel/object.h1
-rw-r--r--src/core/hle/kernel/server_session.cpp117
-rw-r--r--src/core/hle/kernel/server_session.h49
-rw-r--r--src/core/hle/kernel/session.cpp32
-rw-r--r--src/core/hle/kernel/session.h57
-rw-r--r--src/core/hle/kernel/svc.cpp9
12 files changed, 214 insertions, 142 deletions
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index 4637b6017..00bb939a0 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -9,6 +9,7 @@
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/server_port.h"
#include "core/hle/kernel/server_session.h"
+#include "core/hle/kernel/session.h"
namespace Kernel {
@@ -20,28 +21,23 @@ std::shared_ptr<ServerPort> ClientPort::GetServerPort() const {
}
ResultVal<std::shared_ptr<ClientSession>> ClientPort::Connect() {
- // Note: Threads do not wait for the server endpoint to call
- // AcceptSession before returning from this call.
-
if (active_sessions >= max_sessions) {
return ERR_MAX_CONNECTIONS_REACHED;
}
active_sessions++;
- // Create a new session pair, let the created sessions inherit the parent port's HLE handler.
- auto [server, client] =
- ServerSession::CreateSessionPair(kernel, server_port->GetName(), SharedFrom(this));
+ auto [client, server] = Kernel::Session::Create(kernel, name);
if (server_port->HasHLEHandler()) {
- server_port->GetHLEHandler()->ClientConnected(server);
+ server_port->GetHLEHandler()->ClientConnected(std::move(server));
} else {
- server_port->AppendPendingSession(server);
+ server_port->AppendPendingSession(std::move(server));
}
// Wake the threads waiting on the ServerPort
server_port->WakeupAllWaitingThreads();
- return MakeResult(client);
+ return MakeResult(std::move(client));
}
void ClientPort::ConnectionClosed() {
diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp
index 9849dbe91..4669a14ad 100644
--- a/src/core/hle/kernel/client_session.cpp
+++ b/src/core/hle/kernel/client_session.cpp
@@ -1,4 +1,4 @@
-// Copyright 2016 Citra Emulator Project
+// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -12,22 +12,44 @@
namespace Kernel {
-ClientSession::ClientSession(KernelCore& kernel) : Object{kernel} {}
+ClientSession::ClientSession(KernelCore& kernel) : WaitObject{kernel} {}
+
ClientSession::~ClientSession() {
// This destructor will be called automatically when the last ClientSession handle is closed by
// the emulated application.
- if (auto server = parent->server.lock()) {
- server->ClientDisconnected();
+ if (parent->Server()) {
+ parent->Server()->ClientDisconnected();
}
}
-ResultCode ClientSession::SendSyncRequest(Thread* thread, Memory::Memory& memory) {
- // Signal the server session that new data is available
- if (auto server = parent->server.lock()) {
- return server->HandleSyncRequest(SharedFrom(thread), memory);
+bool ClientSession::ShouldWait(const Thread* thread) const {
+ UNIMPLEMENTED();
+ return {};
+}
+
+void ClientSession::Acquire(Thread* thread) {
+ UNIMPLEMENTED();
+}
+
+ResultVal<std::shared_ptr<ClientSession>> ClientSession::Create(KernelCore& kernel,
+ std::shared_ptr<Session> parent,
+ std::string name) {
+ std::shared_ptr<ClientSession> client_session{std::make_shared<ClientSession>(kernel)};
+
+ client_session->name = std::move(name);
+ client_session->parent = std::move(parent);
+
+ return MakeResult(std::move(client_session));
+}
+
+ResultCode ClientSession::SendSyncRequest(std::shared_ptr<Thread> thread, Memory::Memory& memory) {
+ // Keep ServerSession alive until we're done working with it.
+ if (!parent->Server()) {
+ return ERR_SESSION_CLOSED_BY_REMOTE;
}
- return ERR_SESSION_CLOSED_BY_REMOTE;
+ // Signal the server session that new data is available
+ return parent->Server()->HandleSyncRequest(std::move(thread), memory);
}
} // namespace Kernel
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h
index 484dd7bc9..b4289a9a8 100644
--- a/src/core/hle/kernel/client_session.h
+++ b/src/core/hle/kernel/client_session.h
@@ -1,4 +1,4 @@
-// Copyright 2016 Citra Emulator Project
+// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -6,7 +6,9 @@
#include <memory>
#include <string>
-#include "core/hle/kernel/object.h"
+
+#include "core/hle/kernel/wait_object.h"
+#include "core/hle/result.h"
union ResultCode;
@@ -18,15 +20,14 @@ namespace Kernel {
class KernelCore;
class Session;
-class ServerSession;
class Thread;
-class ClientSession final : public Object {
+class ClientSession final : public WaitObject {
public:
explicit ClientSession(KernelCore& kernel);
~ClientSession() override;
- friend class ServerSession;
+ friend class Session;
std::string GetTypeName() const override {
return "ClientSession";
@@ -41,9 +42,17 @@ public:
return HANDLE_TYPE;
}
- ResultCode SendSyncRequest(Thread* thread, Memory::Memory& memory);
+ ResultCode SendSyncRequest(std::shared_ptr<Thread> thread, Memory::Memory& memory);
+
+ bool ShouldWait(const Thread* thread) const override;
+
+ void Acquire(Thread* thread) override;
private:
+ static ResultVal<std::shared_ptr<ClientSession>> Create(KernelCore& kernel,
+ std::shared_ptr<Session> parent,
+ std::string name = "Unknown");
+
/// The parent session, which links to the server endpoint.
std::shared_ptr<Session> parent;
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 8b01567a8..2db28dcf0 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -74,6 +74,8 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread(
thread->WakeAfterDelay(timeout);
}
+ is_thread_waiting = true;
+
return writable_event;
}
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index dab37ba0d..050ad8fd7 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -264,6 +264,18 @@ public:
std::string Description() const;
+ Thread& GetThread() {
+ return *thread;
+ }
+
+ const Thread& GetThread() const {
+ return *thread;
+ }
+
+ bool IsThreadWaiting() const {
+ return is_thread_waiting;
+ }
+
private:
void ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf, bool incoming);
@@ -290,6 +302,7 @@ private:
u32_le command{};
std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers;
+ bool is_thread_waiting{};
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp
index 10431e94c..2c571792b 100644
--- a/src/core/hle/kernel/object.cpp
+++ b/src/core/hle/kernel/object.cpp
@@ -27,6 +27,7 @@ bool Object::IsWaitable() const {
case HandleType::ResourceLimit:
case HandleType::ClientPort:
case HandleType::ClientSession:
+ case HandleType::Session:
return false;
}
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index bbbb4e7cc..e3391e2af 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -29,6 +29,7 @@ enum class HandleType : u32 {
ServerPort,
ClientSession,
ServerSession,
+ Session,
};
class Object : NonCopyable, public std::enable_shared_from_this<Object> {
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 1198c7a97..7825e1ec4 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -1,4 +1,4 @@
-// Copyright 2016 Citra Emulator Project
+// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -9,6 +9,7 @@
#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/core.h"
+#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
@@ -24,34 +25,29 @@
namespace Kernel {
ServerSession::ServerSession(KernelCore& kernel) : WaitObject{kernel} {}
-ServerSession::~ServerSession() {
- // This destructor will be called automatically when the last ServerSession handle is closed by
- // the emulated application.
-
- // Decrease the port's connection count.
- if (parent->port) {
- parent->port->ConnectionClosed();
- }
-}
+ServerSession::~ServerSession() = default;
ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kernel,
+ std::shared_ptr<Session> parent,
std::string name) {
- std::shared_ptr<ServerSession> server_session = std::make_shared<ServerSession>(kernel);
+ std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)};
- server_session->name = std::move(name);
- server_session->parent = nullptr;
+ session->request_event = Core::Timing::CreateEvent(
+ name, [session](u64 userdata, s64 cycles_late) { session->CompleteSyncRequest(); });
+ session->name = std::move(name);
+ session->parent = std::move(parent);
- return MakeResult(std::move(server_session));
+ return MakeResult(std::move(session));
}
bool ServerSession::ShouldWait(const Thread* thread) const {
- // Wait if we have no pending requests, or if we're currently handling a request.
- if (auto client = parent->client.lock()) {
- return pending_requesting_threads.empty() || currently_handling != nullptr;
+ // Closed sessions should never wait, an error will be returned from svcReplyAndReceive.
+ if (!parent->Client()) {
+ return false;
}
- // Closed sessions should never wait, an error will be returned from svcReplyAndReceive.
- return {};
+ // Wait if we have no pending requests, or if we're currently handling a request.
+ return pending_requesting_threads.empty() || currently_handling != nullptr;
}
void ServerSession::Acquire(Thread* thread) {
@@ -128,14 +124,21 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con
return RESULT_SUCCESS;
}
-ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread,
- Memory::Memory& memory) {
- // The ServerSession received a sync request, this means that there's new data available
- // from its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or
- // similar.
- Kernel::HLERequestContext context(SharedFrom(this), thread);
- u32* cmd_buf = (u32*)memory.GetPointer(thread->GetTLSAddress());
- context.PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
+ResultCode ServerSession::QueueSyncRequest(std::shared_ptr<Thread> thread, Memory::Memory& memory) {
+ u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(thread->GetTLSAddress()))};
+ std::shared_ptr<Kernel::HLERequestContext> context{
+ std::make_shared<Kernel::HLERequestContext>(SharedFrom(this), std::move(thread))};
+
+ context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
+ request_queue.Push(std::move(context));
+
+ return RESULT_SUCCESS;
+}
+
+ResultCode ServerSession::CompleteSyncRequest() {
+ ASSERT(!request_queue.Empty());
+
+ auto& context = *request_queue.Front();
ResultCode result = RESULT_SUCCESS;
// If the session has been converted to a domain, handle the domain request
@@ -147,61 +150,27 @@ ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread,
result = hle_handler->HandleSyncRequest(context);
}
- if (thread->GetStatus() == ThreadStatus::Running) {
- // Put the thread to sleep until the server replies, it will be awoken in
- // svcReplyAndReceive for LLE servers.
- thread->SetStatus(ThreadStatus::WaitIPC);
-
- if (hle_handler != nullptr) {
- // For HLE services, we put the request threads to sleep for a short duration to
- // simulate IPC overhead, but only if the HLE handler didn't put the thread to sleep for
- // other reasons like an async callback. The IPC overhead is needed to prevent
- // starvation when a thread only does sync requests to HLE services while a
- // lower-priority thread is waiting to run.
-
- // This delay was approximated in a homebrew application by measuring the average time
- // it takes for svcSendSyncRequest to return when performing the SetLcdForceBlack IPC
- // request to the GSP:GPU service in a n3DS with firmware 11.6. The measured values have
- // a high variance and vary between models.
- static constexpr u64 IPCDelayNanoseconds = 39000;
- thread->WakeAfterDelay(IPCDelayNanoseconds);
- } else {
- // Add the thread to the list of threads that have issued a sync request with this
- // server.
- pending_requesting_threads.push_back(std::move(thread));
- }
- }
-
- // If this ServerSession does not have an HLE implementation, just wake up the threads waiting
- // on it.
- WakeupAllWaitingThreads();
-
- // Handle scenario when ConvertToDomain command was issued, as we must do the conversion at the
- // end of the command such that only commands following this one are handled as domains
if (convert_to_domain) {
ASSERT_MSG(IsSession(), "ServerSession is already a domain instance.");
domain_request_handlers = {hle_handler};
convert_to_domain = false;
}
- return result;
-}
-
-ServerSession::SessionPair ServerSession::CreateSessionPair(KernelCore& kernel,
- const std::string& name,
- std::shared_ptr<ClientPort> port) {
- auto server_session = ServerSession::Create(kernel, name + "_Server").Unwrap();
- std::shared_ptr<ClientSession> client_session = std::make_shared<ClientSession>(kernel);
- client_session->name = name + "_Client";
+ // Some service requests require the thread to block
+ if (!context.IsThreadWaiting()) {
+ context.GetThread().ResumeFromWait();
+ context.GetThread().SetWaitSynchronizationResult(result);
+ }
- std::shared_ptr<Session> parent = std::make_shared<Session>();
- parent->client = client_session;
- parent->server = server_session;
- parent->port = std::move(port);
+ request_queue.Pop();
- client_session->parent = parent;
- server_session->parent = parent;
+ return result;
+}
- return std::make_pair(std::move(server_session), std::move(client_session));
+ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread,
+ Memory::Memory& memory) {
+ Core::System::GetInstance().CoreTiming().ScheduleEvent(20000, request_event, {});
+ return QueueSyncRequest(std::move(thread), memory);
}
+
} // namespace Kernel
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h
index 641709a45..d6e48109e 100644
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/server_session.h
@@ -1,4 +1,4 @@
-// Copyright 2014 Citra Emulator Project
+// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -9,7 +9,7 @@
#include <utility>
#include <vector>
-#include "core/hle/kernel/object.h"
+#include "common/threadsafe_queue.h"
#include "core/hle/kernel/wait_object.h"
#include "core/hle/result.h"
@@ -17,13 +17,14 @@ namespace Memory {
class Memory;
}
+namespace Core::Timing {
+struct EventType;
+}
+
namespace Kernel {
-class ClientPort;
-class ClientSession;
class HLERequestContext;
class KernelCore;
-class ServerSession;
class Session;
class SessionRequestHandler;
class Thread;
@@ -45,6 +46,12 @@ public:
explicit ServerSession(KernelCore& kernel);
~ServerSession() override;
+ friend class Session;
+
+ static ResultVal<std::shared_ptr<ServerSession>> Create(KernelCore& kernel,
+ std::shared_ptr<Session> parent,
+ std::string name = "Unknown");
+
std::string GetTypeName() const override {
return "ServerSession";
}
@@ -66,18 +73,6 @@ public:
return parent.get();
}
- using SessionPair = std::pair<std::shared_ptr<ServerSession>, std::shared_ptr<ClientSession>>;
-
- /**
- * Creates a pair of ServerSession and an associated ClientSession.
- * @param kernel The kernal instance to create the session pair under.
- * @param name Optional name of the ports.
- * @param client_port Optional The ClientPort that spawned this session.
- * @return The created session tuple
- */
- static SessionPair CreateSessionPair(KernelCore& kernel, const std::string& name = "Unknown",
- std::shared_ptr<ClientPort> client_port = nullptr);
-
/**
* Sets the HLE handler for the session. This handler will be called to service IPC requests
* instead of the regular IPC machinery. (The regular IPC machinery is currently not
@@ -128,15 +123,11 @@ public:
}
private:
- /**
- * Creates a server session. The server session can have an optional HLE handler,
- * which will be invoked to handle the IPC requests that this session receives.
- * @param kernel The kernel instance to create this server session under.
- * @param name Optional name of the server session.
- * @return The created server session
- */
- static ResultVal<std::shared_ptr<ServerSession>> Create(KernelCore& kernel,
- std::string name = "Unknown");
+ /// Queues a sync request from the emulated application.
+ ResultCode QueueSyncRequest(std::shared_ptr<Thread> thread, Memory::Memory& memory);
+
+ /// Completes a sync request from the emulated application.
+ ResultCode CompleteSyncRequest();
/// Handles a SyncRequest to a domain, forwarding the request to the proper object or closing an
/// object handle.
@@ -166,6 +157,12 @@ private:
/// The name of this session (optional)
std::string name;
+
+ /// Core timing event used to schedule the service request at some point in the future
+ std::shared_ptr<Core::Timing::EventType> request_event;
+
+ /// Queue of scheduled service requests
+ Common::MPSCQueue<std::shared_ptr<Kernel::HLERequestContext>> request_queue;
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp
index 642914744..dee6e2b72 100644
--- a/src/core/hle/kernel/session.cpp
+++ b/src/core/hle/kernel/session.cpp
@@ -1,12 +1,36 @@
-// Copyright 2015 Citra Emulator Project
+// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/assert.h"
+#include "core/hle/kernel/client_session.h"
+#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/session.h"
-#include "core/hle/kernel/thread.h"
namespace Kernel {
-Session::Session() {}
-Session::~Session() {}
+Session::Session(KernelCore& kernel) : WaitObject{kernel} {}
+Session::~Session() = default;
+
+Session::SessionPair Session::Create(KernelCore& kernel, std::string name) {
+ auto session{std::make_shared<Session>(kernel)};
+ auto client_session{Kernel::ClientSession::Create(kernel, session, name + "_Client").Unwrap()};
+ auto server_session{Kernel::ServerSession::Create(kernel, session, name + "_Server").Unwrap()};
+
+ session->name = std::move(name);
+ session->client = client_session;
+ session->server = server_session;
+
+ return std::make_pair(std::move(client_session), std::move(server_session));
+}
+
+bool Session::ShouldWait(const Thread* thread) const {
+ UNIMPLEMENTED();
+ return {};
+}
+
+void Session::Acquire(Thread* thread) {
+ UNIMPLEMENTED();
+}
+
} // namespace Kernel
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
index 94395f9f5..5a9d4e9ad 100644
--- a/src/core/hle/kernel/session.h
+++ b/src/core/hle/kernel/session.h
@@ -1,27 +1,64 @@
-// Copyright 2018 yuzu emulator team
+// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
-#include "core/hle/kernel/object.h"
+#include <memory>
+#include <string>
+
+#include "core/hle/kernel/wait_object.h"
+#include "core/hle/result.h"
namespace Kernel {
class ClientSession;
-class ClientPort;
class ServerSession;
/**
* Parent structure to link the client and server endpoints of a session with their associated
- * client port. The client port need not exist, as is the case for portless sessions like the
- * FS File and Directory sessions. When one of the endpoints of a session is destroyed, its
- * corresponding field in this structure will be set to nullptr.
+ * client port.
*/
-class Session final {
+class Session final : public WaitObject {
public:
- std::weak_ptr<ClientSession> client; ///< The client endpoint of the session.
- std::weak_ptr<ServerSession> server; ///< The server endpoint of the session.
- std::shared_ptr<ClientPort> port; ///< The port that this session is associated with (optional).
+ explicit Session(KernelCore& kernel);
+ ~Session() override;
+
+ using SessionPair = std::pair<std::shared_ptr<ClientSession>, std::shared_ptr<ServerSession>>;
+
+ static SessionPair Create(KernelCore& kernel, std::string name = "Unknown");
+
+ std::string GetName() const override {
+ return name;
+ }
+
+ static constexpr HandleType HANDLE_TYPE = HandleType::Session;
+ HandleType GetHandleType() const override {
+ return HANDLE_TYPE;
+ }
+
+ bool ShouldWait(const Thread* thread) const override;
+
+ void Acquire(Thread* thread) override;
+
+ std::shared_ptr<ClientSession> Client() {
+ if (auto result{client.lock()}) {
+ return result;
+ }
+ return {};
+ }
+
+ std::shared_ptr<ServerSession> Server() {
+ if (auto result{server.lock()}) {
+ return result;
+ }
+ return {};
+ }
+
+private:
+ std::string name;
+ std::weak_ptr<ClientSession> client;
+ std::weak_ptr<ServerSession> server;
};
+
} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index db3ae3eb8..bd25de478 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -381,11 +381,12 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
- system.PrepareReschedule();
+ auto thread = system.CurrentScheduler().GetCurrentThread();
+ thread->InvalidateWakeupCallback();
+ thread->SetStatus(ThreadStatus::WaitIPC);
+ system.PrepareReschedule(thread->GetProcessorID());
- // TODO(Subv): svcSendSyncRequest should put the caller thread to sleep while the server
- // responds and cause a reschedule.
- return session->SendSyncRequest(system.CurrentScheduler().GetCurrentThread(), system.Memory());
+ return session->SendSyncRequest(SharedFrom(thread), system.Memory());
}
/// Get the ID for the specified thread.