From 38a90882a4230bb797ae3f6857e986d70f3bd265 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 1 Jan 2017 11:57:02 -0500 Subject: [PATCH] Kernel/Synch: Do not attempt a reschedule on every syscall. Not all syscalls should cause reschedules, this commit attempts to remedy that, however, it still does not cover all cases. --- src/core/hle/kernel/mutex.cpp | 1 + src/core/hle/svc.cpp | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 736944bae..8d92a9b8e 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -84,6 +84,7 @@ void Mutex::Release() { if (lock_count == 0) { holding_thread->held_mutexes.erase(this); ResumeWaitingThread(this); + Core::System::GetInstance().PrepareReschedule(); } } } diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 2ca270de3..5b538be22 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -248,6 +248,8 @@ static ResultCode SendSyncRequest(Kernel::Handle handle) { LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str()); + Core::System::GetInstance().PrepareReschedule(); + // TODO(Subv): svcSendSyncRequest should put the caller thread to sleep while the server // responds and cause a reschedule. return session->SendSyncRequest(); @@ -284,6 +286,8 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds) // Create an event to wake the thread up after the specified nanosecond delay has passed thread->WakeAfterDelay(nano_seconds); + Core::System::GetInstance().PrepareReschedule(); + // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread // resumes due to a signal in its wait objects. // Otherwise we retain the default value of timeout. @@ -366,6 +370,8 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha // Create an event to wake the thread up after the specified nanosecond delay has passed thread->WakeAfterDelay(nano_seconds); + Core::System::GetInstance().PrepareReschedule(); + // This value gets set to -1 by default in this case, it is not modified after this. *out = -1; // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to @@ -414,6 +420,8 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha // Create an event to wake the thread up after the specified nanosecond delay has passed thread->WakeAfterDelay(nano_seconds); + Core::System::GetInstance().PrepareReschedule(); + // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to a // signal in one of its wait objects. // Otherwise we retain the default value of timeout, and -1 in the out parameter @@ -448,6 +456,9 @@ static ResultCode ArbitrateAddress(Kernel::Handle handle, u32 address, u32 type, auto res = arbiter->ArbitrateAddress(static_cast(type), address, value, nanoseconds); + // TODO(Subv): Identify in which specific cases this call should cause a reschedule. + Core::System::GetInstance().PrepareReschedule(); + return res; } @@ -574,6 +585,8 @@ static ResultCode CreateThread(Kernel::Handle* out_handle, s32 priority, u32 ent CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread))); + Core::System::GetInstance().PrepareReschedule(); + LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle); @@ -586,6 +599,7 @@ static void ExitThread() { LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::CPU().GetPC()); Kernel::ExitCurrentThread(); + Core::System::GetInstance().PrepareReschedule(); } /// Gets the priority for the specified thread @@ -605,6 +619,7 @@ static ResultCode SetThreadPriority(Kernel::Handle handle, s32 priority) { return ERR_INVALID_HANDLE; thread->SetPriority(priority); + Core::System::GetInstance().PrepareReschedule(); return RESULT_SUCCESS; } @@ -849,6 +864,8 @@ static void SleepThread(s64 nanoseconds) { // Create an event to wake the thread up after the specified nanosecond delay has passed Kernel::GetCurrentThread()->WakeAfterDelay(nanoseconds); + + Core::System::GetInstance().PrepareReschedule(); } /// This returns the total CPU ticks elapsed since the CPU was powered-on @@ -1184,8 +1201,6 @@ void CallSVC(u32 immediate) { if (info) { if (info->func) { info->func(); - // TODO(Subv): Not all service functions should cause a reschedule in all cases. - Core::System::GetInstance().PrepareReschedule(); } else { LOG_ERROR(Kernel_SVC, "unimplemented SVC function %s(..)", info->name); }