summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp5
-rw-r--r--src/core/hle/kernel/global_scheduler_context.cpp8
-rw-r--r--src/core/hle/kernel/global_scheduler_context.h10
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp8
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp25
-rw-r--r--src/core/hle/kernel/k_scheduler.h19
-rw-r--r--src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h56
-rw-r--r--src/core/hle/kernel/svc.cpp3
-rw-r--r--src/core/hle/kernel/synchronization.cpp3
-rw-r--r--src/core/hle/kernel/thread.cpp3
11 files changed, 72 insertions, 69 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index ee61f22c0..5f6dce52a 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -159,6 +159,7 @@ add_library(core STATIC
hle/kernel/k_scheduler.cpp
hle/kernel/k_scheduler.h
hle/kernel/k_scheduler_lock.h
+ hle/kernel/k_scoped_scheduler_lock_and_sleep.h
hle/kernel/kernel.cpp
hle/kernel/kernel.h
hle/kernel/memory/address_space_info.cpp
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index bc32be18b..ac4913173 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -13,6 +13,7 @@
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_scheduler.h"
+#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/time_manager.h"
@@ -157,7 +158,7 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6
Handle event_handle = InvalidHandle;
{
- SchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout);
+ KScopedSchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout);
if (current_thread->IsPendingTermination()) {
lock.CancelSleep();
@@ -227,7 +228,7 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t
Handle event_handle = InvalidHandle;
{
- SchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout);
+ KScopedSchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout);
if (current_thread->IsPendingTermination()) {
lock.CancelSleep();
diff --git a/src/core/hle/kernel/global_scheduler_context.cpp b/src/core/hle/kernel/global_scheduler_context.cpp
index 40e9adf47..a9cb48b38 100644
--- a/src/core/hle/kernel/global_scheduler_context.cpp
+++ b/src/core/hle/kernel/global_scheduler_context.cpp
@@ -44,12 +44,4 @@ bool GlobalSchedulerContext::IsLocked() const {
return scheduler_lock.IsLockedByCurrentThread();
}
-void GlobalSchedulerContext::Lock() {
- scheduler_lock.Lock();
-}
-
-void GlobalSchedulerContext::Unlock() {
- scheduler_lock.Unlock();
-}
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/global_scheduler_context.h b/src/core/hle/kernel/global_scheduler_context.h
index 40fe44cc0..39c383746 100644
--- a/src/core/hle/kernel/global_scheduler_context.h
+++ b/src/core/hle/kernel/global_scheduler_context.h
@@ -55,15 +55,7 @@ public:
private:
friend class SchedulerLock;
-
- /// Lock the scheduler to the current thread.
- void Lock();
-
- /// Unlocks the scheduler, reselects threads, interrupts cores for rescheduling
- /// and reschedules current core if needed.
- void Unlock();
-
- using LockType = KAbstractSchedulerLock<KScheduler>;
+ friend class KScopedSchedulerLockAndSleep;
KernelCore& kernel;
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 7eda89786..e75e80ad0 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -18,6 +18,7 @@
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/k_scheduler.h"
+#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
@@ -56,9 +57,9 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread(
writable_event = pair.writable;
}
+ Handle event_handle = InvalidHandle;
{
- Handle event_handle = InvalidHandle;
- SchedulerLockAndSleep lock(kernel, event_handle, thread.get(), timeout);
+ KScopedSchedulerLockAndSleep lock(kernel, event_handle, thread.get(), timeout);
thread->SetHLECallback(
[context = *this, callback](std::shared_ptr<Thread> thread) mutable -> bool {
ThreadWakeupReason reason = thread->GetSignalingResult() == RESULT_TIMEOUT
@@ -74,9 +75,8 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread(
thread->SetStatus(ThreadStatus::WaitHLEEvent);
thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT);
readable_event->AddWaitingThread(thread);
- lock.Release();
- thread->SetHLETimeEvent(event_handle);
}
+ thread->SetHLETimeEvent(event_handle);
is_thread_waiting = true;
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index c7e2eabd4..466147498 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -14,6 +14,7 @@
#include "core/core_timing.h"
#include "core/cpu_manager.h"
#include "core/hle/kernel/k_scheduler.h"
+#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/process.h"
@@ -800,28 +801,4 @@ SchedulerLock::~SchedulerLock() {
kernel.GlobalSchedulerContext().Unlock();
}
-SchedulerLockAndSleep::SchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle,
- Thread* time_task, s64 nanoseconds)
- : SchedulerLock{kernel}, event_handle{event_handle}, time_task{time_task}, nanoseconds{
- nanoseconds} {
- event_handle = InvalidHandle;
-}
-
-SchedulerLockAndSleep::~SchedulerLockAndSleep() {
- if (sleep_cancelled) {
- return;
- }
- auto& time_manager = kernel.TimeManager();
- time_manager.ScheduleTimeEvent(event_handle, time_task, nanoseconds);
-}
-
-void SchedulerLockAndSleep::Release() {
- if (sleep_cancelled) {
- return;
- }
- auto& time_manager = kernel.TimeManager();
- time_manager.ScheduleTimeEvent(event_handle, time_task, nanoseconds);
- sleep_cancelled = true;
-}
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h
index 7f020d96e..5ba0f3c32 100644
--- a/src/core/hle/kernel/k_scheduler.h
+++ b/src/core/hle/kernel/k_scheduler.h
@@ -207,23 +207,4 @@ protected:
KernelCore& kernel;
};
-class SchedulerLockAndSleep : public SchedulerLock {
-public:
- explicit SchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle, Thread* time_task,
- s64 nanoseconds);
- ~SchedulerLockAndSleep();
-
- void CancelSleep() {
- sleep_cancelled = true;
- }
-
- void Release();
-
-private:
- Handle& event_handle;
- Thread* time_task;
- s64 nanoseconds;
- bool sleep_cancelled{};
-};
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
new file mode 100644
index 000000000..f11a62216
--- /dev/null
+++ b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
@@ -0,0 +1,56 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+// This file references various implementation details from Atmosphere, an open-source firmware for
+// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
+
+#pragma once
+
+#include "common/common_types.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/thread.h"
+#include "core/hle/kernel/time_manager.h"
+
+namespace Kernel {
+
+class KScopedSchedulerLockAndSleep {
+private:
+ KernelCore& kernel;
+ s64 timeout_tick{};
+ Thread* thread{};
+ Handle* event_handle{};
+
+public:
+ explicit KScopedSchedulerLockAndSleep(KernelCore& kernel, Thread* t, s64 timeout)
+ : kernel(kernel), timeout_tick(timeout), thread(t) {
+ /* Lock the scheduler. */
+ kernel.GlobalSchedulerContext().scheduler_lock.Lock();
+ }
+
+ explicit KScopedSchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle, Thread* t,
+ s64 timeout)
+ : kernel(kernel), event_handle(&event_handle), timeout_tick(timeout), thread(t) {
+ /* Lock the scheduler. */
+ kernel.GlobalSchedulerContext().scheduler_lock.Lock();
+ }
+
+ ~KScopedSchedulerLockAndSleep() {
+ /* Register the sleep. */
+ if (this->timeout_tick > 0) {
+ auto& time_manager = kernel.TimeManager();
+ Handle handle{};
+ time_manager.ScheduleTimeEvent(event_handle ? *event_handle : handle, this->thread,
+ this->timeout_tick);
+ }
+
+ /* Unlock the scheduler. */
+ kernel.GlobalSchedulerContext().scheduler_lock.Unlock();
+ }
+
+ void CancelSleep() {
+ this->timeout_tick = 0;
+ }
+};
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 2612a6b0d..2760a307c 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -25,6 +25,7 @@
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_scheduler.h"
+#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/memory/memory_block.h"
#include "core/hle/kernel/memory/page_table.h"
@@ -1654,7 +1655,7 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add
Thread* current_thread = kernel.CurrentScheduler()->GetCurrentThread();
auto* const current_process = kernel.CurrentProcess();
{
- SchedulerLockAndSleep lock(kernel, event_handle, current_thread, nano_seconds);
+ KScopedSchedulerLockAndSleep lock(kernel, event_handle, current_thread, nano_seconds);
const auto& handle_table = current_process->GetHandleTable();
std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle);
ASSERT(thread);
diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp
index 342fb4516..6651ad90c 100644
--- a/src/core/hle/kernel/synchronization.cpp
+++ b/src/core/hle/kernel/synchronization.cpp
@@ -6,6 +6,7 @@
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_scheduler.h"
+#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/synchronization.h"
#include "core/hle/kernel/synchronization_object.h"
@@ -40,7 +41,7 @@ std::pair<ResultCode, Handle> Synchronization::WaitFor(
auto* const thread = kernel.CurrentScheduler()->GetCurrentThread();
Handle event_handle = InvalidHandle;
{
- SchedulerLockAndSleep lock(kernel, event_handle, thread, nano_seconds);
+ KScopedSchedulerLockAndSleep lock(kernel, event_handle, thread, nano_seconds);
const auto itr =
std::find_if(sync_objects.begin(), sync_objects.end(),
[thread](const std::shared_ptr<SynchronizationObject>& object) {
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 804e07f2b..6f89238ca 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -18,6 +18,7 @@
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_scheduler.h"
+#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
@@ -393,7 +394,7 @@ ResultCode Thread::SetActivity(ThreadActivity value) {
ResultCode Thread::Sleep(s64 nanoseconds) {
Handle event_handle{};
{
- SchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds);
+ KScopedSchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds);
SetStatus(ThreadStatus::WaitSleep);
}