summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFernando Sahmkow <fsahmkow27@gmail.com>2020-04-01 23:28:49 +0200
committerFernando Sahmkow <fsahmkow27@gmail.com>2020-06-27 17:36:05 +0200
commit48fa3b7a0f2054a836b0a8061e6b082c246b5ae0 (patch)
tree37a09cfb55f13ebf2df2b9a71622c599733100b0
parentKernel/svcBreak: Implement CacheInvalidation for Singlecore and correct svcBreak. (diff)
downloadyuzu-48fa3b7a0f2054a836b0a8061e6b082c246b5ae0.tar
yuzu-48fa3b7a0f2054a836b0a8061e6b082c246b5ae0.tar.gz
yuzu-48fa3b7a0f2054a836b0a8061e6b082c246b5ae0.tar.bz2
yuzu-48fa3b7a0f2054a836b0a8061e6b082c246b5ae0.tar.lz
yuzu-48fa3b7a0f2054a836b0a8061e6b082c246b5ae0.tar.xz
yuzu-48fa3b7a0f2054a836b0a8061e6b082c246b5ae0.tar.zst
yuzu-48fa3b7a0f2054a836b0a8061e6b082c246b5ae0.zip
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp1
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp1
-rw-r--r--src/core/core_manager.cpp51
-rw-r--r--src/core/core_manager.h63
-rw-r--r--src/core/gdbstub/gdbstub.cpp1
-rw-r--r--src/core/hle/kernel/client_port.cpp2
-rw-r--r--src/core/hle/kernel/kernel.cpp81
-rw-r--r--src/core/hle/kernel/kernel.h3
-rw-r--r--src/core/hle/kernel/svc.cpp3
-rw-r--r--src/core/hle/kernel/synchronization_object.cpp64
-rw-r--r--src/core/hle/kernel/synchronization_object.h15
-rw-r--r--src/core/hle/kernel/thread.cpp34
-rw-r--r--src/core/hle/kernel/thread.h56
-rw-r--r--src/core/hle/service/sm/sm.cpp2
-rw-r--r--src/core/host_timing.cpp206
-rw-r--r--src/core/host_timing.h160
-rw-r--r--src/tests/core/core_timing.cpp1
-rw-r--r--src/yuzu/debugger/wait_tree.cpp2
19 files changed, 8 insertions, 740 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 552094ddb..653b7620b 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -17,8 +17,6 @@ add_library(core STATIC
constants.h
core.cpp
core.h
- core_manager.cpp
- core_manager.h
core_timing.cpp
core_timing.h
core_timing_util.cpp
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index c4aeedef9..c8adf2866 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -12,7 +12,6 @@
#include "core/arm/dynarmic/arm_dynarmic_64.h"
#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
#include "core/core.h"
-#include "core/core_manager.h"
#include "core/core_timing.h"
#include "core/hle/kernel/svc.h"
#include "core/memory.h"
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index a518733b6..14b394368 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -11,7 +11,6 @@
#include "core/arm/cpu_interrupt_handler.h"
#include "core/arm/dynarmic/arm_dynarmic_64.h"
#include "core/core.h"
-#include "core/core_manager.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/gdbstub/gdbstub.h"
diff --git a/src/core/core_manager.cpp b/src/core/core_manager.cpp
deleted file mode 100644
index 82d7acb40..000000000
--- a/src/core/core_manager.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2018 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <condition_variable>
-#include <mutex>
-
-#include "common/logging/log.h"
-#include "core/arm/exclusive_monitor.h"
-#include "core/arm/unicorn/arm_unicorn.h"
-#include "core/core.h"
-#include "core/core_manager.h"
-#include "core/core_timing.h"
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/physical_core.h"
-#include "core/hle/kernel/scheduler.h"
-#include "core/hle/kernel/thread.h"
-#include "core/hle/lock.h"
-#include "core/settings.h"
-
-namespace Core {
-
-CoreManager::CoreManager(System& system, std::size_t core_index)
- : global_scheduler{system.GlobalScheduler()}, physical_core{system.Kernel().PhysicalCore(
- core_index)},
- core_timing{system.CoreTiming()}, core_index{core_index} {}
-
-CoreManager::~CoreManager() = default;
-
-void CoreManager::RunLoop(bool tight_loop) {
- /// Deprecated
-}
-
-void CoreManager::SingleStep() {
- return RunLoop(false);
-}
-
-void CoreManager::PrepareReschedule() {
- //physical_core.Stop();
-}
-
-void CoreManager::Reschedule() {
- // Lock the global kernel mutex when we manipulate the HLE state
- std::lock_guard lock(HLE::g_hle_lock);
-
- // global_scheduler.SelectThread(core_index);
-
- physical_core.Scheduler().TryDoContextSwitch();
-}
-
-} // namespace Core
diff --git a/src/core/core_manager.h b/src/core/core_manager.h
deleted file mode 100644
index d525de00a..000000000
--- a/src/core/core_manager.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2018 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <atomic>
-#include <cstddef>
-#include <memory>
-#include "common/common_types.h"
-
-namespace Kernel {
-class GlobalScheduler;
-class PhysicalCore;
-} // namespace Kernel
-
-namespace Core {
-class System;
-}
-
-namespace Core::Timing {
-class CoreTiming;
-}
-
-namespace Core::Memory {
-class Memory;
-}
-
-namespace Core {
-
-constexpr unsigned NUM_CPU_CORES{4};
-
-class CoreManager {
-public:
- CoreManager(System& system, std::size_t core_index);
- ~CoreManager();
-
- void RunLoop(bool tight_loop = true);
-
- void SingleStep();
-
- void PrepareReschedule();
-
- bool IsMainCore() const {
- return core_index == 0;
- }
-
- std::size_t CoreIndex() const {
- return core_index;
- }
-
-private:
- void Reschedule();
-
- Kernel::GlobalScheduler& global_scheduler;
- Kernel::PhysicalCore& physical_core;
- Timing::CoreTiming& core_timing;
-
- std::atomic<bool> reschedule_pending = false;
- std::size_t core_index;
-};
-
-} // namespace Core
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index 70c0f8b80..79f22a403 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -35,7 +35,6 @@
#include "common/swap.h"
#include "core/arm/arm_interface.h"
#include "core/core.h"
-#include "core/core_manager.h"
#include "core/gdbstub/gdbstub.h"
#include "core/hle/kernel/memory/page_table.h"
#include "core/hle/kernel/process.h"
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index 5498fd313..8aff2227a 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -34,7 +34,7 @@ ResultVal<std::shared_ptr<ClientSession>> ClientPort::Connect() {
}
// Wake the threads waiting on the ServerPort
- server_port->WakeupAllWaitingThreads();
+ server_port->Signal();
return MakeResult(std::move(client));
}
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 1f230fc4a..dbb75416d 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -48,72 +48,6 @@ MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
namespace Kernel {
-/**
- * Callback that will wake up the thread it was scheduled for
- * @param thread_handle The handle of the thread that's been awoken
- * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time
- */
-static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_late) {
- UNREACHABLE();
- const auto proper_handle = static_cast<Handle>(thread_handle);
- const auto& system = Core::System::GetInstance();
-
- // Lock the global kernel mutex when we enter the kernel HLE.
- std::lock_guard lock{HLE::g_hle_lock};
-
- std::shared_ptr<Thread> thread =
- system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle);
- if (thread == nullptr) {
- LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle);
- return;
- }
-
- bool resume = true;
-
- if (thread->GetStatus() == ThreadStatus::WaitSynch ||
- thread->GetStatus() == ThreadStatus::WaitHLEEvent) {
- // Remove the thread from each of its waiting objects' waitlists
- for (const auto& object : thread->GetSynchronizationObjects()) {
- object->RemoveWaitingThread(thread);
- }
- thread->ClearSynchronizationObjects();
-
- // Invoke the wakeup callback before clearing the wait objects
- if (thread->HasWakeupCallback()) {
- resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Timeout, thread, nullptr, 0);
- }
- } else if (thread->GetStatus() == ThreadStatus::WaitMutex ||
- thread->GetStatus() == ThreadStatus::WaitCondVar) {
- thread->SetMutexWaitAddress(0);
- thread->SetWaitHandle(0);
- if (thread->GetStatus() == ThreadStatus::WaitCondVar) {
- thread->GetOwnerProcess()->RemoveConditionVariableThread(thread);
- thread->SetCondVarWaitAddress(0);
- }
-
- auto* const lock_owner = thread->GetLockOwner();
- // Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance
- // and don't have a lock owner unless SignalProcessWideKey was called first and the thread
- // wasn't awakened due to the mutex already being acquired.
- if (lock_owner != nullptr) {
- lock_owner->RemoveMutexWaiter(thread);
- }
- }
-
- if (thread->GetStatus() == ThreadStatus::WaitArb) {
- auto& address_arbiter = thread->GetOwnerProcess()->GetAddressArbiter();
- address_arbiter.HandleWakeupThread(thread);
- }
-
- if (resume) {
- if (thread->GetStatus() == ThreadStatus::WaitCondVar ||
- thread->GetStatus() == ThreadStatus::WaitArb) {
- thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
- }
- thread->ResumeFromWait();
- }
-}
-
struct KernelCore::Impl {
explicit Impl(Core::System& system, KernelCore& kernel)
: global_scheduler{kernel}, synchronization{system}, time_manager{system}, system{system} {}
@@ -129,7 +63,6 @@ struct KernelCore::Impl {
InitializePhysicalCores();
InitializeSystemResourceLimit(kernel);
InitializeMemoryLayout();
- InitializeThreads();
InitializePreemption(kernel);
InitializeSchedulers();
InitializeSuspendThreads();
@@ -161,7 +94,6 @@ struct KernelCore::Impl {
system_resource_limit = nullptr;
global_handle_table.Clear();
- thread_wakeup_event_type = nullptr;
preemption_event = nullptr;
global_scheduler.Shutdown();
@@ -210,11 +142,6 @@ struct KernelCore::Impl {
}
}
- void InitializeThreads() {
- thread_wakeup_event_type =
- Core::Timing::CreateEvent("ThreadWakeupCallback", ThreadWakeupCallback);
- }
-
void InitializePreemption(KernelCore& kernel) {
preemption_event = Core::Timing::CreateEvent(
"PreemptionCallback", [this, &kernel](u64 userdata, s64 cycles_late) {
@@ -376,7 +303,6 @@ struct KernelCore::Impl {
std::shared_ptr<ResourceLimit> system_resource_limit;
- std::shared_ptr<Core::Timing::EventType> thread_wakeup_event_type;
std::shared_ptr<Core::Timing::EventType> preemption_event;
// This is the kernel's handle table or supervisor handle table which
@@ -516,7 +442,8 @@ std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore
return impl->interrupts;
}
-const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts() const {
+const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts()
+ const {
return impl->interrupts;
}
@@ -595,10 +522,6 @@ u64 KernelCore::CreateNewUserProcessID() {
return impl->next_user_process_id++;
}
-const std::shared_ptr<Core::Timing::EventType>& KernelCore::ThreadWakeupCallbackEventType() const {
- return impl->thread_wakeup_event_type;
-}
-
Kernel::HandleTable& KernelCore::GlobalHandleTable() {
return impl->global_handle_table;
}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 846056b85..49bd47e89 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -241,9 +241,6 @@ private:
/// Creates a new thread ID, incrementing the internal thread ID counter.
u64 CreateNewThreadID();
- /// Retrieves the event type used for thread wakeup callbacks.
- const std::shared_ptr<Core::Timing::EventType>& ThreadWakeupCallbackEventType() const;
-
/// Provides a reference to the global handle table.
Kernel::HandleTable& GlobalHandleTable();
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index dbd35580e..781032cd1 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -16,7 +16,6 @@
#include "common/string_util.h"
#include "core/arm/exclusive_monitor.h"
#include "core/core.h"
-#include "core/core_manager.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/cpu_manager.h"
@@ -1909,7 +1908,7 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle,
return ERR_INVALID_COMBINATION;
}
- if (core < Core::NUM_CPU_CORES) {
+ if (core < Core::Hardware::NUM_CPU_CORES) {
if ((affinity_mask & (1ULL << core)) == 0) {
LOG_ERROR(Kernel_SVC,
"Core is not enabled for the current mask, core={}, mask={:016X}", core,
diff --git a/src/core/hle/kernel/synchronization_object.cpp b/src/core/hle/kernel/synchronization_object.cpp
index be9e09106..ba4d39157 100644
--- a/src/core/hle/kernel/synchronization_object.cpp
+++ b/src/core/hle/kernel/synchronization_object.cpp
@@ -38,70 +38,6 @@ void SynchronizationObject::RemoveWaitingThread(std::shared_ptr<Thread> thread)
waiting_threads.erase(itr);
}
-std::shared_ptr<Thread> SynchronizationObject::GetHighestPriorityReadyThread() const {
- Thread* candidate = nullptr;
- u32 candidate_priority = THREADPRIO_LOWEST + 1;
-
- for (const auto& thread : waiting_threads) {
- const ThreadStatus thread_status = thread->GetStatus();
-
- // The list of waiting threads must not contain threads that are not waiting to be awakened.
- ASSERT_MSG(thread_status == ThreadStatus::WaitSynch ||
- thread_status == ThreadStatus::WaitHLEEvent,
- "Inconsistent thread statuses in waiting_threads");
-
- if (thread->GetPriority() >= candidate_priority)
- continue;
-
- if (ShouldWait(thread.get()))
- continue;
-
- candidate = thread.get();
- candidate_priority = thread->GetPriority();
- }
-
- return SharedFrom(candidate);
-}
-
-void SynchronizationObject::WakeupWaitingThread(std::shared_ptr<Thread> thread) {
- ASSERT(!ShouldWait(thread.get()));
-
- if (!thread) {
- return;
- }
-
- if (thread->IsSleepingOnWait()) {
- for (const auto& object : thread->GetSynchronizationObjects()) {
- ASSERT(!object->ShouldWait(thread.get()));
- object->Acquire(thread.get());
- }
- } else {
- Acquire(thread.get());
- }
-
- const std::size_t index = thread->GetSynchronizationObjectIndex(SharedFrom(this));
-
- thread->ClearSynchronizationObjects();
-
- thread->CancelWakeupTimer();
-
- bool resume = true;
- if (thread->HasWakeupCallback()) {
- resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Signal, thread, SharedFrom(this),
- index);
- }
- if (resume) {
- thread->ResumeFromWait();
- kernel.PrepareReschedule(thread->GetProcessorID());
- }
-}
-
-void SynchronizationObject::WakeupAllWaitingThreads() {
- while (auto thread = GetHighestPriorityReadyThread()) {
- WakeupWaitingThread(thread);
- }
-}
-
void SynchronizationObject::ClearWaitingThreads() {
waiting_threads.clear();
}
diff --git a/src/core/hle/kernel/synchronization_object.h b/src/core/hle/kernel/synchronization_object.h
index a35544ac1..f89b24204 100644
--- a/src/core/hle/kernel/synchronization_object.h
+++ b/src/core/hle/kernel/synchronization_object.h
@@ -50,21 +50,6 @@ public:
*/
void RemoveWaitingThread(std::shared_ptr<Thread> thread);
- /**
- * Wake up all threads waiting on this object that can be awoken, in priority order,
- * and set the synchronization result and output of the thread.
- */
- void /* deprecated */ WakeupAllWaitingThreads();
-
- /**
- * Wakes up a single thread waiting on this object.
- * @param thread Thread that is waiting on this object to wakeup.
- */
- void WakeupWaitingThread(std::shared_ptr<Thread> thread);
-
- /// Obtains the highest priority thread that is ready to run from this object's waiting list.
- std::shared_ptr<Thread> /* deprecated */ GetHighestPriorityReadyThread() const;
-
/// Get a const reference to the waiting threads list for debug use
const std::vector<std::shared_ptr<Thread>>& GetWaitingThreads() const;
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index d88039a16..fba2a9c85 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -56,9 +56,6 @@ Thread::~Thread() = default;
void Thread::Stop() {
{
SchedulerLock lock(kernel);
- // Cancel any outstanding wakeup events for this thread
- Core::System::GetInstance().CoreTiming().UnscheduleEvent(
- kernel.ThreadWakeupCallbackEventType(), global_handle);
SetStatus(ThreadStatus::Dead);
Signal();
kernel.GlobalHandleTable().Close(global_handle);
@@ -75,22 +72,6 @@ void Thread::Stop() {
global_handle = 0;
}
-void Thread::WakeAfterDelay(s64 nanoseconds) {
- // Don't schedule a wakeup if the thread wants to wait forever
- if (nanoseconds == -1)
- return;
-
- // This function might be called from any thread so we have to be cautious and use the
- // thread-safe version of ScheduleEvent.
- Core::System::GetInstance().CoreTiming().ScheduleEvent(
- nanoseconds, kernel.ThreadWakeupCallbackEventType(), global_handle);
-}
-
-void Thread::CancelWakeupTimer() {
- Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(),
- global_handle);
-}
-
void Thread::ResumeFromWait() {
SchedulerLock lock(kernel);
switch (status) {
@@ -284,14 +265,6 @@ void Thread::SetPriority(u32 priority) {
UpdatePriority();
}
-void Thread::SetWaitSynchronizationResult(ResultCode result) {
- UNREACHABLE();
-}
-
-void Thread::SetWaitSynchronizationOutput(s32 output) {
- UNREACHABLE();
-}
-
void Thread::SetSynchronizationResults(SynchronizationObject* object, ResultCode result) {
signaling_object = object;
signaling_result = result;
@@ -425,13 +398,6 @@ bool Thread::AllSynchronizationObjectsReady() const {
});
}
-bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
- std::shared_ptr<SynchronizationObject> object,
- std::size_t index) {
- ASSERT(wakeup_callback);
- return wakeup_callback(reason, std::move(thread), std::move(object), index);
-}
-
bool Thread::InvokeHLECallback(std::shared_ptr<Thread> thread) {
ASSERT(hle_callback);
return hle_callback(std::move(thread));
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 61963148d..3ae0df6ef 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -128,9 +128,6 @@ public:
using ThreadSynchronizationObjects = std::vector<std::shared_ptr<SynchronizationObject>>;
- using WakeupCallback =
- std::function<bool(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
- std::shared_ptr<SynchronizationObject> object, std::size_t index)>;
using HLECallback = std::function<bool(std::shared_ptr<Thread> thread)>;
/**
@@ -235,7 +232,7 @@ public:
}
/// Resumes a thread from waiting
- void /* deprecated */ ResumeFromWait();
+ void ResumeFromWait();
void OnWakeUp();
@@ -249,27 +246,6 @@ public:
///
void CancelWait();
- /**
- * Schedules an event to wake up the specified thread after the specified delay
- * @param nanoseconds The time this thread will be allowed to sleep for
- */
- void /* deprecated */ WakeAfterDelay(s64 nanoseconds);
-
- /// Cancel any outstanding wakeup events for this thread
- void /* deprecated */ CancelWakeupTimer();
-
- /**
- * Sets the result after the thread awakens (from svcWaitSynchronization)
- * @param result Value to set to the returned result
- */
- void /*deprecated*/ SetWaitSynchronizationResult(ResultCode result);
-
- /**
- * Sets the output parameter value after the thread awakens (from svcWaitSynchronization)
- * @param output Value to set to the output parameter
- */
- void /*deprecated*/ SetWaitSynchronizationOutput(s32 output);
-
void SetSynchronizationResults(SynchronizationObject* object, ResultCode result);
Core::ARM_Interface& ArmInterface();
@@ -330,11 +306,6 @@ public:
*/
VAddr GetCommandBufferAddress() const;
- /// Returns whether this thread is waiting on objects from a WaitSynchronization call.
- bool IsSleepingOnWait() const {
- return status == ThreadStatus::WaitSynch;
- }
-
ThreadContext32& GetContext32() {
return context_32;
}
@@ -469,18 +440,10 @@ public:
arb_wait_address = address;
}
- bool HasWakeupCallback() const {
- return wakeup_callback != nullptr;
- }
-
bool HasHLECallback() const {
return hle_callback != nullptr;
}
- void SetWakeupCallback(WakeupCallback callback) {
- wakeup_callback = std::move(callback);
- }
-
void SetHLECallback(HLECallback callback) {
hle_callback = std::move(callback);
}
@@ -501,22 +464,10 @@ public:
return hle_object;
}
- void InvalidateWakeupCallback() {
- SetWakeupCallback(nullptr);
- }
-
void InvalidateHLECallback() {
SetHLECallback(nullptr);
}
- /**
- * Invokes the thread's wakeup callback.
- *
- * @pre A valid wakeup callback has been set. Violating this precondition
- * will cause an assertion to trigger.
- */
- bool InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
- std::shared_ptr<SynchronizationObject> object, std::size_t index);
bool InvokeHLECallback(std::shared_ptr<Thread> thread);
u32 GetIdealCore() const {
@@ -698,11 +649,6 @@ private:
/// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
Handle global_handle = 0;
- /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
- /// was waiting via WaitSynchronization then the object will be the last object that became
- /// available. In case of a timeout, the object will be nullptr. DEPRECATED
- WakeupCallback wakeup_callback;
-
/// Callback for HLE Events
HLECallback hle_callback;
Handle hle_time_event;
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 6ada13be4..d872de16c 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -142,7 +142,7 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
}
// Wake the threads waiting on the ServerPort
- server_port->WakeupAllWaitingThreads();
+ server_port->Signal();
LOG_DEBUG(Service_SM, "called service={} -> session={}", name, client->GetObjectId());
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
diff --git a/src/core/host_timing.cpp b/src/core/host_timing.cpp
deleted file mode 100644
index 2f40de1a1..000000000
--- a/src/core/host_timing.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/host_timing.h"
-
-#include <algorithm>
-#include <mutex>
-#include <string>
-#include <tuple>
-
-#include "common/assert.h"
-#include "core/core_timing_util.h"
-
-namespace Core::HostTiming {
-
-std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
- return std::make_shared<EventType>(std::move(callback), std::move(name));
-}
-
-struct CoreTiming::Event {
- u64 time;
- u64 fifo_order;
- u64 userdata;
- std::weak_ptr<EventType> type;
-
- // Sort by time, unless the times are the same, in which case sort by
- // the order added to the queue
- friend bool operator>(const Event& left, const Event& right) {
- return std::tie(left.time, left.fifo_order) > std::tie(right.time, right.fifo_order);
- }
-
- friend bool operator<(const Event& left, const Event& right) {
- return std::tie(left.time, left.fifo_order) < std::tie(right.time, right.fifo_order);
- }
-};
-
-CoreTiming::CoreTiming() {
- clock =
- Common::CreateBestMatchingClock(Core::Hardware::BASE_CLOCK_RATE, Core::Hardware::CNTFREQ);
-}
-
-CoreTiming::~CoreTiming() = default;
-
-void CoreTiming::ThreadEntry(CoreTiming& instance) {
- instance.ThreadLoop();
-}
-
-void CoreTiming::Initialize() {
- event_fifo_id = 0;
- const auto empty_timed_callback = [](u64, s64) {};
- ev_lost = CreateEvent("_lost_event", empty_timed_callback);
- timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this));
-}
-
-void CoreTiming::Shutdown() {
- paused = true;
- shutting_down = true;
- event.Set();
- timer_thread->join();
- ClearPendingEvents();
- timer_thread.reset();
- has_started = false;
-}
-
-void CoreTiming::Pause(bool is_paused) {
- paused = is_paused;
-}
-
-void CoreTiming::SyncPause(bool is_paused) {
- if (is_paused == paused && paused_set == paused) {
- return;
- }
- Pause(is_paused);
- event.Set();
- while (paused_set != is_paused)
- ;
-}
-
-bool CoreTiming::IsRunning() const {
- return !paused_set;
-}
-
-bool CoreTiming::HasPendingEvents() const {
- return !(wait_set && event_queue.empty());
-}
-
-void CoreTiming::ScheduleEvent(s64 ns_into_future, const std::shared_ptr<EventType>& event_type,
- u64 userdata) {
- basic_lock.lock();
- const u64 timeout = static_cast<u64>(GetGlobalTimeNs().count() + ns_into_future);
-
- event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type});
-
- std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
- basic_lock.unlock();
- event.Set();
-}
-
-void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata) {
- basic_lock.lock();
- const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
- return e.type.lock().get() == event_type.get() && e.userdata == userdata;
- });
-
- // Removing random items breaks the invariant so we have to re-establish it.
- if (itr != event_queue.end()) {
- event_queue.erase(itr, event_queue.end());
- std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>());
- }
- basic_lock.unlock();
-}
-
-void CoreTiming::AddTicks(std::size_t core_index, u64 ticks) {
- ticks_count[core_index] += ticks;
-}
-
-void CoreTiming::ResetTicks(std::size_t core_index) {
- ticks_count[core_index] = 0;
-}
-
-u64 CoreTiming::GetCPUTicks() const {
- return clock->GetCPUCycles();
-}
-
-u64 CoreTiming::GetClockTicks() const {
- return clock->GetClockCycles();
-}
-
-void CoreTiming::ClearPendingEvents() {
- event_queue.clear();
-}
-
-void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) {
- basic_lock.lock();
-
- const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
- return e.type.lock().get() == event_type.get();
- });
-
- // Removing random items breaks the invariant so we have to re-establish it.
- if (itr != event_queue.end()) {
- event_queue.erase(itr, event_queue.end());
- std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>());
- }
- basic_lock.unlock();
-}
-
-std::optional<u64> CoreTiming::Advance() {
- advance_lock.lock();
- basic_lock.lock();
- global_timer = GetGlobalTimeNs().count();
-
- while (!event_queue.empty() && event_queue.front().time <= global_timer) {
- Event evt = std::move(event_queue.front());
- std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>());
- event_queue.pop_back();
- basic_lock.unlock();
-
- if (auto event_type{evt.type.lock()}) {
- event_type->callback(evt.userdata, global_timer - evt.time);
- }
-
- basic_lock.lock();
- }
-
- if (!event_queue.empty()) {
- const u64 next_time = event_queue.front().time - global_timer;
- basic_lock.unlock();
- advance_lock.unlock();
- return next_time;
- } else {
- basic_lock.unlock();
- advance_lock.unlock();
- return std::nullopt;
- }
-}
-
-void CoreTiming::ThreadLoop() {
- has_started = true;
- while (!shutting_down) {
- while (!paused) {
- paused_set = false;
- const auto next_time = Advance();
- if (next_time) {
- std::chrono::nanoseconds next_time_ns = std::chrono::nanoseconds(*next_time);
- event.WaitFor(next_time_ns);
- } else {
- wait_set = true;
- event.Wait();
- }
- wait_set = false;
- }
- paused_set = true;
- }
-}
-
-std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const {
- return clock->GetTimeNS();
-}
-
-std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
- return clock->GetTimeUS();
-}
-
-} // namespace Core::HostTiming
diff --git a/src/core/host_timing.h b/src/core/host_timing.h
deleted file mode 100644
index be6b68d7c..000000000
--- a/src/core/host_timing.h
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <atomic>
-#include <chrono>
-#include <functional>
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include "common/common_types.h"
-#include "common/spin_lock.h"
-#include "common/thread.h"
-#include "common/threadsafe_queue.h"
-#include "common/wall_clock.h"
-#include "core/hardware_properties.h"
-
-namespace Core::HostTiming {
-
-/// A callback that may be scheduled for a particular core timing event.
-using TimedCallback = std::function<void(u64 userdata, s64 cycles_late)>;
-
-/// Contains the characteristics of a particular event.
-struct EventType {
- EventType(TimedCallback&& callback, std::string&& name)
- : callback{std::move(callback)}, name{std::move(name)} {}
-
- /// The event's callback function.
- TimedCallback callback;
- /// A pointer to the name of the event.
- const std::string name;
-};
-
-/**
- * This is a system to schedule events into the emulated machine's future. Time is measured
- * in main CPU clock cycles.
- *
- * To schedule an event, you first have to register its type. This is where you pass in the
- * callback. You then schedule events using the type id you get back.
- *
- * The int cyclesLate that the callbacks get is how many cycles late it was.
- * So to schedule a new event on a regular basis:
- * inside callback:
- * ScheduleEvent(periodInCycles - cyclesLate, callback, "whatever")
- */
-class CoreTiming {
-public:
- CoreTiming();
- ~CoreTiming();
-
- CoreTiming(const CoreTiming&) = delete;
- CoreTiming(CoreTiming&&) = delete;
-
- CoreTiming& operator=(const CoreTiming&) = delete;
- CoreTiming& operator=(CoreTiming&&) = delete;
-
- /// CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is
- /// required to end slice - 1 and start slice 0 before the first cycle of code is executed.
- void Initialize();
-
- /// Tears down all timing related functionality.
- void Shutdown();
-
- /// Pauses/Unpauses the execution of the timer thread.
- void Pause(bool is_paused);
-
- /// Pauses/Unpauses the execution of the timer thread and waits until paused.
- void SyncPause(bool is_paused);
-
- /// Checks if core timing is running.
- bool IsRunning() const;
-
- /// Checks if the timer thread has started.
- bool HasStarted() const {
- return has_started;
- }
-
- /// Checks if there are any pending time events.
- bool HasPendingEvents() const;
-
- /// Schedules an event in core timing
- void ScheduleEvent(s64 ns_into_future, const std::shared_ptr<EventType>& event_type,
- u64 userdata = 0);
-
- void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata);
-
- /// We only permit one event of each type in the queue at a time.
- void RemoveEvent(const std::shared_ptr<EventType>& event_type);
-
- void AddTicks(std::size_t core_index, u64 ticks);
-
- void ResetTicks(std::size_t core_index);
-
- /// Returns current time in emulated CPU cycles
- u64 GetCPUTicks() const;
-
- /// Returns current time in emulated in Clock cycles
- u64 GetClockTicks() const;
-
- /// Returns current time in microseconds.
- std::chrono::microseconds GetGlobalTimeUs() const;
-
- /// Returns current time in nanoseconds.
- std::chrono::nanoseconds GetGlobalTimeNs() const;
-
- /// Checks for events manually and returns time in nanoseconds for next event, threadsafe.
- std::optional<u64> Advance();
-
-private:
- struct Event;
-
- /// Clear all pending events. This should ONLY be done on exit.
- void ClearPendingEvents();
-
- static void ThreadEntry(CoreTiming& instance);
- void ThreadLoop();
-
- std::unique_ptr<Common::WallClock> clock;
-
- u64 global_timer = 0;
-
- std::chrono::nanoseconds start_point;
-
- // The queue is a min-heap using std::make_heap/push_heap/pop_heap.
- // We don't use std::priority_queue because we need to be able to serialize, unserialize and
- // erase arbitrary events (RemoveEvent()) regardless of the queue order. These aren't
- // accomodated by the standard adaptor class.
- std::vector<Event> event_queue;
- u64 event_fifo_id = 0;
-
- std::shared_ptr<EventType> ev_lost;
- Common::Event event{};
- Common::SpinLock basic_lock{};
- Common::SpinLock advance_lock{};
- std::unique_ptr<std::thread> timer_thread;
- std::atomic<bool> paused{};
- std::atomic<bool> paused_set{};
- std::atomic<bool> wait_set{};
- std::atomic<bool> shutting_down{};
- std::atomic<bool> has_started{};
-
- std::array<std::atomic<u64>, Core::Hardware::NUM_CPU_CORES> ticks_count{};
-};
-
-/// Creates a core timing event with the given name and callback.
-///
-/// @param name The name of the core timing event to create.
-/// @param callback The callback to execute for the event.
-///
-/// @returns An EventType instance representing the created event.
-///
-std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback);
-
-} // namespace Core::HostTiming
diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp
index 795f3da09..21a5840fb 100644
--- a/src/tests/core/core_timing.cpp
+++ b/src/tests/core/core_timing.cpp
@@ -39,6 +39,7 @@ u64 callbacks_done = 0;
struct ScopeInit final {
ScopeInit() {
+ core_timing.SetMulticore(true);
core_timing.Initialize([]() {});
}
~ScopeInit() {
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index d2dbb259c..0226ae2e2 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -340,7 +340,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
if (thread.GetStatus() == Kernel::ThreadStatus::WaitSynch) {
list.push_back(std::make_unique<WaitTreeObjectList>(thread.GetSynchronizationObjects(),
- thread.IsSleepingOnWait()));
+ thread.IsWaitingSync()));
}
list.push_back(std::make_unique<WaitTreeCallstack>(thread));