diff options
| -rw-r--r-- | src/core/hardware_properties.h | 31 | ||||
| -rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/server_session.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/synchronization.cpp | 21 | ||||
| -rw-r--r-- | src/core/hle/kernel/synchronization.h | 14 |
6 files changed, 50 insertions, 24 deletions
diff --git a/src/core/hardware_properties.h b/src/core/hardware_properties.h index 62cdf9ef0..947140efb 100644 --- a/src/core/hardware_properties.h +++ b/src/core/hardware_properties.h | |||
| @@ -8,14 +8,6 @@ | |||
| 8 | 8 | ||
| 9 | namespace Core { | 9 | namespace Core { |
| 10 | 10 | ||
| 11 | union EmuThreadHandle { | ||
| 12 | u64 raw; | ||
| 13 | struct { | ||
| 14 | u32 host_handle; | ||
| 15 | u32 guest_handle; | ||
| 16 | }; | ||
| 17 | }; | ||
| 18 | |||
| 19 | namespace Hardware { | 11 | namespace Hardware { |
| 20 | 12 | ||
| 21 | // The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz | 13 | // The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz |
| @@ -23,6 +15,29 @@ namespace Hardware { | |||
| 23 | constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch cpu frequency is 1020MHz un/docked | 15 | constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch cpu frequency is 1020MHz un/docked |
| 24 | constexpr u64 CNTFREQ = 19200000; // Switch's hardware clock speed | 16 | constexpr u64 CNTFREQ = 19200000; // Switch's hardware clock speed |
| 25 | constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores | 17 | constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores |
| 18 | |||
| 26 | } // namespace Hardware | 19 | } // namespace Hardware |
| 27 | 20 | ||
| 21 | struct EmuThreadHandle { | ||
| 22 | u32 host_handle; | ||
| 23 | u32 guest_handle; | ||
| 24 | |||
| 25 | u64 GetRaw() const { | ||
| 26 | return (static_cast<u64>(host_handle) << 32) | guest_handle; | ||
| 27 | } | ||
| 28 | |||
| 29 | bool operator==(const EmuThreadHandle& rhs) const { | ||
| 30 | return std::tie(host_handle, guest_handle) == std::tie(rhs.host_handle, rhs.guest_handle); | ||
| 31 | } | ||
| 32 | |||
| 33 | bool operator!=(const EmuThreadHandle& rhs) const { | ||
| 34 | return !operator==(rhs); | ||
| 35 | } | ||
| 36 | |||
| 37 | static constexpr EmuThreadHandle InvalidHandle() { | ||
| 38 | constexpr u32 invalid_handle = 0xFFFFFFFF; | ||
| 39 | return {invalid_handle, invalid_handle}; | ||
| 40 | } | ||
| 41 | }; | ||
| 42 | |||
| 28 | } // namespace Core | 43 | } // namespace Core |
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index b5ffa5418..86f1421bf 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp | |||
| @@ -125,7 +125,7 @@ bool GlobalScheduler::YieldThreadAndBalanceLoad(Thread* yielding_thread) { | |||
| 125 | scheduled_queue[core_id].yield(priority); | 125 | scheduled_queue[core_id].yield(priority); |
| 126 | 126 | ||
| 127 | std::array<Thread*, Core::Hardware::NUM_CPU_CORES> current_threads; | 127 | std::array<Thread*, Core::Hardware::NUM_CPU_CORES> current_threads; |
| 128 | for (u32 i = 0; i < Core::Hardware::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 | ||
| @@ -178,7 +178,7 @@ bool GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread | |||
| 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*, Core::Hardware::NUM_CPU_CORES> current_threads; | 180 | std::array<Thread*, Core::Hardware::NUM_CPU_CORES> current_threads; |
| 181 | for (u32 i = 0; i < Core::Hardware::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]) { |
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index ca98fd984..4604e35c5 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp | |||
| @@ -57,7 +57,7 @@ bool ServerSession::IsSignaled() const { | |||
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | // Wait if we have no pending requests, or if we're currently handling a request. | 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); | 60 | return !pending_requesting_threads.empty() && currently_handling == nullptr; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | void ServerSession::Acquire(Thread* thread) { | 63 | void ServerSession::Acquire(Thread* thread) { |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 86c660cdf..fd91779a3 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -474,7 +474,7 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr | |||
| 474 | objects[i] = object; | 474 | objects[i] = object; |
| 475 | } | 475 | } |
| 476 | auto& synchronization = kernel.Synchronization(); | 476 | auto& synchronization = kernel.Synchronization(); |
| 477 | auto [result, handle_result] = synchronization.WaitFor(objects, nano_seconds); | 477 | const auto [result, handle_result] = synchronization.WaitFor(objects, nano_seconds); |
| 478 | *index = handle_result; | 478 | *index = handle_result; |
| 479 | return result; | 479 | return result; |
| 480 | } | 480 | } |
diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp index 25afc162f..dc37fad1a 100644 --- a/src/core/hle/kernel/synchronization.cpp +++ b/src/core/hle/kernel/synchronization.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hle/kernel/errors.h" | 6 | #include "core/hle/kernel/errors.h" |
| 7 | #include "core/hle/kernel/handle_table.h" | ||
| 7 | #include "core/hle/kernel/kernel.h" | 8 | #include "core/hle/kernel/kernel.h" |
| 8 | #include "core/hle/kernel/scheduler.h" | 9 | #include "core/hle/kernel/scheduler.h" |
| 9 | #include "core/hle/kernel/synchronization.h" | 10 | #include "core/hle/kernel/synchronization.h" |
| @@ -27,30 +28,30 @@ static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, std::shared_p | |||
| 27 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | 28 | thread->SetWaitSynchronizationResult(RESULT_SUCCESS); |
| 28 | thread->SetWaitSynchronizationOutput(static_cast<u32>(index)); | 29 | thread->SetWaitSynchronizationOutput(static_cast<u32>(index)); |
| 29 | return true; | 30 | return true; |
| 30 | }; | 31 | } |
| 31 | 32 | ||
| 32 | Synchronization::Synchronization(Core::System& system) : system{system} {} | 33 | Synchronization::Synchronization(Core::System& system) : system{system} {} |
| 33 | 34 | ||
| 34 | void Synchronization::SignalObject(SynchronizationObject& obj) const { | 35 | void Synchronization::SignalObject(SynchronizationObject& obj) const { |
| 35 | if (obj.IsSignaled()) { | 36 | if (obj.IsSignaled()) { |
| 36 | obj.WakeupAllWaitingThreads(); | 37 | obj.WakeupAllWaitingThreads(); |
| 37 | }; | 38 | } |
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | std::pair<ResultCode, Handle> Synchronization::WaitFor( | 41 | std::pair<ResultCode, Handle> Synchronization::WaitFor( |
| 41 | std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds) { | 42 | std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds) { |
| 42 | auto* const thread = system.CurrentScheduler().GetCurrentThread(); | 43 | auto* const thread = system.CurrentScheduler().GetCurrentThread(); |
| 43 | // Find the first object that is acquirable in the provided list of objects | 44 | // Find the first object that is acquirable in the provided list of objects |
| 44 | auto itr = std::find_if(sync_objects.begin(), sync_objects.end(), | 45 | const auto itr = std::find_if(sync_objects.begin(), sync_objects.end(), |
| 45 | [thread](const std::shared_ptr<SynchronizationObject>& object) { | 46 | [thread](const std::shared_ptr<SynchronizationObject>& object) { |
| 46 | return object->IsSignaled(); | 47 | return object->IsSignaled(); |
| 47 | }); | 48 | }); |
| 48 | 49 | ||
| 49 | if (itr != sync_objects.end()) { | 50 | if (itr != sync_objects.end()) { |
| 50 | // We found a ready object, acquire it and set the result value | 51 | // We found a ready object, acquire it and set the result value |
| 51 | SynchronizationObject* object = itr->get(); | 52 | SynchronizationObject* object = itr->get(); |
| 52 | object->Acquire(thread); | 53 | object->Acquire(thread); |
| 53 | u32 index = static_cast<s32>(std::distance(sync_objects.begin(), itr)); | 54 | const u32 index = static_cast<s32>(std::distance(sync_objects.begin(), itr)); |
| 54 | return {RESULT_SUCCESS, index}; | 55 | return {RESULT_SUCCESS, index}; |
| 55 | } | 56 | } |
| 56 | 57 | ||
| @@ -59,12 +60,12 @@ std::pair<ResultCode, Handle> Synchronization::WaitFor( | |||
| 59 | // If a timeout value of 0 was provided, just return the Timeout error code instead of | 60 | // If a timeout value of 0 was provided, just return the Timeout error code instead of |
| 60 | // suspending the thread. | 61 | // suspending the thread. |
| 61 | if (nano_seconds == 0) { | 62 | if (nano_seconds == 0) { |
| 62 | return {RESULT_TIMEOUT, 0}; | 63 | return {RESULT_TIMEOUT, InvalidHandle}; |
| 63 | } | 64 | } |
| 64 | 65 | ||
| 65 | if (thread->IsSyncCancelled()) { | 66 | if (thread->IsSyncCancelled()) { |
| 66 | thread->SetSyncCancelled(false); | 67 | thread->SetSyncCancelled(false); |
| 67 | return {ERR_SYNCHRONIZATION_CANCELED, 0}; | 68 | return {ERR_SYNCHRONIZATION_CANCELED, InvalidHandle}; |
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | for (auto& object : sync_objects) { | 71 | for (auto& object : sync_objects) { |
| @@ -80,7 +81,7 @@ std::pair<ResultCode, Handle> Synchronization::WaitFor( | |||
| 80 | 81 | ||
| 81 | system.PrepareReschedule(thread->GetProcessorID()); | 82 | system.PrepareReschedule(thread->GetProcessorID()); |
| 82 | 83 | ||
| 83 | return {RESULT_TIMEOUT, 0}; | 84 | return {RESULT_TIMEOUT, InvalidHandle}; |
| 84 | } | 85 | } |
| 85 | 86 | ||
| 86 | } // namespace Kernel | 87 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/synchronization.h b/src/core/hle/kernel/synchronization.h index 3417a9f13..379f4b1d3 100644 --- a/src/core/hle/kernel/synchronization.h +++ b/src/core/hle/kernel/synchronization.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <utility> | 8 | #include <utility> |
| 9 | #include <vector> | ||
| 9 | 10 | ||
| 10 | #include "core/hle/kernel/object.h" | 11 | #include "core/hle/kernel/object.h" |
| 11 | #include "core/hle/result.h" | 12 | #include "core/hle/result.h" |
| @@ -16,15 +17,24 @@ class System; | |||
| 16 | 17 | ||
| 17 | namespace Kernel { | 18 | namespace Kernel { |
| 18 | 19 | ||
| 19 | class KernelCore; | ||
| 20 | class SynchronizationObject; | 20 | class SynchronizationObject; |
| 21 | 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 | */ | ||
| 22 | class Synchronization { | 27 | class Synchronization { |
| 23 | public: | 28 | public: |
| 24 | Synchronization(Core::System& system); | 29 | explicit Synchronization(Core::System& system); |
| 25 | 30 | ||
| 31 | /// Signals a synchronization object, waking up all its waiting threads | ||
| 26 | void SignalObject(SynchronizationObject& obj) const; | 32 | void SignalObject(SynchronizationObject& obj) const; |
| 27 | 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. | ||
| 28 | std::pair<ResultCode, Handle> WaitFor( | 38 | std::pair<ResultCode, Handle> WaitFor( |
| 29 | std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds); | 39 | std::vector<std::shared_ptr<SynchronizationObject>>& sync_objects, s64 nano_seconds); |
| 30 | 40 | ||