diff options
Diffstat (limited to 'src')
42 files changed, 434 insertions, 227 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index d342cafe0..26612e692 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -181,14 +181,16 @@ add_library(core STATIC | |||
| 181 | hle/kernel/svc.cpp | 181 | hle/kernel/svc.cpp |
| 182 | hle/kernel/svc.h | 182 | hle/kernel/svc.h |
| 183 | hle/kernel/svc_wrap.h | 183 | hle/kernel/svc_wrap.h |
| 184 | hle/kernel/synchronization_object.cpp | ||
| 185 | hle/kernel/synchronization_object.h | ||
| 186 | hle/kernel/synchronization.cpp | ||
| 187 | hle/kernel/synchronization.h | ||
| 184 | hle/kernel/thread.cpp | 188 | hle/kernel/thread.cpp |
| 185 | hle/kernel/thread.h | 189 | hle/kernel/thread.h |
| 186 | hle/kernel/transfer_memory.cpp | 190 | hle/kernel/transfer_memory.cpp |
| 187 | hle/kernel/transfer_memory.h | 191 | hle/kernel/transfer_memory.h |
| 188 | hle/kernel/vm_manager.cpp | 192 | hle/kernel/vm_manager.cpp |
| 189 | hle/kernel/vm_manager.h | 193 | hle/kernel/vm_manager.h |
| 190 | hle/kernel/wait_object.cpp | ||
| 191 | hle/kernel/wait_object.h | ||
| 192 | hle/kernel/writable_event.cpp | 194 | hle/kernel/writable_event.cpp |
| 193 | hle/kernel/writable_event.h | 195 | hle/kernel/writable_event.h |
| 194 | hle/lock.cpp | 196 | hle/lock.cpp |
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 791640a3a..29eaf74e5 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "core/core_timing.h" | 14 | #include "core/core_timing.h" |
| 15 | #include "core/core_timing_util.h" | 15 | #include "core/core_timing_util.h" |
| 16 | #include "core/gdbstub/gdbstub.h" | 16 | #include "core/gdbstub/gdbstub.h" |
| 17 | #include "core/hardware_properties.h" | ||
| 17 | #include "core/hle/kernel/process.h" | 18 | #include "core/hle/kernel/process.h" |
| 18 | #include "core/hle/kernel/scheduler.h" | 19 | #include "core/hle/kernel/scheduler.h" |
| 19 | #include "core/hle/kernel/svc.h" | 20 | #include "core/hle/kernel/svc.h" |
| @@ -153,7 +154,7 @@ std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& pag | |||
| 153 | config.tpidr_el0 = &cb->tpidr_el0; | 154 | config.tpidr_el0 = &cb->tpidr_el0; |
| 154 | config.dczid_el0 = 4; | 155 | config.dczid_el0 = 4; |
| 155 | config.ctr_el0 = 0x8444c004; | 156 | config.ctr_el0 = 0x8444c004; |
| 156 | config.cntfrq_el0 = Timing::CNTFREQ; | 157 | config.cntfrq_el0 = Hardware::CNTFREQ; |
| 157 | 158 | ||
| 158 | // Unpredictable instructions | 159 | // Unpredictable instructions |
| 159 | config.define_unpredictable_behaviour = true; | 160 | config.define_unpredictable_behaviour = true; |
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index aa09fa453..46d4178c4 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 13 | #include "common/thread.h" | 13 | #include "common/thread.h" |
| 14 | #include "core/core_timing_util.h" | 14 | #include "core/core_timing_util.h" |
| 15 | #include "core/hardware_properties.h" | ||
| 15 | 16 | ||
| 16 | namespace Core::Timing { | 17 | namespace Core::Timing { |
| 17 | 18 | ||
| @@ -215,7 +216,7 @@ void CoreTiming::Idle() { | |||
| 215 | } | 216 | } |
| 216 | 217 | ||
| 217 | std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const { | 218 | std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const { |
| 218 | return std::chrono::microseconds{GetTicks() * 1000000 / BASE_CLOCK_RATE}; | 219 | return std::chrono::microseconds{GetTicks() * 1000000 / Hardware::BASE_CLOCK_RATE}; |
| 219 | } | 220 | } |
| 220 | 221 | ||
| 221 | s64 CoreTiming::GetDowncount() const { | 222 | s64 CoreTiming::GetDowncount() const { |
diff --git a/src/core/core_timing_util.cpp b/src/core/core_timing_util.cpp index a10472a95..de50d3b14 100644 --- a/src/core/core_timing_util.cpp +++ b/src/core/core_timing_util.cpp | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | namespace Core::Timing { | 12 | namespace Core::Timing { |
| 13 | 13 | ||
| 14 | constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / BASE_CLOCK_RATE; | 14 | constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / Hardware::BASE_CLOCK_RATE; |
| 15 | 15 | ||
| 16 | s64 msToCycles(std::chrono::milliseconds ms) { | 16 | s64 msToCycles(std::chrono::milliseconds ms) { |
| 17 | if (static_cast<u64>(ms.count() / 1000) > MAX_VALUE_TO_MULTIPLY) { | 17 | if (static_cast<u64>(ms.count() / 1000) > MAX_VALUE_TO_MULTIPLY) { |
| @@ -20,9 +20,9 @@ s64 msToCycles(std::chrono::milliseconds ms) { | |||
| 20 | } | 20 | } |
| 21 | if (static_cast<u64>(ms.count()) > MAX_VALUE_TO_MULTIPLY) { | 21 | if (static_cast<u64>(ms.count()) > MAX_VALUE_TO_MULTIPLY) { |
| 22 | LOG_DEBUG(Core_Timing, "Time very big, do rounding"); | 22 | LOG_DEBUG(Core_Timing, "Time very big, do rounding"); |
| 23 | return BASE_CLOCK_RATE * (ms.count() / 1000); | 23 | return Hardware::BASE_CLOCK_RATE * (ms.count() / 1000); |
| 24 | } | 24 | } |
| 25 | return (BASE_CLOCK_RATE * ms.count()) / 1000; | 25 | return (Hardware::BASE_CLOCK_RATE * ms.count()) / 1000; |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | s64 usToCycles(std::chrono::microseconds us) { | 28 | s64 usToCycles(std::chrono::microseconds us) { |
| @@ -32,9 +32,9 @@ s64 usToCycles(std::chrono::microseconds us) { | |||
| 32 | } | 32 | } |
| 33 | if (static_cast<u64>(us.count()) > MAX_VALUE_TO_MULTIPLY) { | 33 | if (static_cast<u64>(us.count()) > MAX_VALUE_TO_MULTIPLY) { |
| 34 | LOG_DEBUG(Core_Timing, "Time very big, do rounding"); | 34 | LOG_DEBUG(Core_Timing, "Time very big, do rounding"); |
| 35 | return BASE_CLOCK_RATE * (us.count() / 1000000); | 35 | return Hardware::BASE_CLOCK_RATE * (us.count() / 1000000); |
| 36 | } | 36 | } |
| 37 | return (BASE_CLOCK_RATE * us.count()) / 1000000; | 37 | return (Hardware::BASE_CLOCK_RATE * us.count()) / 1000000; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | s64 nsToCycles(std::chrono::nanoseconds ns) { | 40 | s64 nsToCycles(std::chrono::nanoseconds ns) { |
| @@ -44,14 +44,14 @@ s64 nsToCycles(std::chrono::nanoseconds ns) { | |||
| 44 | } | 44 | } |
| 45 | if (static_cast<u64>(ns.count()) > MAX_VALUE_TO_MULTIPLY) { | 45 | if (static_cast<u64>(ns.count()) > MAX_VALUE_TO_MULTIPLY) { |
| 46 | LOG_DEBUG(Core_Timing, "Time very big, do rounding"); | 46 | LOG_DEBUG(Core_Timing, "Time very big, do rounding"); |
| 47 | return BASE_CLOCK_RATE * (ns.count() / 1000000000); | 47 | return Hardware::BASE_CLOCK_RATE * (ns.count() / 1000000000); |
| 48 | } | 48 | } |
| 49 | return (BASE_CLOCK_RATE * ns.count()) / 1000000000; | 49 | return (Hardware::BASE_CLOCK_RATE * ns.count()) / 1000000000; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | u64 CpuCyclesToClockCycles(u64 ticks) { | 52 | u64 CpuCyclesToClockCycles(u64 ticks) { |
| 53 | const u128 temporal = Common::Multiply64Into128(ticks, CNTFREQ); | 53 | const u128 temporal = Common::Multiply64Into128(ticks, Hardware::CNTFREQ); |
| 54 | return Common::Divide128On32(temporal, static_cast<u32>(BASE_CLOCK_RATE)).first; | 54 | return Common::Divide128On32(temporal, static_cast<u32>(Hardware::BASE_CLOCK_RATE)).first; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | } // namespace Core::Timing | 57 | } // namespace Core::Timing |
diff --git a/src/core/core_timing_util.h b/src/core/core_timing_util.h index cdd84d70f..addc72b19 100644 --- a/src/core/core_timing_util.h +++ b/src/core/core_timing_util.h | |||
| @@ -6,28 +6,24 @@ | |||
| 6 | 6 | ||
| 7 | #include <chrono> | 7 | #include <chrono> |
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "core/hardware_properties.h" | ||
| 9 | 10 | ||
| 10 | namespace Core::Timing { | 11 | namespace Core::Timing { |
| 11 | 12 | ||
| 12 | // The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz | ||
| 13 | // The exact value used is of course unverified. | ||
| 14 | constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch clock speed is 1020MHz un/docked | ||
| 15 | constexpr u64 CNTFREQ = 19200000; // Value from fusee. | ||
| 16 | |||
| 17 | s64 msToCycles(std::chrono::milliseconds ms); | 13 | s64 msToCycles(std::chrono::milliseconds ms); |
| 18 | s64 usToCycles(std::chrono::microseconds us); | 14 | s64 usToCycles(std::chrono::microseconds us); |
| 19 | s64 nsToCycles(std::chrono::nanoseconds ns); | 15 | s64 nsToCycles(std::chrono::nanoseconds ns); |
| 20 | 16 | ||
| 21 | inline std::chrono::milliseconds CyclesToMs(s64 cycles) { | 17 | inline std::chrono::milliseconds CyclesToMs(s64 cycles) { |
| 22 | return std::chrono::milliseconds(cycles * 1000 / BASE_CLOCK_RATE); | 18 | return std::chrono::milliseconds(cycles * 1000 / Hardware::BASE_CLOCK_RATE); |
| 23 | } | 19 | } |
| 24 | 20 | ||
| 25 | inline std::chrono::nanoseconds CyclesToNs(s64 cycles) { | 21 | inline std::chrono::nanoseconds CyclesToNs(s64 cycles) { |
| 26 | return std::chrono::nanoseconds(cycles * 1000000000 / BASE_CLOCK_RATE); | 22 | return std::chrono::nanoseconds(cycles * 1000000000 / Hardware::BASE_CLOCK_RATE); |
| 27 | } | 23 | } |
| 28 | 24 | ||
| 29 | inline std::chrono::microseconds CyclesToUs(s64 cycles) { | 25 | inline std::chrono::microseconds CyclesToUs(s64 cycles) { |
| 30 | return std::chrono::microseconds(cycles * 1000000 / BASE_CLOCK_RATE); | 26 | return std::chrono::microseconds(cycles * 1000000 / Hardware::BASE_CLOCK_RATE); |
| 31 | } | 27 | } |
| 32 | 28 | ||
| 33 | u64 CpuCyclesToClockCycles(u64 ticks); | 29 | u64 CpuCyclesToClockCycles(u64 ticks); |
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index feb619e1b..97554d1bb 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | #include "core/hardware_properties.h" | ||
| 9 | 10 | ||
| 10 | namespace Core { | 11 | namespace Core { |
| 11 | 12 | ||
| @@ -39,9 +40,7 @@ public: | |||
| 39 | void RunLoop(bool tight_loop); | 40 | void RunLoop(bool tight_loop); |
| 40 | 41 | ||
| 41 | private: | 42 | private: |
| 42 | static constexpr std::size_t NUM_CPU_CORES = 4; | 43 | std::array<std::unique_ptr<CoreManager>, Hardware::NUM_CPU_CORES> core_managers; |
| 43 | |||
| 44 | std::array<std::unique_ptr<CoreManager>, NUM_CPU_CORES> core_managers; | ||
| 45 | std::size_t active_core{}; ///< Active core, only used in single thread mode | 44 | std::size_t active_core{}; ///< Active core, only used in single thread mode |
| 46 | 45 | ||
| 47 | System& system; | 46 | System& system; |
diff --git a/src/core/hardware_properties.h b/src/core/hardware_properties.h new file mode 100644 index 000000000..213461b6a --- /dev/null +++ b/src/core/hardware_properties.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <tuple> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | namespace Core { | ||
| 12 | |||
| 13 | namespace Hardware { | ||
| 14 | |||
| 15 | // The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz | ||
| 16 | // The exact value used is of course unverified. | ||
| 17 | constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch cpu frequency is 1020MHz un/docked | ||
| 18 | constexpr u64 CNTFREQ = 19200000; // Switch's hardware clock speed | ||
| 19 | constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores | ||
| 20 | |||
| 21 | } // namespace Hardware | ||
| 22 | |||
| 23 | struct EmuThreadHandle { | ||
| 24 | u32 host_handle; | ||
| 25 | u32 guest_handle; | ||
| 26 | |||
| 27 | u64 GetRaw() const { | ||
| 28 | return (static_cast<u64>(host_handle) << 32) | guest_handle; | ||
| 29 | } | ||
| 30 | |||
| 31 | bool operator==(const EmuThreadHandle& rhs) const { | ||
| 32 | return std::tie(host_handle, guest_handle) == std::tie(rhs.host_handle, rhs.guest_handle); | ||
| 33 | } | ||
| 34 | |||
| 35 | bool operator!=(const EmuThreadHandle& rhs) const { | ||
| 36 | return !operator==(rhs); | ||
| 37 | } | ||
| 38 | |||
| 39 | static constexpr EmuThreadHandle InvalidHandle() { | ||
| 40 | constexpr u32 invalid_handle = 0xFFFFFFFF; | ||
| 41 | return {invalid_handle, invalid_handle}; | ||
| 42 | } | ||
| 43 | }; | ||
| 44 | |||
| 45 | } // namespace Core | ||
diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp index 4669a14ad..6d66276bc 100644 --- a/src/core/hle/kernel/client_session.cpp +++ b/src/core/hle/kernel/client_session.cpp | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | namespace Kernel { | 13 | namespace Kernel { |
| 14 | 14 | ||
| 15 | ClientSession::ClientSession(KernelCore& kernel) : WaitObject{kernel} {} | 15 | ClientSession::ClientSession(KernelCore& kernel) : SynchronizationObject{kernel} {} |
| 16 | 16 | ||
| 17 | ClientSession::~ClientSession() { | 17 | ClientSession::~ClientSession() { |
| 18 | // This destructor will be called automatically when the last ClientSession handle is closed by | 18 | // This destructor will be called automatically when the last ClientSession handle is closed by |
| @@ -31,6 +31,11 @@ void ClientSession::Acquire(Thread* thread) { | |||
| 31 | UNIMPLEMENTED(); | 31 | UNIMPLEMENTED(); |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | bool ClientSession::IsSignaled() const { | ||
| 35 | UNIMPLEMENTED(); | ||
| 36 | return true; | ||
| 37 | } | ||
| 38 | |||
| 34 | ResultVal<std::shared_ptr<ClientSession>> ClientSession::Create(KernelCore& kernel, | 39 | ResultVal<std::shared_ptr<ClientSession>> ClientSession::Create(KernelCore& kernel, |
| 35 | std::shared_ptr<Session> parent, | 40 | std::shared_ptr<Session> parent, |
| 36 | std::string name) { | 41 | std::string name) { |
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h index b4289a9a8..d15b09554 100644 --- a/src/core/hle/kernel/client_session.h +++ b/src/core/hle/kernel/client_session.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | 9 | ||
| 10 | #include "core/hle/kernel/wait_object.h" | 10 | #include "core/hle/kernel/synchronization_object.h" |
| 11 | #include "core/hle/result.h" | 11 | #include "core/hle/result.h" |
| 12 | 12 | ||
| 13 | union ResultCode; | 13 | union ResultCode; |
| @@ -22,7 +22,7 @@ class KernelCore; | |||
| 22 | class Session; | 22 | class Session; |
| 23 | class Thread; | 23 | class Thread; |
| 24 | 24 | ||
| 25 | class ClientSession final : public WaitObject { | 25 | class ClientSession final : public SynchronizationObject { |
| 26 | public: | 26 | public: |
| 27 | explicit ClientSession(KernelCore& kernel); | 27 | explicit ClientSession(KernelCore& kernel); |
| 28 | ~ClientSession() override; | 28 | ~ClientSession() override; |
| @@ -48,6 +48,8 @@ public: | |||
| 48 | 48 | ||
| 49 | void Acquire(Thread* thread) override; | 49 | void Acquire(Thread* thread) override; |
| 50 | 50 | ||
| 51 | bool IsSignaled() const override; | ||
| 52 | |||
| 51 | private: | 53 | private: |
| 52 | static ResultVal<std::shared_ptr<ClientSession>> Create(KernelCore& kernel, | 54 | static ResultVal<std::shared_ptr<ClientSession>> Create(KernelCore& kernel, |
| 53 | std::shared_ptr<Session> parent, | 55 | std::shared_ptr<Session> parent, |
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index ab05788d7..c558a2f33 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -47,15 +47,15 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread( | |||
| 47 | const std::string& reason, u64 timeout, WakeupCallback&& callback, | 47 | const std::string& reason, u64 timeout, WakeupCallback&& callback, |
| 48 | std::shared_ptr<WritableEvent> writable_event) { | 48 | std::shared_ptr<WritableEvent> writable_event) { |
| 49 | // Put the client thread to sleep until the wait event is signaled or the timeout expires. | 49 | // Put the client thread to sleep until the wait event is signaled or the timeout expires. |
| 50 | thread->SetWakeupCallback([context = *this, callback](ThreadWakeupReason reason, | 50 | thread->SetWakeupCallback( |
| 51 | std::shared_ptr<Thread> thread, | 51 | [context = *this, callback](ThreadWakeupReason reason, std::shared_ptr<Thread> thread, |
| 52 | std::shared_ptr<WaitObject> object, | 52 | std::shared_ptr<SynchronizationObject> object, |
| 53 | std::size_t index) mutable -> bool { | 53 | std::size_t index) mutable -> bool { |
| 54 | ASSERT(thread->GetStatus() == ThreadStatus::WaitHLEEvent); | 54 | ASSERT(thread->GetStatus() == ThreadStatus::WaitHLEEvent); |
| 55 | callback(thread, context, reason); | 55 | callback(thread, context, reason); |
| 56 | context.WriteToOutgoingCommandBuffer(*thread); | 56 | context.WriteToOutgoingCommandBuffer(*thread); |
| 57 | return true; | 57 | return true; |
| 58 | }); | 58 | }); |
| 59 | 59 | ||
| 60 | auto& kernel = Core::System::GetInstance().Kernel(); | 60 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 61 | if (!writable_event) { | 61 | if (!writable_event) { |
| @@ -67,7 +67,7 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread( | |||
| 67 | const auto readable_event{writable_event->GetReadableEvent()}; | 67 | const auto readable_event{writable_event->GetReadableEvent()}; |
| 68 | writable_event->Clear(); | 68 | writable_event->Clear(); |
| 69 | thread->SetStatus(ThreadStatus::WaitHLEEvent); | 69 | thread->SetStatus(ThreadStatus::WaitHLEEvent); |
| 70 | thread->SetWaitObjects({readable_event}); | 70 | thread->SetSynchronizationObjects({readable_event}); |
| 71 | readable_event->AddWaitingThread(thread); | 71 | readable_event->AddWaitingThread(thread); |
| 72 | 72 | ||
| 73 | if (timeout > 0) { | 73 | if (timeout > 0) { |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index edd4c4259..4eb1d8703 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include "core/hle/kernel/process.h" | 23 | #include "core/hle/kernel/process.h" |
| 24 | #include "core/hle/kernel/resource_limit.h" | 24 | #include "core/hle/kernel/resource_limit.h" |
| 25 | #include "core/hle/kernel/scheduler.h" | 25 | #include "core/hle/kernel/scheduler.h" |
| 26 | #include "core/hle/kernel/synchronization.h" | ||
| 26 | #include "core/hle/kernel/thread.h" | 27 | #include "core/hle/kernel/thread.h" |
| 27 | #include "core/hle/lock.h" | 28 | #include "core/hle/lock.h" |
| 28 | #include "core/hle/result.h" | 29 | #include "core/hle/result.h" |
| @@ -54,10 +55,10 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ | |||
| 54 | if (thread->GetStatus() == ThreadStatus::WaitSynch || | 55 | if (thread->GetStatus() == ThreadStatus::WaitSynch || |
| 55 | thread->GetStatus() == ThreadStatus::WaitHLEEvent) { | 56 | thread->GetStatus() == ThreadStatus::WaitHLEEvent) { |
| 56 | // Remove the thread from each of its waiting objects' waitlists | 57 | // Remove the thread from each of its waiting objects' waitlists |
| 57 | for (const auto& object : thread->GetWaitObjects()) { | 58 | for (const auto& object : thread->GetSynchronizationObjects()) { |
| 58 | object->RemoveWaitingThread(thread); | 59 | object->RemoveWaitingThread(thread); |
| 59 | } | 60 | } |
| 60 | thread->ClearWaitObjects(); | 61 | thread->ClearSynchronizationObjects(); |
| 61 | 62 | ||
| 62 | // Invoke the wakeup callback before clearing the wait objects | 63 | // Invoke the wakeup callback before clearing the wait objects |
| 63 | if (thread->HasWakeupCallback()) { | 64 | if (thread->HasWakeupCallback()) { |
| @@ -96,7 +97,8 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ | |||
| 96 | } | 97 | } |
| 97 | 98 | ||
| 98 | struct KernelCore::Impl { | 99 | struct KernelCore::Impl { |
| 99 | explicit Impl(Core::System& system) : system{system}, global_scheduler{system} {} | 100 | explicit Impl(Core::System& system) |
| 101 | : system{system}, global_scheduler{system}, synchronization{system} {} | ||
| 100 | 102 | ||
| 101 | void Initialize(KernelCore& kernel) { | 103 | void Initialize(KernelCore& kernel) { |
| 102 | Shutdown(); | 104 | Shutdown(); |
| @@ -191,6 +193,7 @@ struct KernelCore::Impl { | |||
| 191 | std::vector<std::shared_ptr<Process>> process_list; | 193 | std::vector<std::shared_ptr<Process>> process_list; |
| 192 | Process* current_process = nullptr; | 194 | Process* current_process = nullptr; |
| 193 | Kernel::GlobalScheduler global_scheduler; | 195 | Kernel::GlobalScheduler global_scheduler; |
| 196 | Kernel::Synchronization synchronization; | ||
| 194 | 197 | ||
| 195 | std::shared_ptr<ResourceLimit> system_resource_limit; | 198 | std::shared_ptr<ResourceLimit> system_resource_limit; |
| 196 | 199 | ||
| @@ -270,6 +273,14 @@ const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const { | |||
| 270 | return impl->cores[id]; | 273 | return impl->cores[id]; |
| 271 | } | 274 | } |
| 272 | 275 | ||
| 276 | Kernel::Synchronization& KernelCore::Synchronization() { | ||
| 277 | return impl->synchronization; | ||
| 278 | } | ||
| 279 | |||
| 280 | const Kernel::Synchronization& KernelCore::Synchronization() const { | ||
| 281 | return impl->synchronization; | ||
| 282 | } | ||
| 283 | |||
| 273 | Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { | 284 | Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { |
| 274 | return *impl->exclusive_monitor; | 285 | return *impl->exclusive_monitor; |
| 275 | } | 286 | } |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index fccffaf3a..1eede3063 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -29,6 +29,7 @@ class HandleTable; | |||
| 29 | class PhysicalCore; | 29 | class PhysicalCore; |
| 30 | class Process; | 30 | class Process; |
| 31 | class ResourceLimit; | 31 | class ResourceLimit; |
| 32 | class Synchronization; | ||
| 32 | class Thread; | 33 | class Thread; |
| 33 | 34 | ||
| 34 | /// Represents a single instance of the kernel. | 35 | /// Represents a single instance of the kernel. |
| @@ -92,6 +93,12 @@ public: | |||
| 92 | /// Gets the an instance of the respective physical CPU core. | 93 | /// Gets the an instance of the respective physical CPU core. |
| 93 | const Kernel::PhysicalCore& PhysicalCore(std::size_t id) const; | 94 | const Kernel::PhysicalCore& PhysicalCore(std::size_t id) const; |
| 94 | 95 | ||
| 96 | /// Gets the an instance of the Synchronization Interface. | ||
| 97 | Kernel::Synchronization& Synchronization(); | ||
| 98 | |||
| 99 | /// Gets the an instance of the Synchronization Interface. | ||
| 100 | const Kernel::Synchronization& Synchronization() const; | ||
| 101 | |||
| 95 | /// Stops execution of 'id' core, in order to reschedule a new thread. | 102 | /// Stops execution of 'id' core, in order to reschedule a new thread. |
| 96 | void PrepareReschedule(std::size_t id); | 103 | void PrepareReschedule(std::size_t id); |
| 97 | 104 | ||
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index b9035a0be..2fcb7326c 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -337,7 +337,7 @@ void Process::LoadModule(CodeSet module_, VAddr base_addr) { | |||
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | Process::Process(Core::System& system) | 339 | Process::Process(Core::System& system) |
| 340 | : WaitObject{system.Kernel()}, vm_manager{system}, | 340 | : SynchronizationObject{system.Kernel()}, vm_manager{system}, |
| 341 | address_arbiter{system}, mutex{system}, system{system} {} | 341 | address_arbiter{system}, mutex{system}, system{system} {} |
| 342 | 342 | ||
| 343 | Process::~Process() = default; | 343 | Process::~Process() = default; |
| @@ -357,7 +357,7 @@ void Process::ChangeStatus(ProcessStatus new_status) { | |||
| 357 | 357 | ||
| 358 | status = new_status; | 358 | status = new_status; |
| 359 | is_signaled = true; | 359 | is_signaled = true; |
| 360 | WakeupAllWaitingThreads(); | 360 | Signal(); |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | void Process::AllocateMainThreadStack(u64 stack_size) { | 363 | void Process::AllocateMainThreadStack(u64 stack_size) { |
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 3483fa19d..4887132a7 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -15,8 +15,8 @@ | |||
| 15 | #include "core/hle/kernel/handle_table.h" | 15 | #include "core/hle/kernel/handle_table.h" |
| 16 | #include "core/hle/kernel/mutex.h" | 16 | #include "core/hle/kernel/mutex.h" |
| 17 | #include "core/hle/kernel/process_capability.h" | 17 | #include "core/hle/kernel/process_capability.h" |
| 18 | #include "core/hle/kernel/synchronization_object.h" | ||
| 18 | #include "core/hle/kernel/vm_manager.h" | 19 | #include "core/hle/kernel/vm_manager.h" |
| 19 | #include "core/hle/kernel/wait_object.h" | ||
| 20 | #include "core/hle/result.h" | 20 | #include "core/hle/result.h" |
| 21 | 21 | ||
| 22 | namespace Core { | 22 | namespace Core { |
| @@ -60,7 +60,7 @@ enum class ProcessStatus { | |||
| 60 | DebugBreak, | 60 | DebugBreak, |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | class Process final : public WaitObject { | 63 | class Process final : public SynchronizationObject { |
| 64 | public: | 64 | public: |
| 65 | explicit Process(Core::System& system); | 65 | explicit Process(Core::System& system); |
| 66 | ~Process() override; | 66 | ~Process() override; |
| @@ -359,10 +359,6 @@ private: | |||
| 359 | /// specified by metadata provided to the process during loading. | 359 | /// specified by metadata provided to the process during loading. |
| 360 | bool is_64bit_process = true; | 360 | bool is_64bit_process = true; |
| 361 | 361 | ||
| 362 | /// Whether or not this process is signaled. This occurs | ||
| 363 | /// upon the process changing to a different state. | ||
| 364 | bool is_signaled = false; | ||
| 365 | |||
| 366 | /// Total running time for the process in ticks. | 362 | /// Total running time for the process in ticks. |
| 367 | u64 total_process_running_time_ticks = 0; | 363 | u64 total_process_running_time_ticks = 0; |
| 368 | 364 | ||
diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp index d8ac97aa1..9d3d3a81b 100644 --- a/src/core/hle/kernel/readable_event.cpp +++ b/src/core/hle/kernel/readable_event.cpp | |||
| @@ -11,30 +11,30 @@ | |||
| 11 | 11 | ||
| 12 | namespace Kernel { | 12 | namespace Kernel { |
| 13 | 13 | ||
| 14 | ReadableEvent::ReadableEvent(KernelCore& kernel) : WaitObject{kernel} {} | 14 | ReadableEvent::ReadableEvent(KernelCore& kernel) : SynchronizationObject{kernel} {} |
| 15 | ReadableEvent::~ReadableEvent() = default; | 15 | ReadableEvent::~ReadableEvent() = default; |
| 16 | 16 | ||
| 17 | bool ReadableEvent::ShouldWait(const Thread* thread) const { | 17 | bool ReadableEvent::ShouldWait(const Thread* thread) const { |
| 18 | return !signaled; | 18 | return !is_signaled; |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | void ReadableEvent::Acquire(Thread* thread) { | 21 | void ReadableEvent::Acquire(Thread* thread) { |
| 22 | ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); | 22 | ASSERT_MSG(IsSignaled(), "object unavailable!"); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | void ReadableEvent::Signal() { | 25 | void ReadableEvent::Signal() { |
| 26 | if (!signaled) { | 26 | if (!is_signaled) { |
| 27 | signaled = true; | 27 | is_signaled = true; |
| 28 | WakeupAllWaitingThreads(); | 28 | SynchronizationObject::Signal(); |
| 29 | }; | 29 | }; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | void ReadableEvent::Clear() { | 32 | void ReadableEvent::Clear() { |
| 33 | signaled = false; | 33 | is_signaled = false; |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | ResultCode ReadableEvent::Reset() { | 36 | ResultCode ReadableEvent::Reset() { |
| 37 | if (!signaled) { | 37 | if (!is_signaled) { |
| 38 | return ERR_INVALID_STATE; | 38 | return ERR_INVALID_STATE; |
| 39 | } | 39 | } |
| 40 | 40 | ||
diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h index 11ff71c3a..3264dd066 100644 --- a/src/core/hle/kernel/readable_event.h +++ b/src/core/hle/kernel/readable_event.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/object.h" | 7 | #include "core/hle/kernel/object.h" |
| 8 | #include "core/hle/kernel/wait_object.h" | 8 | #include "core/hle/kernel/synchronization_object.h" |
| 9 | 9 | ||
| 10 | union ResultCode; | 10 | union ResultCode; |
| 11 | 11 | ||
| @@ -14,7 +14,7 @@ namespace Kernel { | |||
| 14 | class KernelCore; | 14 | class KernelCore; |
| 15 | class WritableEvent; | 15 | class WritableEvent; |
| 16 | 16 | ||
| 17 | class ReadableEvent final : public WaitObject { | 17 | class ReadableEvent final : public SynchronizationObject { |
| 18 | friend class WritableEvent; | 18 | friend class WritableEvent; |
| 19 | 19 | ||
| 20 | public: | 20 | public: |
| @@ -46,13 +46,11 @@ public: | |||
| 46 | /// then ERR_INVALID_STATE will be returned. | 46 | /// then ERR_INVALID_STATE will be returned. |
| 47 | ResultCode Reset(); | 47 | ResultCode Reset(); |
| 48 | 48 | ||
| 49 | void Signal() override; | ||
| 50 | |||
| 49 | private: | 51 | private: |
| 50 | explicit ReadableEvent(KernelCore& kernel); | 52 | explicit ReadableEvent(KernelCore& kernel); |
| 51 | 53 | ||
| 52 | void Signal(); | ||
| 53 | |||
| 54 | bool signaled{}; | ||
| 55 | |||
| 56 | std::string name; ///< Name of event (optional) | 54 | std::string name; ///< Name of event (optional) |
| 57 | }; | 55 | }; |
| 58 | 56 | ||
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index eb196a690..86f1421bf 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp | |||
| @@ -124,8 +124,8 @@ bool GlobalScheduler::YieldThreadAndBalanceLoad(Thread* yielding_thread) { | |||
| 124 | "Thread yielding without being in front"); | 124 | "Thread yielding without being in front"); |
| 125 | scheduled_queue[core_id].yield(priority); | 125 | scheduled_queue[core_id].yield(priority); |
| 126 | 126 | ||
| 127 | std::array<Thread*, NUM_CPU_CORES> current_threads; | 127 | std::array<Thread*, Core::Hardware::NUM_CPU_CORES> current_threads; |
| 128 | for (u32 i = 0; i < NUM_CPU_CORES; i++) { | 128 | for (std::size_t i = 0; i < current_threads.size(); i++) { |
| 129 | current_threads[i] = scheduled_queue[i].empty() ? nullptr : scheduled_queue[i].front(); | 129 | current_threads[i] = scheduled_queue[i].empty() ? nullptr : scheduled_queue[i].front(); |
| 130 | } | 130 | } |
| 131 | 131 | ||
| @@ -177,8 +177,8 @@ bool GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread | |||
| 177 | // function... | 177 | // function... |
| 178 | if (scheduled_queue[core_id].empty()) { | 178 | if (scheduled_queue[core_id].empty()) { |
| 179 | // Here, "current_threads" is calculated after the ""yield"", unlike yield -1 | 179 | // Here, "current_threads" is calculated after the ""yield"", unlike yield -1 |
| 180 | std::array<Thread*, NUM_CPU_CORES> current_threads; | 180 | std::array<Thread*, Core::Hardware::NUM_CPU_CORES> current_threads; |
| 181 | for (u32 i = 0; i < NUM_CPU_CORES; i++) { | 181 | for (std::size_t i = 0; i < current_threads.size(); i++) { |
| 182 | current_threads[i] = scheduled_queue[i].empty() ? nullptr : scheduled_queue[i].front(); | 182 | current_threads[i] = scheduled_queue[i].empty() ? nullptr : scheduled_queue[i].front(); |
| 183 | } | 183 | } |
| 184 | for (auto& thread : suggested_queue[core_id]) { | 184 | for (auto& thread : suggested_queue[core_id]) { |
| @@ -208,7 +208,7 @@ bool GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread | |||
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | void GlobalScheduler::PreemptThreads() { | 210 | void GlobalScheduler::PreemptThreads() { |
| 211 | for (std::size_t core_id = 0; core_id < NUM_CPU_CORES; core_id++) { | 211 | for (std::size_t core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { |
| 212 | const u32 priority = preemption_priorities[core_id]; | 212 | const u32 priority = preemption_priorities[core_id]; |
| 213 | 213 | ||
| 214 | if (scheduled_queue[core_id].size(priority) > 0) { | 214 | if (scheduled_queue[core_id].size(priority) > 0) { |
| @@ -349,7 +349,7 @@ bool GlobalScheduler::AskForReselectionOrMarkRedundant(Thread* current_thread, | |||
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | void GlobalScheduler::Shutdown() { | 351 | void GlobalScheduler::Shutdown() { |
| 352 | for (std::size_t core = 0; core < NUM_CPU_CORES; core++) { | 352 | for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { |
| 353 | scheduled_queue[core].clear(); | 353 | scheduled_queue[core].clear(); |
| 354 | suggested_queue[core].clear(); | 354 | suggested_queue[core].clear(); |
| 355 | } | 355 | } |
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index 14b77960a..96db049cb 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "common/multi_level_queue.h" | 12 | #include "common/multi_level_queue.h" |
| 13 | #include "core/hardware_properties.h" | ||
| 13 | #include "core/hle/kernel/thread.h" | 14 | #include "core/hle/kernel/thread.h" |
| 14 | 15 | ||
| 15 | namespace Core { | 16 | namespace Core { |
| @@ -23,8 +24,6 @@ class Process; | |||
| 23 | 24 | ||
| 24 | class GlobalScheduler final { | 25 | class GlobalScheduler final { |
| 25 | public: | 26 | public: |
| 26 | static constexpr u32 NUM_CPU_CORES = 4; | ||
| 27 | |||
| 28 | explicit GlobalScheduler(Core::System& system); | 27 | explicit GlobalScheduler(Core::System& system); |
| 29 | ~GlobalScheduler(); | 28 | ~GlobalScheduler(); |
| 30 | 29 | ||
| @@ -125,7 +124,7 @@ public: | |||
| 125 | void PreemptThreads(); | 124 | void PreemptThreads(); |
| 126 | 125 | ||
| 127 | u32 CpuCoresCount() const { | 126 | u32 CpuCoresCount() const { |
| 128 | return NUM_CPU_CORES; | 127 | return Core::Hardware::NUM_CPU_CORES; |
| 129 | } | 128 | } |
| 130 | 129 | ||
| 131 | void SetReselectionPending() { | 130 | void SetReselectionPending() { |
| @@ -149,13 +148,15 @@ private: | |||
| 149 | bool AskForReselectionOrMarkRedundant(Thread* current_thread, const Thread* winner); | 148 | bool AskForReselectionOrMarkRedundant(Thread* current_thread, const Thread* winner); |
| 150 | 149 | ||
| 151 | static constexpr u32 min_regular_priority = 2; | 150 | static constexpr u32 min_regular_priority = 2; |
| 152 | std::array<Common::MultiLevelQueue<Thread*, THREADPRIO_COUNT>, NUM_CPU_CORES> scheduled_queue; | 151 | std::array<Common::MultiLevelQueue<Thread*, THREADPRIO_COUNT>, Core::Hardware::NUM_CPU_CORES> |
| 153 | std::array<Common::MultiLevelQueue<Thread*, THREADPRIO_COUNT>, NUM_CPU_CORES> suggested_queue; | 152 | scheduled_queue; |
| 153 | std::array<Common::MultiLevelQueue<Thread*, THREADPRIO_COUNT>, Core::Hardware::NUM_CPU_CORES> | ||
| 154 | suggested_queue; | ||
| 154 | std::atomic<bool> is_reselection_pending{false}; | 155 | std::atomic<bool> is_reselection_pending{false}; |
| 155 | 156 | ||
| 156 | // The priority levels at which the global scheduler preempts threads every 10 ms. They are | 157 | // The priority levels at which the global scheduler preempts threads every 10 ms. They are |
| 157 | // ordered from Core 0 to Core 3. | 158 | // ordered from Core 0 to Core 3. |
| 158 | std::array<u32, NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 62}; | 159 | std::array<u32, Core::Hardware::NUM_CPU_CORES> preemption_priorities = {59, 59, 59, 62}; |
| 159 | 160 | ||
| 160 | /// Lists all thread ids that aren't deleted/etc. | 161 | /// Lists all thread ids that aren't deleted/etc. |
| 161 | std::vector<std::shared_ptr<Thread>> thread_list; | 162 | std::vector<std::shared_ptr<Thread>> thread_list; |
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp index a4ccfa35e..a549ae9d7 100644 --- a/src/core/hle/kernel/server_port.cpp +++ b/src/core/hle/kernel/server_port.cpp | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | namespace Kernel { | 14 | namespace Kernel { |
| 15 | 15 | ||
| 16 | ServerPort::ServerPort(KernelCore& kernel) : WaitObject{kernel} {} | 16 | ServerPort::ServerPort(KernelCore& kernel) : SynchronizationObject{kernel} {} |
| 17 | ServerPort::~ServerPort() = default; | 17 | ServerPort::~ServerPort() = default; |
| 18 | 18 | ||
| 19 | ResultVal<std::shared_ptr<ServerSession>> ServerPort::Accept() { | 19 | ResultVal<std::shared_ptr<ServerSession>> ServerPort::Accept() { |
| @@ -39,6 +39,10 @@ void ServerPort::Acquire(Thread* thread) { | |||
| 39 | ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); | 39 | ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | bool ServerPort::IsSignaled() const { | ||
| 43 | return !pending_sessions.empty(); | ||
| 44 | } | ||
| 45 | |||
| 42 | ServerPort::PortPair ServerPort::CreatePortPair(KernelCore& kernel, u32 max_sessions, | 46 | ServerPort::PortPair ServerPort::CreatePortPair(KernelCore& kernel, u32 max_sessions, |
| 43 | std::string name) { | 47 | std::string name) { |
| 44 | std::shared_ptr<ServerPort> server_port = std::make_shared<ServerPort>(kernel); | 48 | std::shared_ptr<ServerPort> server_port = std::make_shared<ServerPort>(kernel); |
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h index 8be8a75ea..41b191b86 100644 --- a/src/core/hle/kernel/server_port.h +++ b/src/core/hle/kernel/server_port.h | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include <vector> | 10 | #include <vector> |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "core/hle/kernel/object.h" | 12 | #include "core/hle/kernel/object.h" |
| 13 | #include "core/hle/kernel/wait_object.h" | 13 | #include "core/hle/kernel/synchronization_object.h" |
| 14 | #include "core/hle/result.h" | 14 | #include "core/hle/result.h" |
| 15 | 15 | ||
| 16 | namespace Kernel { | 16 | namespace Kernel { |
| @@ -20,7 +20,7 @@ class KernelCore; | |||
| 20 | class ServerSession; | 20 | class ServerSession; |
| 21 | class SessionRequestHandler; | 21 | class SessionRequestHandler; |
| 22 | 22 | ||
| 23 | class ServerPort final : public WaitObject { | 23 | class ServerPort final : public SynchronizationObject { |
| 24 | public: | 24 | public: |
| 25 | explicit ServerPort(KernelCore& kernel); | 25 | explicit ServerPort(KernelCore& kernel); |
| 26 | ~ServerPort() override; | 26 | ~ServerPort() override; |
| @@ -82,6 +82,8 @@ public: | |||
| 82 | bool ShouldWait(const Thread* thread) const override; | 82 | bool ShouldWait(const Thread* thread) const override; |
| 83 | void Acquire(Thread* thread) override; | 83 | void Acquire(Thread* thread) override; |
| 84 | 84 | ||
| 85 | bool IsSignaled() const override; | ||
| 86 | |||
| 85 | private: | 87 | private: |
| 86 | /// ServerSessions waiting to be accepted by the port | 88 | /// ServerSessions waiting to be accepted by the port |
| 87 | std::vector<std::shared_ptr<ServerSession>> pending_sessions; | 89 | std::vector<std::shared_ptr<ServerSession>> pending_sessions; |
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 7825e1ec4..4604e35c5 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | 24 | ||
| 25 | namespace Kernel { | 25 | namespace Kernel { |
| 26 | 26 | ||
| 27 | ServerSession::ServerSession(KernelCore& kernel) : WaitObject{kernel} {} | 27 | ServerSession::ServerSession(KernelCore& kernel) : SynchronizationObject{kernel} {} |
| 28 | ServerSession::~ServerSession() = default; | 28 | ServerSession::~ServerSession() = default; |
| 29 | 29 | ||
| 30 | ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kernel, | 30 | ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kernel, |
| @@ -50,6 +50,16 @@ bool ServerSession::ShouldWait(const Thread* thread) const { | |||
| 50 | return pending_requesting_threads.empty() || currently_handling != nullptr; | 50 | return pending_requesting_threads.empty() || currently_handling != nullptr; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | bool ServerSession::IsSignaled() const { | ||
| 54 | // Closed sessions should never wait, an error will be returned from svcReplyAndReceive. | ||
| 55 | if (!parent->Client()) { | ||
| 56 | return true; | ||
| 57 | } | ||
| 58 | |||
| 59 | // Wait if we have no pending requests, or if we're currently handling a request. | ||
| 60 | return !pending_requesting_threads.empty() && currently_handling == nullptr; | ||
| 61 | } | ||
| 62 | |||
| 53 | void ServerSession::Acquire(Thread* thread) { | 63 | void ServerSession::Acquire(Thread* thread) { |
| 54 | ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); | 64 | ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); |
| 55 | // We are now handling a request, pop it from the stack. | 65 | // We are now handling a request, pop it from the stack. |
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index d6e48109e..77e4f6721 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include <vector> | 10 | #include <vector> |
| 11 | 11 | ||
| 12 | #include "common/threadsafe_queue.h" | 12 | #include "common/threadsafe_queue.h" |
| 13 | #include "core/hle/kernel/wait_object.h" | 13 | #include "core/hle/kernel/synchronization_object.h" |
| 14 | #include "core/hle/result.h" | 14 | #include "core/hle/result.h" |
| 15 | 15 | ||
| 16 | namespace Memory { | 16 | namespace Memory { |
| @@ -41,7 +41,7 @@ class Thread; | |||
| 41 | * After the server replies to the request, the response is marshalled back to the caller's | 41 | * After the server replies to the request, the response is marshalled back to the caller's |
| 42 | * TLS buffer and control is transferred back to it. | 42 | * TLS buffer and control is transferred back to it. |
| 43 | */ | 43 | */ |
| 44 | class ServerSession final : public WaitObject { | 44 | class ServerSession final : public SynchronizationObject { |
| 45 | public: | 45 | public: |
| 46 | explicit ServerSession(KernelCore& kernel); | 46 | explicit ServerSession(KernelCore& kernel); |
| 47 | ~ServerSession() override; | 47 | ~ServerSession() override; |
| @@ -73,6 +73,8 @@ public: | |||
| 73 | return parent.get(); | 73 | return parent.get(); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | bool IsSignaled() const override; | ||
| 77 | |||
| 76 | /** | 78 | /** |
| 77 | * Sets the HLE handler for the session. This handler will be called to service IPC requests | 79 | * Sets the HLE handler for the session. This handler will be called to service IPC requests |
| 78 | * instead of the regular IPC machinery. (The regular IPC machinery is currently not | 80 | * instead of the regular IPC machinery. (The regular IPC machinery is currently not |
diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp index dee6e2b72..e4dd53e24 100644 --- a/src/core/hle/kernel/session.cpp +++ b/src/core/hle/kernel/session.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | namespace Kernel { | 10 | namespace Kernel { |
| 11 | 11 | ||
| 12 | Session::Session(KernelCore& kernel) : WaitObject{kernel} {} | 12 | Session::Session(KernelCore& kernel) : SynchronizationObject{kernel} {} |
| 13 | Session::~Session() = default; | 13 | Session::~Session() = default; |
| 14 | 14 | ||
| 15 | Session::SessionPair Session::Create(KernelCore& kernel, std::string name) { | 15 | Session::SessionPair Session::Create(KernelCore& kernel, std::string name) { |
| @@ -29,6 +29,11 @@ bool Session::ShouldWait(const Thread* thread) const { | |||
| 29 | return {}; | 29 | return {}; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | bool Session::IsSignaled() const { | ||
| 33 | UNIMPLEMENTED(); | ||
| 34 | return true; | ||
| 35 | } | ||
| 36 | |||
| 32 | void Session::Acquire(Thread* thread) { | 37 | void Session::Acquire(Thread* thread) { |
| 33 | UNIMPLEMENTED(); | 38 | UNIMPLEMENTED(); |
| 34 | } | 39 | } |
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h index 15a5ac15f..7cd9c0d77 100644 --- a/src/core/hle/kernel/session.h +++ b/src/core/hle/kernel/session.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include <utility> | 9 | #include <utility> |
| 10 | 10 | ||
| 11 | #include "core/hle/kernel/wait_object.h" | 11 | #include "core/hle/kernel/synchronization_object.h" |
| 12 | 12 | ||
| 13 | namespace Kernel { | 13 | namespace Kernel { |
| 14 | 14 | ||
| @@ -19,7 +19,7 @@ class ServerSession; | |||
| 19 | * Parent structure to link the client and server endpoints of a session with their associated | 19 | * Parent structure to link the client and server endpoints of a session with their associated |
| 20 | * client port. | 20 | * client port. |
| 21 | */ | 21 | */ |
| 22 | class Session final : public WaitObject { | 22 | class Session final : public SynchronizationObject { |
| 23 | public: | 23 | public: |
| 24 | explicit Session(KernelCore& kernel); | 24 | explicit Session(KernelCore& kernel); |
| 25 | ~Session() override; | 25 | ~Session() override; |
| @@ -39,6 +39,8 @@ public: | |||
| 39 | 39 | ||
| 40 | bool ShouldWait(const Thread* thread) const override; | 40 | bool ShouldWait(const Thread* thread) const override; |
| 41 | 41 | ||
| 42 | bool IsSignaled() const override; | ||
| 43 | |||
| 42 | void Acquire(Thread* thread) override; | 44 | void Acquire(Thread* thread) override; |
| 43 | 45 | ||
| 44 | std::shared_ptr<ClientSession> Client() { | 46 | std::shared_ptr<ClientSession> Client() { |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 9cae5c73d..fd91779a3 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include "core/hle/kernel/shared_memory.h" | 32 | #include "core/hle/kernel/shared_memory.h" |
| 33 | #include "core/hle/kernel/svc.h" | 33 | #include "core/hle/kernel/svc.h" |
| 34 | #include "core/hle/kernel/svc_wrap.h" | 34 | #include "core/hle/kernel/svc_wrap.h" |
| 35 | #include "core/hle/kernel/synchronization.h" | ||
| 35 | #include "core/hle/kernel/thread.h" | 36 | #include "core/hle/kernel/thread.h" |
| 36 | #include "core/hle/kernel/transfer_memory.h" | 37 | #include "core/hle/kernel/transfer_memory.h" |
| 37 | #include "core/hle/kernel/writable_event.h" | 38 | #include "core/hle/kernel/writable_event.h" |
| @@ -433,22 +434,6 @@ static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle han | |||
| 433 | return ERR_INVALID_HANDLE; | 434 | return ERR_INVALID_HANDLE; |
| 434 | } | 435 | } |
| 435 | 436 | ||
| 436 | /// Default thread wakeup callback for WaitSynchronization | ||
| 437 | static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, | ||
| 438 | std::shared_ptr<WaitObject> object, std::size_t index) { | ||
| 439 | ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch); | ||
| 440 | |||
| 441 | if (reason == ThreadWakeupReason::Timeout) { | ||
| 442 | thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); | ||
| 443 | return true; | ||
| 444 | } | ||
| 445 | |||
| 446 | ASSERT(reason == ThreadWakeupReason::Signal); | ||
| 447 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | ||
| 448 | thread->SetWaitSynchronizationOutput(static_cast<u32>(index)); | ||
| 449 | return true; | ||
| 450 | }; | ||
| 451 | |||
| 452 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | 437 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds |
| 453 | static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr handles_address, | 438 | static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr handles_address, |
| 454 | u64 handle_count, s64 nano_seconds) { | 439 | u64 handle_count, s64 nano_seconds) { |
| @@ -472,14 +457,14 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr | |||
| 472 | } | 457 | } |
| 473 | 458 | ||
| 474 | auto* const thread = system.CurrentScheduler().GetCurrentThread(); | 459 | auto* const thread = system.CurrentScheduler().GetCurrentThread(); |
| 475 | 460 | auto& kernel = system.Kernel(); | |
| 476 | using ObjectPtr = Thread::ThreadWaitObjects::value_type; | 461 | using ObjectPtr = Thread::ThreadSynchronizationObjects::value_type; |
| 477 | Thread::ThreadWaitObjects objects(handle_count); | 462 | Thread::ThreadSynchronizationObjects objects(handle_count); |
| 478 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 463 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); |
| 479 | 464 | ||
| 480 | for (u64 i = 0; i < handle_count; ++i) { | 465 | for (u64 i = 0; i < handle_count; ++i) { |
| 481 | const Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); | 466 | const Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); |
| 482 | const auto object = handle_table.Get<WaitObject>(handle); | 467 | const auto object = handle_table.Get<SynchronizationObject>(handle); |
| 483 | 468 | ||
| 484 | if (object == nullptr) { | 469 | if (object == nullptr) { |
| 485 | LOG_ERROR(Kernel_SVC, "Object is a nullptr"); | 470 | LOG_ERROR(Kernel_SVC, "Object is a nullptr"); |
| @@ -488,47 +473,10 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr | |||
| 488 | 473 | ||
| 489 | objects[i] = object; | 474 | objects[i] = object; |
| 490 | } | 475 | } |
| 491 | 476 | auto& synchronization = kernel.Synchronization(); | |
| 492 | // Find the first object that is acquirable in the provided list of objects | 477 | const auto [result, handle_result] = synchronization.WaitFor(objects, nano_seconds); |
| 493 | auto itr = std::find_if(objects.begin(), objects.end(), [thread](const ObjectPtr& object) { | 478 | *index = handle_result; |
| 494 | return !object->ShouldWait(thread); | 479 | return result; |
| 495 | }); | ||
| 496 | |||
| 497 | if (itr != objects.end()) { | ||
| 498 | // We found a ready object, acquire it and set the result value | ||
| 499 | WaitObject* object = itr->get(); | ||
| 500 | object->Acquire(thread); | ||
| 501 | *index = static_cast<s32>(std::distance(objects.begin(), itr)); | ||
| 502 | return RESULT_SUCCESS; | ||
| 503 | } | ||
| 504 | |||
| 505 | // No objects were ready to be acquired, prepare to suspend the thread. | ||
| 506 | |||
| 507 | // If a timeout value of 0 was provided, just return the Timeout error code instead of | ||
| 508 | // suspending the thread. | ||
| 509 | if (nano_seconds == 0) { | ||
| 510 | return RESULT_TIMEOUT; | ||
| 511 | } | ||
| 512 | |||
| 513 | if (thread->IsSyncCancelled()) { | ||
| 514 | thread->SetSyncCancelled(false); | ||
| 515 | return ERR_SYNCHRONIZATION_CANCELED; | ||
| 516 | } | ||
| 517 | |||
| 518 | for (auto& object : objects) { | ||
| 519 | object->AddWaitingThread(SharedFrom(thread)); | ||
| 520 | } | ||
| 521 | |||
| 522 | thread->SetWaitObjects(std::move(objects)); | ||
| 523 | thread->SetStatus(ThreadStatus::WaitSynch); | ||
| 524 | |||
| 525 | // Create an event to wake the thread up after the specified nanosecond delay has passed | ||
| 526 | thread->WakeAfterDelay(nano_seconds); | ||
| 527 | thread->SetWakeupCallback(DefaultThreadWakeupCallback); | ||
| 528 | |||
| 529 | system.PrepareReschedule(thread->GetProcessorID()); | ||
| 530 | |||
| 531 | return RESULT_TIMEOUT; | ||
| 532 | } | 480 | } |
| 533 | 481 | ||
| 534 | /// Resumes a thread waiting on WaitSynchronization | 482 | /// Resumes a thread waiting on WaitSynchronization |
diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp new file mode 100644 index 000000000..dc37fad1a --- /dev/null +++ b/src/core/hle/kernel/synchronization.cpp | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/core.h" | ||
| 6 | #include "core/hle/kernel/errors.h" | ||
| 7 | #include "core/hle/kernel/handle_table.h" | ||
| 8 | #include "core/hle/kernel/kernel.h" | ||
| 9 | #include "core/hle/kernel/scheduler.h" | ||
| 10 | #include "core/hle/kernel/synchronization.h" | ||
| 11 | #include "core/hle/kernel/synchronization_object.h" | ||
| 12 | #include "core/hle/kernel/thread.h" | ||
| 13 | |||
| 14 | namespace Kernel { | ||
| 15 | |||
| 16 | /// Default thread wakeup callback for WaitSynchronization | ||
| 17 | static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, | ||
| 18 | std::shared_ptr<SynchronizationObject> object, | ||
| 19 | std::size_t index) { | ||
| 20 | ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch); | ||
| 21 | |||
| 22 | if (reason == ThreadWakeupReason::Timeout) { | ||
| 23 | thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); | ||
| 24 | return true; | ||
| 25 | } | ||
| 26 | |||
| 27 | ASSERT(reason == ThreadWakeupReason::Signal); | ||
| 28 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | ||
| 29 | thread->SetWaitSynchronizationOutput(static_cast<u32>(index)); | ||
| 30 | return true; | ||
| 31 | } | ||
| 32 | |||
| 33 | Synchronization::Synchronization(Core::System& system) : system{system} {} | ||
| 34 | |||
| 35 | void Synchronization::SignalObject(SynchronizationObject& obj) const { | ||
| 36 | if (obj.IsSignaled()) { | ||
| 37 | obj.WakeupAllWaitingThreads(); | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | std::pair<ResultCode, Handle> Synchronization::WaitFor( | ||
| 42 | std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds) { | ||
| 43 | auto* const thread = system.CurrentScheduler().GetCurrentThread(); | ||
| 44 | // Find the first object that is acquirable in the provided list of objects | ||
| 45 | const auto itr = std::find_if(sync_objects.begin(), sync_objects.end(), | ||
| 46 | [thread](const std::shared_ptr<SynchronizationObject>& object) { | ||
| 47 | return object->IsSignaled(); | ||
| 48 | }); | ||
| 49 | |||
| 50 | if (itr != sync_objects.end()) { | ||
| 51 | // We found a ready object, acquire it and set the result value | ||
| 52 | SynchronizationObject* object = itr->get(); | ||
| 53 | object->Acquire(thread); | ||
| 54 | const u32 index = static_cast<s32>(std::distance(sync_objects.begin(), itr)); | ||
| 55 | return {RESULT_SUCCESS, index}; | ||
| 56 | } | ||
| 57 | |||
| 58 | // No objects were ready to be acquired, prepare to suspend the thread. | ||
| 59 | |||
| 60 | // If a timeout value of 0 was provided, just return the Timeout error code instead of | ||
| 61 | // suspending the thread. | ||
| 62 | if (nano_seconds == 0) { | ||
| 63 | return {RESULT_TIMEOUT, InvalidHandle}; | ||
| 64 | } | ||
| 65 | |||
| 66 | if (thread->IsSyncCancelled()) { | ||
| 67 | thread->SetSyncCancelled(false); | ||
| 68 | return {ERR_SYNCHRONIZATION_CANCELED, InvalidHandle}; | ||
| 69 | } | ||
| 70 | |||
| 71 | for (auto& object : sync_objects) { | ||
| 72 | object->AddWaitingThread(SharedFrom(thread)); | ||
| 73 | } | ||
| 74 | |||
| 75 | thread->SetSynchronizationObjects(std::move(sync_objects)); | ||
| 76 | thread->SetStatus(ThreadStatus::WaitSynch); | ||
| 77 | |||
| 78 | // Create an event to wake the thread up after the specified nanosecond delay has passed | ||
| 79 | thread->WakeAfterDelay(nano_seconds); | ||
| 80 | thread->SetWakeupCallback(DefaultThreadWakeupCallback); | ||
| 81 | |||
| 82 | system.PrepareReschedule(thread->GetProcessorID()); | ||
| 83 | |||
| 84 | return {RESULT_TIMEOUT, InvalidHandle}; | ||
| 85 | } | ||
| 86 | |||
| 87 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/synchronization.h b/src/core/hle/kernel/synchronization.h new file mode 100644 index 000000000..379f4b1d3 --- /dev/null +++ b/src/core/hle/kernel/synchronization.h | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <utility> | ||
| 9 | #include <vector> | ||
| 10 | |||
| 11 | #include "core/hle/kernel/object.h" | ||
| 12 | #include "core/hle/result.h" | ||
| 13 | |||
| 14 | namespace Core { | ||
| 15 | class System; | ||
| 16 | } // namespace Core | ||
| 17 | |||
| 18 | namespace Kernel { | ||
| 19 | |||
| 20 | class SynchronizationObject; | ||
| 21 | |||
| 22 | /** | ||
| 23 | * The 'Synchronization' class is an interface for handling synchronization methods | ||
| 24 | * used by Synchronization objects and synchronization SVCs. This centralizes processing of | ||
| 25 | * such | ||
| 26 | */ | ||
| 27 | class Synchronization { | ||
| 28 | public: | ||
| 29 | explicit Synchronization(Core::System& system); | ||
| 30 | |||
| 31 | /// Signals a synchronization object, waking up all its waiting threads | ||
| 32 | void SignalObject(SynchronizationObject& obj) const; | ||
| 33 | |||
| 34 | /// Tries to see if waiting for any of the sync_objects is necessary, if not | ||
| 35 | /// it returns Success and the handle index of the signaled sync object. In | ||
| 36 | /// case not, the current thread will be locked and wait for nano_seconds or | ||
| 37 | /// for a synchronization object to signal. | ||
| 38 | std::pair<ResultCode, Handle> WaitFor( | ||
| 39 | std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds); | ||
| 40 | |||
| 41 | private: | ||
| 42 | Core::System& system; | ||
| 43 | }; | ||
| 44 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/synchronization_object.cpp index 1838260fd..43f3eef18 100644 --- a/src/core/hle/kernel/wait_object.cpp +++ b/src/core/hle/kernel/synchronization_object.cpp | |||
| @@ -10,20 +10,26 @@ | |||
| 10 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/kernel/object.h" | 11 | #include "core/hle/kernel/object.h" |
| 12 | #include "core/hle/kernel/process.h" | 12 | #include "core/hle/kernel/process.h" |
| 13 | #include "core/hle/kernel/synchronization.h" | ||
| 14 | #include "core/hle/kernel/synchronization_object.h" | ||
| 13 | #include "core/hle/kernel/thread.h" | 15 | #include "core/hle/kernel/thread.h" |
| 14 | 16 | ||
| 15 | namespace Kernel { | 17 | namespace Kernel { |
| 16 | 18 | ||
| 17 | WaitObject::WaitObject(KernelCore& kernel) : Object{kernel} {} | 19 | SynchronizationObject::SynchronizationObject(KernelCore& kernel) : Object{kernel} {} |
| 18 | WaitObject::~WaitObject() = default; | 20 | SynchronizationObject::~SynchronizationObject() = default; |
| 19 | 21 | ||
| 20 | void WaitObject::AddWaitingThread(std::shared_ptr<Thread> thread) { | 22 | void SynchronizationObject::Signal() { |
| 23 | kernel.Synchronization().SignalObject(*this); | ||
| 24 | } | ||
| 25 | |||
| 26 | void SynchronizationObject::AddWaitingThread(std::shared_ptr<Thread> thread) { | ||
| 21 | auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread); | 27 | auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread); |
| 22 | if (itr == waiting_threads.end()) | 28 | if (itr == waiting_threads.end()) |
| 23 | waiting_threads.push_back(std::move(thread)); | 29 | waiting_threads.push_back(std::move(thread)); |
| 24 | } | 30 | } |
| 25 | 31 | ||
| 26 | void WaitObject::RemoveWaitingThread(std::shared_ptr<Thread> thread) { | 32 | void SynchronizationObject::RemoveWaitingThread(std::shared_ptr<Thread> thread) { |
| 27 | auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread); | 33 | auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread); |
| 28 | // If a thread passed multiple handles to the same object, | 34 | // If a thread passed multiple handles to the same object, |
| 29 | // the kernel might attempt to remove the thread from the object's | 35 | // the kernel might attempt to remove the thread from the object's |
| @@ -32,7 +38,7 @@ void WaitObject::RemoveWaitingThread(std::shared_ptr<Thread> thread) { | |||
| 32 | waiting_threads.erase(itr); | 38 | waiting_threads.erase(itr); |
| 33 | } | 39 | } |
| 34 | 40 | ||
| 35 | std::shared_ptr<Thread> WaitObject::GetHighestPriorityReadyThread() const { | 41 | std::shared_ptr<Thread> SynchronizationObject::GetHighestPriorityReadyThread() const { |
| 36 | Thread* candidate = nullptr; | 42 | Thread* candidate = nullptr; |
| 37 | u32 candidate_priority = THREADPRIO_LOWEST + 1; | 43 | u32 candidate_priority = THREADPRIO_LOWEST + 1; |
| 38 | 44 | ||
| @@ -57,7 +63,7 @@ std::shared_ptr<Thread> WaitObject::GetHighestPriorityReadyThread() const { | |||
| 57 | return SharedFrom(candidate); | 63 | return SharedFrom(candidate); |
| 58 | } | 64 | } |
| 59 | 65 | ||
| 60 | void WaitObject::WakeupWaitingThread(std::shared_ptr<Thread> thread) { | 66 | void SynchronizationObject::WakeupWaitingThread(std::shared_ptr<Thread> thread) { |
| 61 | ASSERT(!ShouldWait(thread.get())); | 67 | ASSERT(!ShouldWait(thread.get())); |
| 62 | 68 | ||
| 63 | if (!thread) { | 69 | if (!thread) { |
| @@ -65,7 +71,7 @@ void WaitObject::WakeupWaitingThread(std::shared_ptr<Thread> thread) { | |||
| 65 | } | 71 | } |
| 66 | 72 | ||
| 67 | if (thread->IsSleepingOnWait()) { | 73 | if (thread->IsSleepingOnWait()) { |
| 68 | for (const auto& object : thread->GetWaitObjects()) { | 74 | for (const auto& object : thread->GetSynchronizationObjects()) { |
| 69 | ASSERT(!object->ShouldWait(thread.get())); | 75 | ASSERT(!object->ShouldWait(thread.get())); |
| 70 | object->Acquire(thread.get()); | 76 | object->Acquire(thread.get()); |
| 71 | } | 77 | } |
| @@ -73,9 +79,9 @@ void WaitObject::WakeupWaitingThread(std::shared_ptr<Thread> thread) { | |||
| 73 | Acquire(thread.get()); | 79 | Acquire(thread.get()); |
| 74 | } | 80 | } |
| 75 | 81 | ||
| 76 | const std::size_t index = thread->GetWaitObjectIndex(SharedFrom(this)); | 82 | const std::size_t index = thread->GetSynchronizationObjectIndex(SharedFrom(this)); |
| 77 | 83 | ||
| 78 | thread->ClearWaitObjects(); | 84 | thread->ClearSynchronizationObjects(); |
| 79 | 85 | ||
| 80 | thread->CancelWakeupTimer(); | 86 | thread->CancelWakeupTimer(); |
| 81 | 87 | ||
| @@ -90,13 +96,13 @@ void WaitObject::WakeupWaitingThread(std::shared_ptr<Thread> thread) { | |||
| 90 | } | 96 | } |
| 91 | } | 97 | } |
| 92 | 98 | ||
| 93 | void WaitObject::WakeupAllWaitingThreads() { | 99 | void SynchronizationObject::WakeupAllWaitingThreads() { |
| 94 | while (auto thread = GetHighestPriorityReadyThread()) { | 100 | while (auto thread = GetHighestPriorityReadyThread()) { |
| 95 | WakeupWaitingThread(thread); | 101 | WakeupWaitingThread(thread); |
| 96 | } | 102 | } |
| 97 | } | 103 | } |
| 98 | 104 | ||
| 99 | const std::vector<std::shared_ptr<Thread>>& WaitObject::GetWaitingThreads() const { | 105 | const std::vector<std::shared_ptr<Thread>>& SynchronizationObject::GetWaitingThreads() const { |
| 100 | return waiting_threads; | 106 | return waiting_threads; |
| 101 | } | 107 | } |
| 102 | 108 | ||
diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/synchronization_object.h index 9a17958a4..741c31faf 100644 --- a/src/core/hle/kernel/wait_object.h +++ b/src/core/hle/kernel/synchronization_object.h | |||
| @@ -15,10 +15,10 @@ class KernelCore; | |||
| 15 | class Thread; | 15 | class Thread; |
| 16 | 16 | ||
| 17 | /// Class that represents a Kernel object that a thread can be waiting on | 17 | /// Class that represents a Kernel object that a thread can be waiting on |
| 18 | class WaitObject : public Object { | 18 | class SynchronizationObject : public Object { |
| 19 | public: | 19 | public: |
| 20 | explicit WaitObject(KernelCore& kernel); | 20 | explicit SynchronizationObject(KernelCore& kernel); |
| 21 | ~WaitObject() override; | 21 | ~SynchronizationObject() override; |
| 22 | 22 | ||
| 23 | /** | 23 | /** |
| 24 | * Check if the specified thread should wait until the object is available | 24 | * Check if the specified thread should wait until the object is available |
| @@ -30,6 +30,13 @@ public: | |||
| 30 | /// Acquire/lock the object for the specified thread if it is available | 30 | /// Acquire/lock the object for the specified thread if it is available |
| 31 | virtual void Acquire(Thread* thread) = 0; | 31 | virtual void Acquire(Thread* thread) = 0; |
| 32 | 32 | ||
| 33 | /// Signal this object | ||
| 34 | virtual void Signal(); | ||
| 35 | |||
| 36 | virtual bool IsSignaled() const { | ||
| 37 | return is_signaled; | ||
| 38 | } | ||
| 39 | |||
| 33 | /** | 40 | /** |
| 34 | * Add a thread to wait on this object | 41 | * Add a thread to wait on this object |
| 35 | * @param thread Pointer to thread to add | 42 | * @param thread Pointer to thread to add |
| @@ -60,16 +67,20 @@ public: | |||
| 60 | /// Get a const reference to the waiting threads list for debug use | 67 | /// Get a const reference to the waiting threads list for debug use |
| 61 | const std::vector<std::shared_ptr<Thread>>& GetWaitingThreads() const; | 68 | const std::vector<std::shared_ptr<Thread>>& GetWaitingThreads() const; |
| 62 | 69 | ||
| 70 | protected: | ||
| 71 | bool is_signaled{}; // Tells if this sync object is signalled; | ||
| 72 | |||
| 63 | private: | 73 | private: |
| 64 | /// Threads waiting for this object to become available | 74 | /// Threads waiting for this object to become available |
| 65 | std::vector<std::shared_ptr<Thread>> waiting_threads; | 75 | std::vector<std::shared_ptr<Thread>> waiting_threads; |
| 66 | }; | 76 | }; |
| 67 | 77 | ||
| 68 | // Specialization of DynamicObjectCast for WaitObjects | 78 | // Specialization of DynamicObjectCast for SynchronizationObjects |
| 69 | template <> | 79 | template <> |
| 70 | inline std::shared_ptr<WaitObject> DynamicObjectCast<WaitObject>(std::shared_ptr<Object> object) { | 80 | inline std::shared_ptr<SynchronizationObject> DynamicObjectCast<SynchronizationObject>( |
| 81 | std::shared_ptr<Object> object) { | ||
| 71 | if (object != nullptr && object->IsWaitable()) { | 82 | if (object != nullptr && object->IsWaitable()) { |
| 72 | return std::static_pointer_cast<WaitObject>(object); | 83 | return std::static_pointer_cast<SynchronizationObject>(object); |
| 73 | } | 84 | } |
| 74 | return nullptr; | 85 | return nullptr; |
| 75 | } | 86 | } |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index ad464e03b..ae5f2c8bd 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "core/core.h" | 15 | #include "core/core.h" |
| 16 | #include "core/core_timing.h" | 16 | #include "core/core_timing.h" |
| 17 | #include "core/core_timing_util.h" | 17 | #include "core/core_timing_util.h" |
| 18 | #include "core/hardware_properties.h" | ||
| 18 | #include "core/hle/kernel/errors.h" | 19 | #include "core/hle/kernel/errors.h" |
| 19 | #include "core/hle/kernel/handle_table.h" | 20 | #include "core/hle/kernel/handle_table.h" |
| 20 | #include "core/hle/kernel/kernel.h" | 21 | #include "core/hle/kernel/kernel.h" |
| @@ -31,11 +32,15 @@ bool Thread::ShouldWait(const Thread* thread) const { | |||
| 31 | return status != ThreadStatus::Dead; | 32 | return status != ThreadStatus::Dead; |
| 32 | } | 33 | } |
| 33 | 34 | ||
| 35 | bool Thread::IsSignaled() const { | ||
| 36 | return status == ThreadStatus::Dead; | ||
| 37 | } | ||
| 38 | |||
| 34 | void Thread::Acquire(Thread* thread) { | 39 | void Thread::Acquire(Thread* thread) { |
| 35 | ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); | 40 | ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); |
| 36 | } | 41 | } |
| 37 | 42 | ||
| 38 | Thread::Thread(KernelCore& kernel) : WaitObject{kernel} {} | 43 | Thread::Thread(KernelCore& kernel) : SynchronizationObject{kernel} {} |
| 39 | Thread::~Thread() = default; | 44 | Thread::~Thread() = default; |
| 40 | 45 | ||
| 41 | void Thread::Stop() { | 46 | void Thread::Stop() { |
| @@ -45,7 +50,7 @@ void Thread::Stop() { | |||
| 45 | kernel.ThreadWakeupCallbackHandleTable().Close(callback_handle); | 50 | kernel.ThreadWakeupCallbackHandleTable().Close(callback_handle); |
| 46 | callback_handle = 0; | 51 | callback_handle = 0; |
| 47 | SetStatus(ThreadStatus::Dead); | 52 | SetStatus(ThreadStatus::Dead); |
| 48 | WakeupAllWaitingThreads(); | 53 | Signal(); |
| 49 | 54 | ||
| 50 | // Clean up any dangling references in objects that this thread was waiting for | 55 | // Clean up any dangling references in objects that this thread was waiting for |
| 51 | for (auto& wait_object : wait_objects) { | 56 | for (auto& wait_object : wait_objects) { |
| @@ -215,7 +220,7 @@ void Thread::SetWaitSynchronizationOutput(s32 output) { | |||
| 215 | context.cpu_registers[1] = output; | 220 | context.cpu_registers[1] = output; |
| 216 | } | 221 | } |
| 217 | 222 | ||
| 218 | s32 Thread::GetWaitObjectIndex(std::shared_ptr<WaitObject> object) const { | 223 | s32 Thread::GetSynchronizationObjectIndex(std::shared_ptr<SynchronizationObject> object) const { |
| 219 | ASSERT_MSG(!wait_objects.empty(), "Thread is not waiting for anything"); | 224 | ASSERT_MSG(!wait_objects.empty(), "Thread is not waiting for anything"); |
| 220 | const auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object); | 225 | const auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object); |
| 221 | return static_cast<s32>(std::distance(match, wait_objects.rend()) - 1); | 226 | return static_cast<s32>(std::distance(match, wait_objects.rend()) - 1); |
| @@ -336,14 +341,16 @@ void Thread::ChangeCore(u32 core, u64 mask) { | |||
| 336 | SetCoreAndAffinityMask(core, mask); | 341 | SetCoreAndAffinityMask(core, mask); |
| 337 | } | 342 | } |
| 338 | 343 | ||
| 339 | bool Thread::AllWaitObjectsReady() const { | 344 | bool Thread::AllSynchronizationObjectsReady() const { |
| 340 | return std::none_of( | 345 | return std::none_of(wait_objects.begin(), wait_objects.end(), |
| 341 | wait_objects.begin(), wait_objects.end(), | 346 | [this](const std::shared_ptr<SynchronizationObject>& object) { |
| 342 | [this](const std::shared_ptr<WaitObject>& object) { return object->ShouldWait(this); }); | 347 | return object->ShouldWait(this); |
| 348 | }); | ||
| 343 | } | 349 | } |
| 344 | 350 | ||
| 345 | bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, | 351 | bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, |
| 346 | std::shared_ptr<WaitObject> object, std::size_t index) { | 352 | std::shared_ptr<SynchronizationObject> object, |
| 353 | std::size_t index) { | ||
| 347 | ASSERT(wakeup_callback); | 354 | ASSERT(wakeup_callback); |
| 348 | return wakeup_callback(reason, std::move(thread), std::move(object), index); | 355 | return wakeup_callback(reason, std::move(thread), std::move(object), index); |
| 349 | } | 356 | } |
| @@ -425,7 +432,7 @@ ResultCode Thread::SetCoreAndAffinityMask(s32 new_core, u64 new_affinity_mask) { | |||
| 425 | const s32 old_core = processor_id; | 432 | const s32 old_core = processor_id; |
| 426 | if (processor_id >= 0 && ((affinity_mask >> processor_id) & 1) == 0) { | 433 | if (processor_id >= 0 && ((affinity_mask >> processor_id) & 1) == 0) { |
| 427 | if (static_cast<s32>(ideal_core) < 0) { | 434 | if (static_cast<s32>(ideal_core) < 0) { |
| 428 | processor_id = HighestSetCore(affinity_mask, GlobalScheduler::NUM_CPU_CORES); | 435 | processor_id = HighestSetCore(affinity_mask, Core::Hardware::NUM_CPU_CORES); |
| 429 | } else { | 436 | } else { |
| 430 | processor_id = ideal_core; | 437 | processor_id = ideal_core; |
| 431 | } | 438 | } |
| @@ -449,7 +456,7 @@ void Thread::AdjustSchedulingOnStatus(u32 old_flags) { | |||
| 449 | scheduler.Unschedule(current_priority, static_cast<u32>(processor_id), this); | 456 | scheduler.Unschedule(current_priority, static_cast<u32>(processor_id), this); |
| 450 | } | 457 | } |
| 451 | 458 | ||
| 452 | for (u32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { | 459 | for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { |
| 453 | if (core != static_cast<u32>(processor_id) && ((affinity_mask >> core) & 1) != 0) { | 460 | if (core != static_cast<u32>(processor_id) && ((affinity_mask >> core) & 1) != 0) { |
| 454 | scheduler.Unsuggest(current_priority, core, this); | 461 | scheduler.Unsuggest(current_priority, core, this); |
| 455 | } | 462 | } |
| @@ -460,7 +467,7 @@ void Thread::AdjustSchedulingOnStatus(u32 old_flags) { | |||
| 460 | scheduler.Schedule(current_priority, static_cast<u32>(processor_id), this); | 467 | scheduler.Schedule(current_priority, static_cast<u32>(processor_id), this); |
| 461 | } | 468 | } |
| 462 | 469 | ||
| 463 | for (u32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { | 470 | for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { |
| 464 | if (core != static_cast<u32>(processor_id) && ((affinity_mask >> core) & 1) != 0) { | 471 | if (core != static_cast<u32>(processor_id) && ((affinity_mask >> core) & 1) != 0) { |
| 465 | scheduler.Suggest(current_priority, core, this); | 472 | scheduler.Suggest(current_priority, core, this); |
| 466 | } | 473 | } |
| @@ -479,7 +486,7 @@ void Thread::AdjustSchedulingOnPriority(u32 old_priority) { | |||
| 479 | scheduler.Unschedule(old_priority, static_cast<u32>(processor_id), this); | 486 | scheduler.Unschedule(old_priority, static_cast<u32>(processor_id), this); |
| 480 | } | 487 | } |
| 481 | 488 | ||
| 482 | for (u32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { | 489 | for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { |
| 483 | if (core != static_cast<u32>(processor_id) && ((affinity_mask >> core) & 1) != 0) { | 490 | if (core != static_cast<u32>(processor_id) && ((affinity_mask >> core) & 1) != 0) { |
| 484 | scheduler.Unsuggest(old_priority, core, this); | 491 | scheduler.Unsuggest(old_priority, core, this); |
| 485 | } | 492 | } |
| @@ -496,7 +503,7 @@ void Thread::AdjustSchedulingOnPriority(u32 old_priority) { | |||
| 496 | } | 503 | } |
| 497 | } | 504 | } |
| 498 | 505 | ||
| 499 | for (u32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { | 506 | for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { |
| 500 | if (core != static_cast<u32>(processor_id) && ((affinity_mask >> core) & 1) != 0) { | 507 | if (core != static_cast<u32>(processor_id) && ((affinity_mask >> core) & 1) != 0) { |
| 501 | scheduler.Suggest(current_priority, core, this); | 508 | scheduler.Suggest(current_priority, core, this); |
| 502 | } | 509 | } |
| @@ -512,7 +519,7 @@ void Thread::AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core) { | |||
| 512 | return; | 519 | return; |
| 513 | } | 520 | } |
| 514 | 521 | ||
| 515 | for (u32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { | 522 | for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { |
| 516 | if (((old_affinity_mask >> core) & 1) != 0) { | 523 | if (((old_affinity_mask >> core) & 1) != 0) { |
| 517 | if (core == static_cast<u32>(old_core)) { | 524 | if (core == static_cast<u32>(old_core)) { |
| 518 | scheduler.Unschedule(current_priority, core, this); | 525 | scheduler.Unschedule(current_priority, core, this); |
| @@ -522,7 +529,7 @@ void Thread::AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core) { | |||
| 522 | } | 529 | } |
| 523 | } | 530 | } |
| 524 | 531 | ||
| 525 | for (u32 core = 0; core < GlobalScheduler::NUM_CPU_CORES; core++) { | 532 | for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { |
| 526 | if (((affinity_mask >> core) & 1) != 0) { | 533 | if (((affinity_mask >> core) & 1) != 0) { |
| 527 | if (core == static_cast<u32>(processor_id)) { | 534 | if (core == static_cast<u32>(processor_id)) { |
| 528 | scheduler.Schedule(current_priority, core, this); | 535 | scheduler.Schedule(current_priority, core, this); |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 3bcf9e137..7a4916318 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "core/arm/arm_interface.h" | 12 | #include "core/arm/arm_interface.h" |
| 13 | #include "core/hle/kernel/object.h" | 13 | #include "core/hle/kernel/object.h" |
| 14 | #include "core/hle/kernel/wait_object.h" | 14 | #include "core/hle/kernel/synchronization_object.h" |
| 15 | #include "core/hle/result.h" | 15 | #include "core/hle/result.h" |
| 16 | 16 | ||
| 17 | namespace Kernel { | 17 | namespace Kernel { |
| @@ -95,7 +95,7 @@ enum class ThreadSchedMasks : u32 { | |||
| 95 | ForcePauseMask = 0x0070, | 95 | ForcePauseMask = 0x0070, |
| 96 | }; | 96 | }; |
| 97 | 97 | ||
| 98 | class Thread final : public WaitObject { | 98 | class Thread final : public SynchronizationObject { |
| 99 | public: | 99 | public: |
| 100 | explicit Thread(KernelCore& kernel); | 100 | explicit Thread(KernelCore& kernel); |
| 101 | ~Thread() override; | 101 | ~Thread() override; |
| @@ -104,11 +104,11 @@ public: | |||
| 104 | 104 | ||
| 105 | using ThreadContext = Core::ARM_Interface::ThreadContext; | 105 | using ThreadContext = Core::ARM_Interface::ThreadContext; |
| 106 | 106 | ||
| 107 | using ThreadWaitObjects = std::vector<std::shared_ptr<WaitObject>>; | 107 | using ThreadSynchronizationObjects = std::vector<std::shared_ptr<SynchronizationObject>>; |
| 108 | 108 | ||
| 109 | using WakeupCallback = | 109 | using WakeupCallback = |
| 110 | std::function<bool(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, | 110 | std::function<bool(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, |
| 111 | std::shared_ptr<WaitObject> object, std::size_t index)>; | 111 | std::shared_ptr<SynchronizationObject> object, std::size_t index)>; |
| 112 | 112 | ||
| 113 | /** | 113 | /** |
| 114 | * Creates and returns a new thread. The new thread is immediately scheduled | 114 | * Creates and returns a new thread. The new thread is immediately scheduled |
| @@ -146,6 +146,7 @@ public: | |||
| 146 | 146 | ||
| 147 | bool ShouldWait(const Thread* thread) const override; | 147 | bool ShouldWait(const Thread* thread) const override; |
| 148 | void Acquire(Thread* thread) override; | 148 | void Acquire(Thread* thread) override; |
| 149 | bool IsSignaled() const override; | ||
| 149 | 150 | ||
| 150 | /** | 151 | /** |
| 151 | * Gets the thread's current priority | 152 | * Gets the thread's current priority |
| @@ -233,7 +234,7 @@ public: | |||
| 233 | * | 234 | * |
| 234 | * @param object Object to query the index of. | 235 | * @param object Object to query the index of. |
| 235 | */ | 236 | */ |
| 236 | s32 GetWaitObjectIndex(std::shared_ptr<WaitObject> object) const; | 237 | s32 GetSynchronizationObjectIndex(std::shared_ptr<SynchronizationObject> object) const; |
| 237 | 238 | ||
| 238 | /** | 239 | /** |
| 239 | * Stops a thread, invalidating it from further use | 240 | * Stops a thread, invalidating it from further use |
| @@ -314,15 +315,15 @@ public: | |||
| 314 | return owner_process; | 315 | return owner_process; |
| 315 | } | 316 | } |
| 316 | 317 | ||
| 317 | const ThreadWaitObjects& GetWaitObjects() const { | 318 | const ThreadSynchronizationObjects& GetSynchronizationObjects() const { |
| 318 | return wait_objects; | 319 | return wait_objects; |
| 319 | } | 320 | } |
| 320 | 321 | ||
| 321 | void SetWaitObjects(ThreadWaitObjects objects) { | 322 | void SetSynchronizationObjects(ThreadSynchronizationObjects objects) { |
| 322 | wait_objects = std::move(objects); | 323 | wait_objects = std::move(objects); |
| 323 | } | 324 | } |
| 324 | 325 | ||
| 325 | void ClearWaitObjects() { | 326 | void ClearSynchronizationObjects() { |
| 326 | for (const auto& waiting_object : wait_objects) { | 327 | for (const auto& waiting_object : wait_objects) { |
| 327 | waiting_object->RemoveWaitingThread(SharedFrom(this)); | 328 | waiting_object->RemoveWaitingThread(SharedFrom(this)); |
| 328 | } | 329 | } |
| @@ -330,7 +331,7 @@ public: | |||
| 330 | } | 331 | } |
| 331 | 332 | ||
| 332 | /// Determines whether all the objects this thread is waiting on are ready. | 333 | /// Determines whether all the objects this thread is waiting on are ready. |
| 333 | bool AllWaitObjectsReady() const; | 334 | bool AllSynchronizationObjectsReady() const; |
| 334 | 335 | ||
| 335 | const MutexWaitingThreads& GetMutexWaitingThreads() const { | 336 | const MutexWaitingThreads& GetMutexWaitingThreads() const { |
| 336 | return wait_mutex_threads; | 337 | return wait_mutex_threads; |
| @@ -395,7 +396,7 @@ public: | |||
| 395 | * will cause an assertion to trigger. | 396 | * will cause an assertion to trigger. |
| 396 | */ | 397 | */ |
| 397 | bool InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, | 398 | bool InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread, |
| 398 | std::shared_ptr<WaitObject> object, std::size_t index); | 399 | std::shared_ptr<SynchronizationObject> object, std::size_t index); |
| 399 | 400 | ||
| 400 | u32 GetIdealCore() const { | 401 | u32 GetIdealCore() const { |
| 401 | return ideal_core; | 402 | return ideal_core; |
| @@ -494,7 +495,7 @@ private: | |||
| 494 | 495 | ||
| 495 | /// Objects that the thread is waiting on, in the same order as they were | 496 | /// Objects that the thread is waiting on, in the same order as they were |
| 496 | /// passed to WaitSynchronization. | 497 | /// passed to WaitSynchronization. |
| 497 | ThreadWaitObjects wait_objects; | 498 | ThreadSynchronizationObjects wait_objects; |
| 498 | 499 | ||
| 499 | /// List of threads that are waiting for a mutex that is held by this thread. | 500 | /// List of threads that are waiting for a mutex that is held by this thread. |
| 500 | MutexWaitingThreads wait_mutex_threads; | 501 | MutexWaitingThreads wait_mutex_threads; |
diff --git a/src/core/hle/kernel/writable_event.cpp b/src/core/hle/kernel/writable_event.cpp index c9332e3e1..fc2f7c424 100644 --- a/src/core/hle/kernel/writable_event.cpp +++ b/src/core/hle/kernel/writable_event.cpp | |||
| @@ -22,7 +22,6 @@ EventPair WritableEvent::CreateEventPair(KernelCore& kernel, std::string name) { | |||
| 22 | writable_event->name = name + ":Writable"; | 22 | writable_event->name = name + ":Writable"; |
| 23 | writable_event->readable = readable_event; | 23 | writable_event->readable = readable_event; |
| 24 | readable_event->name = name + ":Readable"; | 24 | readable_event->name = name + ":Readable"; |
| 25 | readable_event->signaled = false; | ||
| 26 | 25 | ||
| 27 | return {std::move(readable_event), std::move(writable_event)}; | 26 | return {std::move(readable_event), std::move(writable_event)}; |
| 28 | } | 27 | } |
| @@ -40,7 +39,7 @@ void WritableEvent::Clear() { | |||
| 40 | } | 39 | } |
| 41 | 40 | ||
| 42 | bool WritableEvent::IsSignaled() const { | 41 | bool WritableEvent::IsSignaled() const { |
| 43 | return readable->signaled; | 42 | return readable->IsSignaled(); |
| 44 | } | 43 | } |
| 45 | 44 | ||
| 46 | } // namespace Kernel | 45 | } // namespace Kernel |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 89bf8b815..e6b56a9f9 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "core/core_timing_util.h" | 10 | #include "core/core_timing_util.h" |
| 11 | #include "core/frontend/emu_window.h" | 11 | #include "core/frontend/emu_window.h" |
| 12 | #include "core/frontend/input.h" | 12 | #include "core/frontend/input.h" |
| 13 | #include "core/hardware_properties.h" | ||
| 13 | #include "core/hle/ipc_helpers.h" | 14 | #include "core/hle/ipc_helpers.h" |
| 14 | #include "core/hle/kernel/client_port.h" | 15 | #include "core/hle/kernel/client_port.h" |
| 15 | #include "core/hle/kernel/client_session.h" | 16 | #include "core/hle/kernel/client_session.h" |
| @@ -37,11 +38,11 @@ namespace Service::HID { | |||
| 37 | 38 | ||
| 38 | // Updating period for each HID device. | 39 | // Updating period for each HID device. |
| 39 | // TODO(ogniK): Find actual polling rate of hid | 40 | // TODO(ogniK): Find actual polling rate of hid |
| 40 | constexpr s64 pad_update_ticks = static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 66); | 41 | constexpr s64 pad_update_ticks = static_cast<s64>(Core::Hardware::BASE_CLOCK_RATE / 66); |
| 41 | [[maybe_unused]] constexpr s64 accelerometer_update_ticks = | 42 | [[maybe_unused]] constexpr s64 accelerometer_update_ticks = |
| 42 | static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 100); | 43 | static_cast<s64>(Core::Hardware::BASE_CLOCK_RATE / 100); |
| 43 | [[maybe_unused]] constexpr s64 gyroscope_update_ticks = | 44 | [[maybe_unused]] constexpr s64 gyroscope_update_ticks = |
| 44 | static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 100); | 45 | static_cast<s64>(Core::Hardware::BASE_CLOCK_RATE / 100); |
| 45 | constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; | 46 | constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; |
| 46 | 47 | ||
| 47 | IAppletResource::IAppletResource(Core::System& system) | 48 | IAppletResource::IAppletResource(Core::System& system) |
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 62752e419..134152210 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "core/core.h" | 12 | #include "core/core.h" |
| 13 | #include "core/core_timing.h" | 13 | #include "core/core_timing.h" |
| 14 | #include "core/core_timing_util.h" | 14 | #include "core/core_timing_util.h" |
| 15 | #include "core/hardware_properties.h" | ||
| 15 | #include "core/hle/kernel/kernel.h" | 16 | #include "core/hle/kernel/kernel.h" |
| 16 | #include "core/hle/kernel/readable_event.h" | 17 | #include "core/hle/kernel/readable_event.h" |
| 17 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | 18 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" |
| @@ -26,8 +27,8 @@ | |||
| 26 | 27 | ||
| 27 | namespace Service::NVFlinger { | 28 | namespace Service::NVFlinger { |
| 28 | 29 | ||
| 29 | constexpr s64 frame_ticks = static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 60); | 30 | constexpr s64 frame_ticks = static_cast<s64>(Core::Hardware::BASE_CLOCK_RATE / 60); |
| 30 | constexpr s64 frame_ticks_30fps = static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 30); | 31 | constexpr s64 frame_ticks_30fps = static_cast<s64>(Core::Hardware::BASE_CLOCK_RATE / 30); |
| 31 | 32 | ||
| 32 | NVFlinger::NVFlinger(Core::System& system) : system(system) { | 33 | NVFlinger::NVFlinger(Core::System& system) : system(system) { |
| 33 | displays.emplace_back(0, "Default", system); | 34 | displays.emplace_back(0, "Default", system); |
| @@ -222,7 +223,7 @@ void NVFlinger::Compose() { | |||
| 222 | 223 | ||
| 223 | s64 NVFlinger::GetNextTicks() const { | 224 | s64 NVFlinger::GetNextTicks() const { |
| 224 | constexpr s64 max_hertz = 120LL; | 225 | constexpr s64 max_hertz = 120LL; |
| 225 | return (Core::Timing::BASE_CLOCK_RATE * (1LL << swap_interval)) / max_hertz; | 226 | return (Core::Hardware::BASE_CLOCK_RATE * (1LL << swap_interval)) / max_hertz; |
| 226 | } | 227 | } |
| 227 | 228 | ||
| 228 | } // namespace Service::NVFlinger | 229 | } // namespace Service::NVFlinger |
diff --git a/src/core/hle/service/time/standard_steady_clock_core.cpp b/src/core/hle/service/time/standard_steady_clock_core.cpp index ca1a783fc..1575f0b49 100644 --- a/src/core/hle/service/time/standard_steady_clock_core.cpp +++ b/src/core/hle/service/time/standard_steady_clock_core.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/core_timing.h" | 6 | #include "core/core_timing.h" |
| 7 | #include "core/core_timing_util.h" | 7 | #include "core/core_timing_util.h" |
| 8 | #include "core/hardware_properties.h" | ||
| 8 | #include "core/hle/service/time/standard_steady_clock_core.h" | 9 | #include "core/hle/service/time/standard_steady_clock_core.h" |
| 9 | 10 | ||
| 10 | namespace Service::Time::Clock { | 11 | namespace Service::Time::Clock { |
| @@ -12,7 +13,7 @@ namespace Service::Time::Clock { | |||
| 12 | TimeSpanType StandardSteadyClockCore::GetCurrentRawTimePoint(Core::System& system) { | 13 | TimeSpanType StandardSteadyClockCore::GetCurrentRawTimePoint(Core::System& system) { |
| 13 | const TimeSpanType ticks_time_span{TimeSpanType::FromTicks( | 14 | const TimeSpanType ticks_time_span{TimeSpanType::FromTicks( |
| 14 | Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()), | 15 | Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()), |
| 15 | Core::Timing::CNTFREQ)}; | 16 | Core::Hardware::CNTFREQ)}; |
| 16 | TimeSpanType raw_time_point{setup_value.nanoseconds + ticks_time_span.nanoseconds}; | 17 | TimeSpanType raw_time_point{setup_value.nanoseconds + ticks_time_span.nanoseconds}; |
| 17 | 18 | ||
| 18 | if (raw_time_point.nanoseconds < cached_raw_time_point.nanoseconds) { | 19 | if (raw_time_point.nanoseconds < cached_raw_time_point.nanoseconds) { |
diff --git a/src/core/hle/service/time/tick_based_steady_clock_core.cpp b/src/core/hle/service/time/tick_based_steady_clock_core.cpp index c77b98189..44d5bc651 100644 --- a/src/core/hle/service/time/tick_based_steady_clock_core.cpp +++ b/src/core/hle/service/time/tick_based_steady_clock_core.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/core_timing.h" | 6 | #include "core/core_timing.h" |
| 7 | #include "core/core_timing_util.h" | 7 | #include "core/core_timing_util.h" |
| 8 | #include "core/hardware_properties.h" | ||
| 8 | #include "core/hle/service/time/tick_based_steady_clock_core.h" | 9 | #include "core/hle/service/time/tick_based_steady_clock_core.h" |
| 9 | 10 | ||
| 10 | namespace Service::Time::Clock { | 11 | namespace Service::Time::Clock { |
| @@ -12,7 +13,7 @@ namespace Service::Time::Clock { | |||
| 12 | SteadyClockTimePoint TickBasedSteadyClockCore::GetTimePoint(Core::System& system) { | 13 | SteadyClockTimePoint TickBasedSteadyClockCore::GetTimePoint(Core::System& system) { |
| 13 | const TimeSpanType ticks_time_span{TimeSpanType::FromTicks( | 14 | const TimeSpanType ticks_time_span{TimeSpanType::FromTicks( |
| 14 | Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()), | 15 | Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()), |
| 15 | Core::Timing::CNTFREQ)}; | 16 | Core::Hardware::CNTFREQ)}; |
| 16 | 17 | ||
| 17 | return {ticks_time_span.ToSeconds(), GetClockSourceId()}; | 18 | return {ticks_time_span.ToSeconds(), GetClockSourceId()}; |
| 18 | } | 19 | } |
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index 8ef4efcef..749b7be70 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/core_timing.h" | 7 | #include "core/core_timing.h" |
| 8 | #include "core/core_timing_util.h" | 8 | #include "core/core_timing_util.h" |
| 9 | #include "core/hardware_properties.h" | ||
| 9 | #include "core/hle/ipc_helpers.h" | 10 | #include "core/hle/ipc_helpers.h" |
| 10 | #include "core/hle/kernel/client_port.h" | 11 | #include "core/hle/kernel/client_port.h" |
| 11 | #include "core/hle/kernel/client_session.h" | 12 | #include "core/hle/kernel/client_session.h" |
| @@ -233,7 +234,7 @@ void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERe | |||
| 233 | if (current_time_point.clock_source_id == context.steady_time_point.clock_source_id) { | 234 | if (current_time_point.clock_source_id == context.steady_time_point.clock_source_id) { |
| 234 | const auto ticks{Clock::TimeSpanType::FromTicks( | 235 | const auto ticks{Clock::TimeSpanType::FromTicks( |
| 235 | Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()), | 236 | Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()), |
| 236 | Core::Timing::CNTFREQ)}; | 237 | Core::Hardware::CNTFREQ)}; |
| 237 | const s64 base_time_point{context.offset + current_time_point.time_point - | 238 | const s64 base_time_point{context.offset + current_time_point.time_point - |
| 238 | ticks.ToSeconds()}; | 239 | ticks.ToSeconds()}; |
| 239 | IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2}; | 240 | IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2}; |
diff --git a/src/core/hle/service/time/time_sharedmemory.cpp b/src/core/hle/service/time/time_sharedmemory.cpp index 9b03191bf..fdaef233f 100644 --- a/src/core/hle/service/time/time_sharedmemory.cpp +++ b/src/core/hle/service/time/time_sharedmemory.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/core_timing.h" | 6 | #include "core/core_timing.h" |
| 7 | #include "core/core_timing_util.h" | 7 | #include "core/core_timing_util.h" |
| 8 | #include "core/hardware_properties.h" | ||
| 8 | #include "core/hle/service/time/clock_types.h" | 9 | #include "core/hle/service/time/clock_types.h" |
| 9 | #include "core/hle/service/time/steady_clock_core.h" | 10 | #include "core/hle/service/time/steady_clock_core.h" |
| 10 | #include "core/hle/service/time/time_sharedmemory.h" | 11 | #include "core/hle/service/time/time_sharedmemory.h" |
| @@ -31,7 +32,7 @@ void SharedMemory::SetupStandardSteadyClock(Core::System& system, | |||
| 31 | Clock::TimeSpanType current_time_point) { | 32 | Clock::TimeSpanType current_time_point) { |
| 32 | const Clock::TimeSpanType ticks_time_span{Clock::TimeSpanType::FromTicks( | 33 | const Clock::TimeSpanType ticks_time_span{Clock::TimeSpanType::FromTicks( |
| 33 | Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()), | 34 | Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()), |
| 34 | Core::Timing::CNTFREQ)}; | 35 | Core::Hardware::CNTFREQ)}; |
| 35 | const Clock::SteadyClockContext context{ | 36 | const Clock::SteadyClockContext context{ |
| 36 | static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds), | 37 | static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds), |
| 37 | clock_source_id}; | 38 | clock_source_id}; |
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index d1e6bed93..4472500d2 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/core_timing.h" | 10 | #include "core/core_timing.h" |
| 11 | #include "core/core_timing_util.h" | 11 | #include "core/core_timing_util.h" |
| 12 | #include "core/hardware_properties.h" | ||
| 12 | #include "core/hle/kernel/process.h" | 13 | #include "core/hle/kernel/process.h" |
| 13 | #include "core/hle/service/hid/controllers/npad.h" | 14 | #include "core/hle/service/hid/controllers/npad.h" |
| 14 | #include "core/hle/service/hid/hid.h" | 15 | #include "core/hle/service/hid/hid.h" |
| @@ -17,7 +18,7 @@ | |||
| 17 | 18 | ||
| 18 | namespace Memory { | 19 | namespace Memory { |
| 19 | 20 | ||
| 20 | constexpr s64 CHEAT_ENGINE_TICKS = static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 12); | 21 | constexpr s64 CHEAT_ENGINE_TICKS = static_cast<s64>(Core::Hardware::BASE_CLOCK_RATE / 12); |
| 21 | constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF; | 22 | constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF; |
| 22 | 23 | ||
| 23 | StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata) | 24 | StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata) |
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp index 55e0dbc49..1e060f009 100644 --- a/src/core/tools/freezer.cpp +++ b/src/core/tools/freezer.cpp | |||
| @@ -7,13 +7,14 @@ | |||
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 9 | #include "core/core_timing_util.h" | 9 | #include "core/core_timing_util.h" |
| 10 | #include "core/hardware_properties.h" | ||
| 10 | #include "core/memory.h" | 11 | #include "core/memory.h" |
| 11 | #include "core/tools/freezer.h" | 12 | #include "core/tools/freezer.h" |
| 12 | 13 | ||
| 13 | namespace Tools { | 14 | namespace Tools { |
| 14 | namespace { | 15 | namespace { |
| 15 | 16 | ||
| 16 | constexpr s64 MEMORY_FREEZER_TICKS = static_cast<s64>(Core::Timing::BASE_CLOCK_RATE / 60); | 17 | constexpr s64 MEMORY_FREEZER_TICKS = static_cast<s64>(Core::Hardware::BASE_CLOCK_RATE / 60); |
| 17 | 18 | ||
| 18 | u64 MemoryReadWidth(Memory::Memory& memory, u32 width, VAddr addr) { | 19 | u64 MemoryReadWidth(Memory::Memory& memory, u32 width, VAddr addr) { |
| 19 | switch (width) { | 20 | switch (width) { |
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 727bd8a94..3f1a94627 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | #include "core/hle/kernel/process.h" | 12 | #include "core/hle/kernel/process.h" |
| 13 | #include "core/hle/kernel/readable_event.h" | 13 | #include "core/hle/kernel/readable_event.h" |
| 14 | #include "core/hle/kernel/scheduler.h" | 14 | #include "core/hle/kernel/scheduler.h" |
| 15 | #include "core/hle/kernel/synchronization_object.h" | ||
| 15 | #include "core/hle/kernel/thread.h" | 16 | #include "core/hle/kernel/thread.h" |
| 16 | #include "core/hle/kernel/wait_object.h" | ||
| 17 | #include "core/memory.h" | 17 | #include "core/memory.h" |
| 18 | 18 | ||
| 19 | WaitTreeItem::WaitTreeItem() = default; | 19 | WaitTreeItem::WaitTreeItem() = default; |
| @@ -133,8 +133,9 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() cons | |||
| 133 | return list; | 133 | return list; |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | WaitTreeWaitObject::WaitTreeWaitObject(const Kernel::WaitObject& o) : object(o) {} | 136 | WaitTreeSynchronizationObject::WaitTreeSynchronizationObject(const Kernel::SynchronizationObject& o) |
| 137 | WaitTreeWaitObject::~WaitTreeWaitObject() = default; | 137 | : object(o) {} |
| 138 | WaitTreeSynchronizationObject::~WaitTreeSynchronizationObject() = default; | ||
| 138 | 139 | ||
| 139 | WaitTreeExpandableItem::WaitTreeExpandableItem() = default; | 140 | WaitTreeExpandableItem::WaitTreeExpandableItem() = default; |
| 140 | WaitTreeExpandableItem::~WaitTreeExpandableItem() = default; | 141 | WaitTreeExpandableItem::~WaitTreeExpandableItem() = default; |
| @@ -143,25 +144,26 @@ bool WaitTreeExpandableItem::IsExpandable() const { | |||
| 143 | return true; | 144 | return true; |
| 144 | } | 145 | } |
| 145 | 146 | ||
| 146 | QString WaitTreeWaitObject::GetText() const { | 147 | QString WaitTreeSynchronizationObject::GetText() const { |
| 147 | return tr("[%1]%2 %3") | 148 | return tr("[%1]%2 %3") |
| 148 | .arg(object.GetObjectId()) | 149 | .arg(object.GetObjectId()) |
| 149 | .arg(QString::fromStdString(object.GetTypeName()), | 150 | .arg(QString::fromStdString(object.GetTypeName()), |
| 150 | QString::fromStdString(object.GetName())); | 151 | QString::fromStdString(object.GetName())); |
| 151 | } | 152 | } |
| 152 | 153 | ||
| 153 | std::unique_ptr<WaitTreeWaitObject> WaitTreeWaitObject::make(const Kernel::WaitObject& object) { | 154 | std::unique_ptr<WaitTreeSynchronizationObject> WaitTreeSynchronizationObject::make( |
| 155 | const Kernel::SynchronizationObject& object) { | ||
| 154 | switch (object.GetHandleType()) { | 156 | switch (object.GetHandleType()) { |
| 155 | case Kernel::HandleType::ReadableEvent: | 157 | case Kernel::HandleType::ReadableEvent: |
| 156 | return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::ReadableEvent&>(object)); | 158 | return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::ReadableEvent&>(object)); |
| 157 | case Kernel::HandleType::Thread: | 159 | case Kernel::HandleType::Thread: |
| 158 | return std::make_unique<WaitTreeThread>(static_cast<const Kernel::Thread&>(object)); | 160 | return std::make_unique<WaitTreeThread>(static_cast<const Kernel::Thread&>(object)); |
| 159 | default: | 161 | default: |
| 160 | return std::make_unique<WaitTreeWaitObject>(object); | 162 | return std::make_unique<WaitTreeSynchronizationObject>(object); |
| 161 | } | 163 | } |
| 162 | } | 164 | } |
| 163 | 165 | ||
| 164 | std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeWaitObject::GetChildren() const { | 166 | std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeSynchronizationObject::GetChildren() const { |
| 165 | std::vector<std::unique_ptr<WaitTreeItem>> list; | 167 | std::vector<std::unique_ptr<WaitTreeItem>> list; |
| 166 | 168 | ||
| 167 | const auto& threads = object.GetWaitingThreads(); | 169 | const auto& threads = object.GetWaitingThreads(); |
| @@ -173,8 +175,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeWaitObject::GetChildren() con | |||
| 173 | return list; | 175 | return list; |
| 174 | } | 176 | } |
| 175 | 177 | ||
| 176 | WaitTreeObjectList::WaitTreeObjectList(const std::vector<std::shared_ptr<Kernel::WaitObject>>& list, | 178 | WaitTreeObjectList::WaitTreeObjectList( |
| 177 | bool w_all) | 179 | const std::vector<std::shared_ptr<Kernel::SynchronizationObject>>& list, bool w_all) |
| 178 | : object_list(list), wait_all(w_all) {} | 180 | : object_list(list), wait_all(w_all) {} |
| 179 | 181 | ||
| 180 | WaitTreeObjectList::~WaitTreeObjectList() = default; | 182 | WaitTreeObjectList::~WaitTreeObjectList() = default; |
| @@ -188,11 +190,12 @@ QString WaitTreeObjectList::GetText() const { | |||
| 188 | std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeObjectList::GetChildren() const { | 190 | std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeObjectList::GetChildren() const { |
| 189 | std::vector<std::unique_ptr<WaitTreeItem>> list(object_list.size()); | 191 | std::vector<std::unique_ptr<WaitTreeItem>> list(object_list.size()); |
| 190 | std::transform(object_list.begin(), object_list.end(), list.begin(), | 192 | std::transform(object_list.begin(), object_list.end(), list.begin(), |
| 191 | [](const auto& t) { return WaitTreeWaitObject::make(*t); }); | 193 | [](const auto& t) { return WaitTreeSynchronizationObject::make(*t); }); |
| 192 | return list; | 194 | return list; |
| 193 | } | 195 | } |
| 194 | 196 | ||
| 195 | WaitTreeThread::WaitTreeThread(const Kernel::Thread& thread) : WaitTreeWaitObject(thread) {} | 197 | WaitTreeThread::WaitTreeThread(const Kernel::Thread& thread) |
| 198 | : WaitTreeSynchronizationObject(thread) {} | ||
| 196 | WaitTreeThread::~WaitTreeThread() = default; | 199 | WaitTreeThread::~WaitTreeThread() = default; |
| 197 | 200 | ||
| 198 | QString WaitTreeThread::GetText() const { | 201 | QString WaitTreeThread::GetText() const { |
| @@ -241,7 +244,8 @@ QString WaitTreeThread::GetText() const { | |||
| 241 | const QString pc_info = tr(" PC = 0x%1 LR = 0x%2") | 244 | const QString pc_info = tr(" PC = 0x%1 LR = 0x%2") |
| 242 | .arg(context.pc, 8, 16, QLatin1Char{'0'}) | 245 | .arg(context.pc, 8, 16, QLatin1Char{'0'}) |
| 243 | .arg(context.cpu_registers[30], 8, 16, QLatin1Char{'0'}); | 246 | .arg(context.cpu_registers[30], 8, 16, QLatin1Char{'0'}); |
| 244 | return QStringLiteral("%1%2 (%3) ").arg(WaitTreeWaitObject::GetText(), pc_info, status); | 247 | return QStringLiteral("%1%2 (%3) ") |
| 248 | .arg(WaitTreeSynchronizationObject::GetText(), pc_info, status); | ||
| 245 | } | 249 | } |
| 246 | 250 | ||
| 247 | QColor WaitTreeThread::GetColor() const { | 251 | QColor WaitTreeThread::GetColor() const { |
| @@ -273,7 +277,7 @@ QColor WaitTreeThread::GetColor() const { | |||
| 273 | } | 277 | } |
| 274 | 278 | ||
| 275 | std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const { | 279 | std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const { |
| 276 | std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren()); | 280 | std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeSynchronizationObject::GetChildren()); |
| 277 | 281 | ||
| 278 | const auto& thread = static_cast<const Kernel::Thread&>(object); | 282 | const auto& thread = static_cast<const Kernel::Thread&>(object); |
| 279 | 283 | ||
| @@ -314,7 +318,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const { | |||
| 314 | } | 318 | } |
| 315 | 319 | ||
| 316 | if (thread.GetStatus() == Kernel::ThreadStatus::WaitSynch) { | 320 | if (thread.GetStatus() == Kernel::ThreadStatus::WaitSynch) { |
| 317 | list.push_back(std::make_unique<WaitTreeObjectList>(thread.GetWaitObjects(), | 321 | list.push_back(std::make_unique<WaitTreeObjectList>(thread.GetSynchronizationObjects(), |
| 318 | thread.IsSleepingOnWait())); | 322 | thread.IsSleepingOnWait())); |
| 319 | } | 323 | } |
| 320 | 324 | ||
| @@ -323,7 +327,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const { | |||
| 323 | return list; | 327 | return list; |
| 324 | } | 328 | } |
| 325 | 329 | ||
| 326 | WaitTreeEvent::WaitTreeEvent(const Kernel::ReadableEvent& object) : WaitTreeWaitObject(object) {} | 330 | WaitTreeEvent::WaitTreeEvent(const Kernel::ReadableEvent& object) |
| 331 | : WaitTreeSynchronizationObject(object) {} | ||
| 327 | WaitTreeEvent::~WaitTreeEvent() = default; | 332 | WaitTreeEvent::~WaitTreeEvent() = default; |
| 328 | 333 | ||
| 329 | WaitTreeThreadList::WaitTreeThreadList(const std::vector<std::shared_ptr<Kernel::Thread>>& list) | 334 | WaitTreeThreadList::WaitTreeThreadList(const std::vector<std::shared_ptr<Kernel::Thread>>& list) |
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h index 631274a5f..8e3bc4b24 100644 --- a/src/yuzu/debugger/wait_tree.h +++ b/src/yuzu/debugger/wait_tree.h | |||
| @@ -19,7 +19,7 @@ class EmuThread; | |||
| 19 | namespace Kernel { | 19 | namespace Kernel { |
| 20 | class HandleTable; | 20 | class HandleTable; |
| 21 | class ReadableEvent; | 21 | class ReadableEvent; |
| 22 | class WaitObject; | 22 | class SynchronizationObject; |
| 23 | class Thread; | 23 | class Thread; |
| 24 | } // namespace Kernel | 24 | } // namespace Kernel |
| 25 | 25 | ||
| @@ -99,35 +99,37 @@ private: | |||
| 99 | const Kernel::Thread& thread; | 99 | const Kernel::Thread& thread; |
| 100 | }; | 100 | }; |
| 101 | 101 | ||
| 102 | class WaitTreeWaitObject : public WaitTreeExpandableItem { | 102 | class WaitTreeSynchronizationObject : public WaitTreeExpandableItem { |
| 103 | Q_OBJECT | 103 | Q_OBJECT |
| 104 | public: | 104 | public: |
| 105 | explicit WaitTreeWaitObject(const Kernel::WaitObject& object); | 105 | explicit WaitTreeSynchronizationObject(const Kernel::SynchronizationObject& object); |
| 106 | ~WaitTreeWaitObject() override; | 106 | ~WaitTreeSynchronizationObject() override; |
| 107 | 107 | ||
| 108 | static std::unique_ptr<WaitTreeWaitObject> make(const Kernel::WaitObject& object); | 108 | static std::unique_ptr<WaitTreeSynchronizationObject> make( |
| 109 | const Kernel::SynchronizationObject& object); | ||
| 109 | QString GetText() const override; | 110 | QString GetText() const override; |
| 110 | std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; | 111 | std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; |
| 111 | 112 | ||
| 112 | protected: | 113 | protected: |
| 113 | const Kernel::WaitObject& object; | 114 | const Kernel::SynchronizationObject& object; |
| 114 | }; | 115 | }; |
| 115 | 116 | ||
| 116 | class WaitTreeObjectList : public WaitTreeExpandableItem { | 117 | class WaitTreeObjectList : public WaitTreeExpandableItem { |
| 117 | Q_OBJECT | 118 | Q_OBJECT |
| 118 | public: | 119 | public: |
| 119 | WaitTreeObjectList(const std::vector<std::shared_ptr<Kernel::WaitObject>>& list, bool wait_all); | 120 | WaitTreeObjectList(const std::vector<std::shared_ptr<Kernel::SynchronizationObject>>& list, |
| 121 | bool wait_all); | ||
| 120 | ~WaitTreeObjectList() override; | 122 | ~WaitTreeObjectList() override; |
| 121 | 123 | ||
| 122 | QString GetText() const override; | 124 | QString GetText() const override; |
| 123 | std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; | 125 | std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; |
| 124 | 126 | ||
| 125 | private: | 127 | private: |
| 126 | const std::vector<std::shared_ptr<Kernel::WaitObject>>& object_list; | 128 | const std::vector<std::shared_ptr<Kernel::SynchronizationObject>>& object_list; |
| 127 | bool wait_all; | 129 | bool wait_all; |
| 128 | }; | 130 | }; |
| 129 | 131 | ||
| 130 | class WaitTreeThread : public WaitTreeWaitObject { | 132 | class WaitTreeThread : public WaitTreeSynchronizationObject { |
| 131 | Q_OBJECT | 133 | Q_OBJECT |
| 132 | public: | 134 | public: |
| 133 | explicit WaitTreeThread(const Kernel::Thread& thread); | 135 | explicit WaitTreeThread(const Kernel::Thread& thread); |
| @@ -138,7 +140,7 @@ public: | |||
| 138 | std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; | 140 | std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; |
| 139 | }; | 141 | }; |
| 140 | 142 | ||
| 141 | class WaitTreeEvent : public WaitTreeWaitObject { | 143 | class WaitTreeEvent : public WaitTreeSynchronizationObject { |
| 142 | Q_OBJECT | 144 | Q_OBJECT |
| 143 | public: | 145 | public: |
| 144 | explicit WaitTreeEvent(const Kernel::ReadableEvent& object); | 146 | explicit WaitTreeEvent(const Kernel::ReadableEvent& object); |