Browse Source
Merge pull request #7462 from bunnei/kernel-improve-scheduling
Merge pull request #7462 from bunnei/kernel-improve-scheduling
Kernel: Improve threading & scheduling V3nce_cpp
committed by
GitHub
32 changed files with 895 additions and 634 deletions
-
2src/core/CMakeLists.txt
-
6src/core/core.cpp
-
3src/core/core.h
-
23src/core/cpu_manager.cpp
-
92src/core/hle/kernel/k_address_arbiter.cpp
-
4src/core/hle/kernel/k_auto_object.h
-
245src/core/hle/kernel/k_condition_variable.cpp
-
2src/core/hle/kernel/k_condition_variable.h
-
6src/core/hle/kernel/k_handle_table.cpp
-
2src/core/hle/kernel/k_handle_table.h
-
80src/core/hle/kernel/k_light_condition_variable.cpp
-
58src/core/hle/kernel/k_light_condition_variable.h
-
72src/core/hle/kernel/k_light_lock.cpp
-
2src/core/hle/kernel/k_light_lock.h
-
28src/core/hle/kernel/k_process.cpp
-
1src/core/hle/kernel/k_process.h
-
101src/core/hle/kernel/k_scheduler.cpp
-
2src/core/hle/kernel/k_scheduler.h
-
10src/core/hle/kernel/k_scheduler_lock.h
-
1src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
-
3src/core/hle/kernel/k_server_session.cpp
-
151src/core/hle/kernel/k_synchronization_object.cpp
-
32src/core/hle/kernel/k_synchronization_object.h
-
246src/core/hle/kernel/k_thread.cpp
-
72src/core/hle/kernel/k_thread.h
-
51src/core/hle/kernel/k_thread_queue.cpp
-
74src/core/hle/kernel/k_thread_queue.h
-
81src/core/hle/kernel/kernel.cpp
-
5src/core/hle/kernel/kernel.h
-
33src/core/hle/kernel/service_thread.cpp
-
35src/core/hle/kernel/svc.cpp
-
6src/core/hle/kernel/time_manager.cpp
@ -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 { |
|||
public: |
|||
ThreadQueueImplForKLightConditionVariable(KernelCore& kernel_, KThread::WaiterList* wl, |
|||
bool term) |
|||
: KThreadQueue(kernel_), m_wait_list(wl), m_allow_terminating_thread(term) {} |
|||
|
|||
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); |
|||
} |
|||
|
|||
private: |
|||
KThread::WaiterList* m_wait_list; |
|||
bool m_allow_terminating_thread; |
|||
}; |
|||
|
|||
} // 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
|
|||
@ -0,0 +1,51 @@ |
|||
// Copyright 2021 yuzu Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#pragma once
|
|||
|
|||
#include "core/hle/kernel/k_thread_queue.h"
|
|||
#include "core/hle/kernel/kernel.h"
|
|||
#include "core/hle/kernel/time_manager.h"
|
|||
|
|||
namespace Kernel { |
|||
|
|||
void KThreadQueue::NotifyAvailable([[maybe_unused]] KThread* waiting_thread, |
|||
[[maybe_unused]] KSynchronizationObject* signaled_object, |
|||
[[maybe_unused]] ResultCode wait_result) {} |
|||
|
|||
void KThreadQueue::EndWait(KThread* waiting_thread, ResultCode wait_result) { |
|||
// Set the thread's wait result.
|
|||
waiting_thread->SetWaitResult(wait_result); |
|||
|
|||
// Set the thread as runnable.
|
|||
waiting_thread->SetState(ThreadState::Runnable); |
|||
|
|||
// Clear the thread's wait queue.
|
|||
waiting_thread->ClearWaitQueue(); |
|||
|
|||
// Cancel the thread task.
|
|||
kernel.TimeManager().UnscheduleTimeEvent(waiting_thread); |
|||
} |
|||
|
|||
void KThreadQueue::CancelWait(KThread* waiting_thread, ResultCode wait_result, |
|||
bool cancel_timer_task) { |
|||
// Set the thread's wait result.
|
|||
waiting_thread->SetWaitResult(wait_result); |
|||
|
|||
// Set the thread as runnable.
|
|||
waiting_thread->SetState(ThreadState::Runnable); |
|||
|
|||
// Clear the thread's wait queue.
|
|||
waiting_thread->ClearWaitQueue(); |
|||
|
|||
// Cancel the thread task.
|
|||
if (cancel_timer_task) { |
|||
kernel.TimeManager().UnscheduleTimeEvent(waiting_thread); |
|||
} |
|||
} |
|||
|
|||
void KThreadQueueWithoutEndWait::EndWait([[maybe_unused]] KThread* waiting_thread, |
|||
[[maybe_unused]] ResultCode wait_result) {} |
|||
|
|||
} // namespace Kernel
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue