forked from suyu/suyu
hle: kernel: Separate KScopedSchedulerLockAndSleep from k_scheduler.
This commit is contained in:
parent
8d3e06349e
commit
4756cb203e
11 changed files with 72 additions and 69 deletions
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
56
src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
Normal file
56
src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
Normal 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
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue