mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-07-04 23:31:19 +01:00
hle: kernel: KLightConditionVariable: Migrate to updated KThreadQueue.
This commit is contained in:
parent
423acf53b7
commit
5dff28290f
3 changed files with 87 additions and 54 deletions
|
@ -185,6 +185,7 @@ add_library(core STATIC
|
||||||
hle/kernel/k_event.h
|
hle/kernel/k_event.h
|
||||||
hle/kernel/k_handle_table.cpp
|
hle/kernel/k_handle_table.cpp
|
||||||
hle/kernel/k_handle_table.h
|
hle/kernel/k_handle_table.h
|
||||||
|
hle/kernel/k_light_condition_variable.cpp
|
||||||
hle/kernel/k_light_condition_variable.h
|
hle/kernel/k_light_condition_variable.h
|
||||||
hle/kernel/k_light_lock.cpp
|
hle/kernel/k_light_lock.cpp
|
||||||
hle/kernel/k_light_lock.h
|
hle/kernel/k_light_lock.h
|
||||||
|
|
80
src/core/hle/kernel/k_light_condition_variable.cpp
Normal file
80
src/core/hle/kernel/k_light_condition_variable.cpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "core/hle/kernel/k_light_condition_variable.h"
|
||||||
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
|
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
|
||||||
|
#include "core/hle/kernel/k_thread_queue.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class ThreadQueueImplForKLightConditionVariable final : public KThreadQueue {
|
||||||
|
private:
|
||||||
|
KThread::WaiterList* m_wait_list;
|
||||||
|
bool m_allow_terminating_thread;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ThreadQueueImplForKLightConditionVariable(KernelCore& kernel_, KThread::WaiterList* wl,
|
||||||
|
bool term)
|
||||||
|
: KThreadQueue(kernel_), m_wait_list(wl), m_allow_terminating_thread(term) {}
|
||||||
|
|
||||||
|
virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result,
|
||||||
|
bool cancel_timer_task) override {
|
||||||
|
// Only process waits if we're allowed to.
|
||||||
|
if (ResultTerminationRequested == wait_result && m_allow_terminating_thread) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the thread from the waiting thread from the light condition variable.
|
||||||
|
m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread));
|
||||||
|
|
||||||
|
// Invoke the base cancel wait handler.
|
||||||
|
KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_terminating_thread) {
|
||||||
|
// Create thread queue.
|
||||||
|
KThread* owner = GetCurrentThreadPointer(kernel);
|
||||||
|
|
||||||
|
ThreadQueueImplForKLightConditionVariable wait_queue(kernel, std::addressof(wait_list),
|
||||||
|
allow_terminating_thread);
|
||||||
|
|
||||||
|
// Sleep the thread.
|
||||||
|
{
|
||||||
|
KScopedSchedulerLockAndSleep lk(kernel, owner, timeout);
|
||||||
|
|
||||||
|
if (!allow_terminating_thread && owner->IsTerminationRequested()) {
|
||||||
|
lk.CancelSleep();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock->Unlock();
|
||||||
|
|
||||||
|
// Add the thread to the queue.
|
||||||
|
wait_list.push_back(*owner);
|
||||||
|
|
||||||
|
// Begin waiting.
|
||||||
|
owner->BeginWait(std::addressof(wait_queue));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-acquire the lock.
|
||||||
|
lock->Lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KLightConditionVariable::Broadcast() {
|
||||||
|
KScopedSchedulerLock lk(kernel);
|
||||||
|
|
||||||
|
// Signal all threads.
|
||||||
|
for (auto it = wait_list.begin(); it != wait_list.end(); it = wait_list.erase(it)) {
|
||||||
|
it->EndWait(ResultSuccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Kernel
|
|
@ -1,73 +1,25 @@
|
||||||
// Copyright 2020 yuzu Emulator Project
|
// Copyright 2021 yuzu Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// 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
|
#pragma once
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/kernel/k_scheduler.h"
|
#include "core/hle/kernel/k_thread.h"
|
||||||
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
|
|
||||||
#include "core/hle/kernel/time_manager.h"
|
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
class KernelCore;
|
class KernelCore;
|
||||||
|
class KLightLock;
|
||||||
|
|
||||||
class KLightConditionVariable {
|
class KLightConditionVariable {
|
||||||
public:
|
public:
|
||||||
explicit KLightConditionVariable(KernelCore& kernel_) : kernel{kernel_} {}
|
explicit KLightConditionVariable(KernelCore& kernel_) : kernel{kernel_} {}
|
||||||
|
|
||||||
void Wait(KLightLock* lock, s64 timeout = -1, bool allow_terminating_thread = true) {
|
void Wait(KLightLock* lock, s64 timeout = -1, bool allow_terminating_thread = true);
|
||||||
WaitImpl(lock, timeout, allow_terminating_thread);
|
void Broadcast();
|
||||||
}
|
|
||||||
|
|
||||||
void Broadcast() {
|
|
||||||
KScopedSchedulerLock lk{kernel};
|
|
||||||
|
|
||||||
// Signal all threads.
|
|
||||||
for (auto& thread : wait_list) {
|
|
||||||
thread.SetState(ThreadState::Runnable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void WaitImpl(KLightLock* lock, s64 timeout, bool allow_terminating_thread) {
|
|
||||||
KThread* owner = GetCurrentThreadPointer(kernel);
|
|
||||||
|
|
||||||
// Sleep the thread.
|
|
||||||
{
|
|
||||||
KScopedSchedulerLockAndSleep lk{kernel, owner, timeout};
|
|
||||||
|
|
||||||
if (!allow_terminating_thread && owner->IsTerminationRequested()) {
|
|
||||||
lk.CancelSleep();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock->Unlock();
|
|
||||||
|
|
||||||
// Set the thread as waiting.
|
|
||||||
GetCurrentThread(kernel).SetState(ThreadState::Waiting);
|
|
||||||
|
|
||||||
// Add the thread to the queue.
|
|
||||||
wait_list.push_back(GetCurrentThread(kernel));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the thread from the wait list.
|
|
||||||
{
|
|
||||||
KScopedSchedulerLock sl{kernel};
|
|
||||||
|
|
||||||
wait_list.erase(wait_list.iterator_to(GetCurrentThread(kernel)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cancel the task that the sleep setup.
|
|
||||||
kernel.TimeManager().UnscheduleTimeEvent(owner);
|
|
||||||
|
|
||||||
// Re-acquire the lock.
|
|
||||||
lock->Lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelCore& kernel;
|
KernelCore& kernel;
|
||||||
KThread::WaiterList wait_list{};
|
KThread::WaiterList wait_list{};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue