diff options
| -rw-r--r-- | src/common/bit_util.h | 1 | ||||
| -rw-r--r-- | src/common/multi_level_queue.h | 14 | ||||
| -rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 15 | ||||
| -rw-r--r-- | src/tests/common/bit_utils.cpp | 39 | ||||
| -rw-r--r-- | src/tests/common/multi_level_queue.cpp | 2 |
5 files changed, 30 insertions, 41 deletions
diff --git a/src/common/bit_util.h b/src/common/bit_util.h index 70e728a5e..a4f9ed4aa 100644 --- a/src/common/bit_util.h +++ b/src/common/bit_util.h | |||
| @@ -59,7 +59,6 @@ inline u64 CountLeadingZeroes64(u64 value) { | |||
| 59 | } | 59 | } |
| 60 | #endif | 60 | #endif |
| 61 | 61 | ||
| 62 | |||
| 63 | #ifdef _MSC_VER | 62 | #ifdef _MSC_VER |
| 64 | inline u32 CountTrailingZeroes32(u32 value) { | 63 | inline u32 CountTrailingZeroes32(u32 value) { |
| 65 | unsigned long trailing_zero = 0; | 64 | unsigned long trailing_zero = 0; |
diff --git a/src/common/multi_level_queue.h b/src/common/multi_level_queue.h index 68b35ffaa..2b61b91e0 100644 --- a/src/common/multi_level_queue.h +++ b/src/common/multi_level_queue.h | |||
| @@ -7,12 +7,21 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <iterator> | 8 | #include <iterator> |
| 9 | #include <list> | 9 | #include <list> |
| 10 | #include <utility> | ||
| 10 | 11 | ||
| 11 | #include "common/bit_util.h" | 12 | #include "common/bit_util.h" |
| 12 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 13 | 14 | ||
| 14 | namespace Common { | 15 | namespace Common { |
| 15 | 16 | ||
| 17 | /** | ||
| 18 | * A MultiLevelQueue is a type of priority queue which has the following characteristics: | ||
| 19 | * - iteratable through each of its elements. | ||
| 20 | * - back can be obtained. | ||
| 21 | * - O(1) add, lookup (both front and back) | ||
| 22 | * - discrete priorities and a max of 64 priorities (limited domain) | ||
| 23 | * This type of priority queue is normaly used for managing threads within an scheduler | ||
| 24 | */ | ||
| 16 | template <typename T, std::size_t Depth> | 25 | template <typename T, std::size_t Depth> |
| 17 | class MultiLevelQueue { | 26 | class MultiLevelQueue { |
| 18 | public: | 27 | public: |
| @@ -37,9 +46,7 @@ public: | |||
| 37 | friend bool operator==(const iterator_impl& lhs, const iterator_impl& rhs) { | 46 | friend bool operator==(const iterator_impl& lhs, const iterator_impl& rhs) { |
| 38 | if (lhs.IsEnd() && rhs.IsEnd()) | 47 | if (lhs.IsEnd() && rhs.IsEnd()) |
| 39 | return true; | 48 | return true; |
| 40 | if (lhs.current_priority == rhs.current_priority) | 49 | return std::tie(lhs.current_priority, lhs.it) == std::tie(rhs.current_priority, rhs.it); |
| 41 | return lhs.it == rhs.it; | ||
| 42 | return false; | ||
| 43 | } | 50 | } |
| 44 | 51 | ||
| 45 | friend bool operator!=(const iterator_impl& lhs, const iterator_impl& rhs) { | 52 | friend bool operator!=(const iterator_impl& lhs, const iterator_impl& rhs) { |
| @@ -301,7 +308,6 @@ private: | |||
| 301 | using const_list_iterator = typename std::list<T>::const_iterator; | 308 | using const_list_iterator = typename std::list<T>::const_iterator; |
| 302 | 309 | ||
| 303 | static void ListShiftForward(std::list<T>& list, const std::size_t shift = 1) { | 310 | static void ListShiftForward(std::list<T>& list, const std::size_t shift = 1) { |
| 304 | // NOTE: May want to consider making this an assertion or something | ||
| 305 | if (shift >= list.size()) { | 311 | if (shift >= list.size()) { |
| 306 | return; | 312 | return; |
| 307 | } | 313 | } |
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 58217b732..6d0f13ecf 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp | |||
| @@ -45,10 +45,10 @@ Thread* Scheduler::PopNextReadyThread() { | |||
| 45 | Thread* next = nullptr; | 45 | Thread* next = nullptr; |
| 46 | Thread* thread = GetCurrentThread(); | 46 | Thread* thread = GetCurrentThread(); |
| 47 | 47 | ||
| 48 | |||
| 49 | if (thread && thread->GetStatus() == ThreadStatus::Running) { | 48 | if (thread && thread->GetStatus() == ThreadStatus::Running) { |
| 50 | if (ready_queue.empty()) | 49 | if (ready_queue.empty()) { |
| 51 | return thread; | 50 | return thread; |
| 51 | } | ||
| 52 | // We have to do better than the current thread. | 52 | // We have to do better than the current thread. |
| 53 | // This call returns null when that's not possible. | 53 | // This call returns null when that's not possible. |
| 54 | next = ready_queue.front(); | 54 | next = ready_queue.front(); |
| @@ -56,8 +56,9 @@ Thread* Scheduler::PopNextReadyThread() { | |||
| 56 | next = thread; | 56 | next = thread; |
| 57 | } | 57 | } |
| 58 | } else { | 58 | } else { |
| 59 | if (ready_queue.empty()) | 59 | if (ready_queue.empty()) { |
| 60 | return nullptr; | 60 | return nullptr; |
| 61 | } | ||
| 61 | next = ready_queue.front(); | 62 | next = ready_queue.front(); |
| 62 | } | 63 | } |
| 63 | 64 | ||
| @@ -176,8 +177,9 @@ void Scheduler::UnscheduleThread(Thread* thread, u32 priority) { | |||
| 176 | 177 | ||
| 177 | void Scheduler::SetThreadPriority(Thread* thread, u32 priority) { | 178 | void Scheduler::SetThreadPriority(Thread* thread, u32 priority) { |
| 178 | std::lock_guard<std::mutex> lock(scheduler_mutex); | 179 | std::lock_guard<std::mutex> lock(scheduler_mutex); |
| 179 | if (thread->GetPriority() == priority) | 180 | if (thread->GetPriority() == priority) { |
| 180 | return; | 181 | return; |
| 182 | } | ||
| 181 | 183 | ||
| 182 | // If thread was ready, adjust queues | 184 | // If thread was ready, adjust queues |
| 183 | if (thread->GetStatus() == ThreadStatus::Ready) | 185 | if (thread->GetStatus() == ThreadStatus::Ready) |
| @@ -188,9 +190,10 @@ Thread* Scheduler::GetNextSuggestedThread(u32 core, u32 maximum_priority) const | |||
| 188 | std::lock_guard<std::mutex> lock(scheduler_mutex); | 190 | std::lock_guard<std::mutex> lock(scheduler_mutex); |
| 189 | 191 | ||
| 190 | const u32 mask = 1U << core; | 192 | const u32 mask = 1U << core; |
| 191 | for (auto& thread : ready_queue) { | 193 | for (auto* thread : ready_queue) { |
| 192 | if ((thread->GetAffinityMask() & mask) != 0 && thread->GetPriority() < maximum_priority) | 194 | if ((thread->GetAffinityMask() & mask) != 0 && thread->GetPriority() < maximum_priority) { |
| 193 | return thread; | 195 | return thread; |
| 196 | } | ||
| 194 | } | 197 | } |
| 195 | return nullptr; | 198 | return nullptr; |
| 196 | } | 199 | } |
diff --git a/src/tests/common/bit_utils.cpp b/src/tests/common/bit_utils.cpp index 77c17c526..479b5995a 100644 --- a/src/tests/common/bit_utils.cpp +++ b/src/tests/common/bit_utils.cpp | |||
| @@ -8,35 +8,16 @@ | |||
| 8 | 8 | ||
| 9 | namespace Common { | 9 | namespace Common { |
| 10 | 10 | ||
| 11 | inline u32 CTZ32(u32 value) { | 11 | TEST_CASE("BitUtils::CountTrailingZeroes", "[common]") { |
| 12 | u32 count = 0; | 12 | REQUIRE(Common::CountTrailingZeroes32(0) == 32); |
| 13 | while (((value >> count) & 0xf) == 0 && count < 32) | 13 | REQUIRE(Common::CountTrailingZeroes64(0) == 64); |
| 14 | count += 4; | 14 | REQUIRE(Common::CountTrailingZeroes32(9) == 0); |
| 15 | while (((value >> count) & 1) == 0 && count < 32) | 15 | REQUIRE(Common::CountTrailingZeroes32(8) == 3); |
| 16 | count++; | 16 | REQUIRE(Common::CountTrailingZeroes32(0x801000) == 12); |
| 17 | return count; | 17 | REQUIRE(Common::CountTrailingZeroes64(9) == 0); |
| 18 | } | 18 | REQUIRE(Common::CountTrailingZeroes64(8) == 3); |
| 19 | 19 | REQUIRE(Common::CountTrailingZeroes64(0x801000) == 12); | |
| 20 | inline u64 CTZ64(u64 value) { | 20 | REQUIRE(Common::CountTrailingZeroes64(0x801000000000UL) == 36); |
| 21 | u64 count = 0; | ||
| 22 | while (((value >> count) & 0xf) == 0 && count < 64) | ||
| 23 | count += 4; | ||
| 24 | while (((value >> count) & 1) == 0 && count < 64) | ||
| 25 | count++; | ||
| 26 | return count; | ||
| 27 | } | ||
| 28 | |||
| 29 | |||
| 30 | TEST_CASE("BitUtils", "[common]") { | ||
| 31 | REQUIRE(Common::CountTrailingZeroes32(0) == CTZ32(0)); | ||
| 32 | REQUIRE(Common::CountTrailingZeroes64(0) == CTZ64(0)); | ||
| 33 | REQUIRE(Common::CountTrailingZeroes32(9) == CTZ32(9)); | ||
| 34 | REQUIRE(Common::CountTrailingZeroes32(8) == CTZ32(8)); | ||
| 35 | REQUIRE(Common::CountTrailingZeroes32(0x801000) == CTZ32(0x801000)); | ||
| 36 | REQUIRE(Common::CountTrailingZeroes64(9) == CTZ64(9)); | ||
| 37 | REQUIRE(Common::CountTrailingZeroes64(8) == CTZ64(8)); | ||
| 38 | REQUIRE(Common::CountTrailingZeroes64(0x801000) == CTZ64(0x801000)); | ||
| 39 | REQUIRE(Common::CountTrailingZeroes64(0x801000000000UL) == CTZ64(0x801000000000UL)); | ||
| 40 | } | 21 | } |
| 41 | 22 | ||
| 42 | } // namespace Common | 23 | } // namespace Common |
diff --git a/src/tests/common/multi_level_queue.cpp b/src/tests/common/multi_level_queue.cpp index 9a8b84695..cca7ec7da 100644 --- a/src/tests/common/multi_level_queue.cpp +++ b/src/tests/common/multi_level_queue.cpp | |||
| @@ -11,7 +11,7 @@ namespace Common { | |||
| 11 | 11 | ||
| 12 | TEST_CASE("MultiLevelQueue", "[common]") { | 12 | TEST_CASE("MultiLevelQueue", "[common]") { |
| 13 | std::array<f32, 8> values = {0.0, 5.0, 1.0, 9.0, 8.0, 2.0, 6.0, 7.0}; | 13 | std::array<f32, 8> values = {0.0, 5.0, 1.0, 9.0, 8.0, 2.0, 6.0, 7.0}; |
| 14 | Common::MultiLevelQueue<f32,64> mlq; | 14 | Common::MultiLevelQueue<f32, 64> mlq; |
| 15 | REQUIRE(mlq.empty()); | 15 | REQUIRE(mlq.empty()); |
| 16 | mlq.add(values[2], 2); | 16 | mlq.add(values[2], 2); |
| 17 | mlq.add(values[7], 7); | 17 | mlq.add(values[7], 7); |