hle: kernel: Separate KScopedSchedulerLockAndSleep from k_scheduler.

This commit is contained in:
bunnei 2020-12-03 21:56:02 -08:00
parent 8d3e06349e
commit 4756cb203e
11 changed files with 72 additions and 69 deletions

View File

@ -159,6 +159,7 @@ add_library(core STATIC
hle/kernel/k_scheduler.cpp hle/kernel/k_scheduler.cpp
hle/kernel/k_scheduler.h hle/kernel/k_scheduler.h
hle/kernel/k_scheduler_lock.h hle/kernel/k_scheduler_lock.h
hle/kernel/k_scoped_scheduler_lock_and_sleep.h
hle/kernel/kernel.cpp hle/kernel/kernel.cpp
hle/kernel/kernel.h hle/kernel/kernel.h
hle/kernel/memory/address_space_info.cpp hle/kernel/memory/address_space_info.cpp

View File

@ -13,6 +13,7 @@
#include "core/hle/kernel/errors.h" #include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_scheduler.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/kernel.h"
#include "core/hle/kernel/thread.h" #include "core/hle/kernel/thread.h"
#include "core/hle/kernel/time_manager.h" #include "core/hle/kernel/time_manager.h"
@ -157,7 +158,7 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6
Handle event_handle = InvalidHandle; Handle event_handle = InvalidHandle;
{ {
SchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout); KScopedSchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout);
if (current_thread->IsPendingTermination()) { if (current_thread->IsPendingTermination()) {
lock.CancelSleep(); lock.CancelSleep();
@ -227,7 +228,7 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t
Handle event_handle = InvalidHandle; Handle event_handle = InvalidHandle;
{ {
SchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout); KScopedSchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout);
if (current_thread->IsPendingTermination()) { if (current_thread->IsPendingTermination()) {
lock.CancelSleep(); lock.CancelSleep();

View File

@ -44,12 +44,4 @@ bool GlobalSchedulerContext::IsLocked() const {
return scheduler_lock.IsLockedByCurrentThread(); return scheduler_lock.IsLockedByCurrentThread();
} }
void GlobalSchedulerContext::Lock() {
scheduler_lock.Lock();
}
void GlobalSchedulerContext::Unlock() {
scheduler_lock.Unlock();
}
} // namespace Kernel } // namespace Kernel

View File

@ -55,15 +55,7 @@ public:
private: private:
friend class SchedulerLock; friend class SchedulerLock;
friend class KScopedSchedulerLockAndSleep;
/// 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>;
KernelCore& kernel; KernelCore& kernel;

View File

@ -18,6 +18,7 @@
#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/k_scheduler.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/kernel.h"
#include "core/hle/kernel/object.h" #include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
@ -56,9 +57,9 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread(
writable_event = pair.writable; 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( thread->SetHLECallback(
[context = *this, callback](std::shared_ptr<Thread> thread) mutable -> bool { [context = *this, callback](std::shared_ptr<Thread> thread) mutable -> bool {
ThreadWakeupReason reason = thread->GetSignalingResult() == RESULT_TIMEOUT ThreadWakeupReason reason = thread->GetSignalingResult() == RESULT_TIMEOUT
@ -74,9 +75,8 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread(
thread->SetStatus(ThreadStatus::WaitHLEEvent); thread->SetStatus(ThreadStatus::WaitHLEEvent);
thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT); thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT);
readable_event->AddWaitingThread(thread); readable_event->AddWaitingThread(thread);
lock.Release();
thread->SetHLETimeEvent(event_handle);
} }
thread->SetHLETimeEvent(event_handle);
is_thread_waiting = true; is_thread_waiting = true;

View File

@ -14,6 +14,7 @@
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/cpu_manager.h" #include "core/cpu_manager.h"
#include "core/hle/kernel/k_scheduler.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/kernel.h"
#include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
@ -800,28 +801,4 @@ SchedulerLock::~SchedulerLock() {
kernel.GlobalSchedulerContext().Unlock(); 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 } // namespace Kernel

View File

@ -207,23 +207,4 @@ protected:
KernelCore& kernel; 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 } // namespace Kernel

View File

@ -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

View File

@ -25,6 +25,7 @@
#include "core/hle/kernel/errors.h" #include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_scheduler.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/kernel.h"
#include "core/hle/kernel/memory/memory_block.h" #include "core/hle/kernel/memory/memory_block.h"
#include "core/hle/kernel/memory/page_table.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(); Thread* current_thread = kernel.CurrentScheduler()->GetCurrentThread();
auto* const current_process = kernel.CurrentProcess(); 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(); const auto& handle_table = current_process->GetHandleTable();
std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle); std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle);
ASSERT(thread); ASSERT(thread);

View File

@ -6,6 +6,7 @@
#include "core/hle/kernel/errors.h" #include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_scheduler.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/kernel.h"
#include "core/hle/kernel/synchronization.h" #include "core/hle/kernel/synchronization.h"
#include "core/hle/kernel/synchronization_object.h" #include "core/hle/kernel/synchronization_object.h"
@ -40,7 +41,7 @@ std::pair<ResultCode, Handle> Synchronization::WaitFor(
auto* const thread = kernel.CurrentScheduler()->GetCurrentThread(); auto* const thread = kernel.CurrentScheduler()->GetCurrentThread();
Handle event_handle = InvalidHandle; Handle event_handle = InvalidHandle;
{ {
SchedulerLockAndSleep lock(kernel, event_handle, thread, nano_seconds); KScopedSchedulerLockAndSleep lock(kernel, event_handle, thread, nano_seconds);
const auto itr = const auto itr =
std::find_if(sync_objects.begin(), sync_objects.end(), std::find_if(sync_objects.begin(), sync_objects.end(),
[thread](const std::shared_ptr<SynchronizationObject>& object) { [thread](const std::shared_ptr<SynchronizationObject>& object) {

View File

@ -18,6 +18,7 @@
#include "core/hle/kernel/errors.h" #include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_scheduler.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/kernel.h"
#include "core/hle/kernel/object.h" #include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
@ -393,7 +394,7 @@ ResultCode Thread::SetActivity(ThreadActivity value) {
ResultCode Thread::Sleep(s64 nanoseconds) { ResultCode Thread::Sleep(s64 nanoseconds) {
Handle event_handle{}; Handle event_handle{};
{ {
SchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds); KScopedSchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds);
SetStatus(ThreadStatus::WaitSleep); SetStatus(ThreadStatus::WaitSleep);
} }