summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/bit_util.h1
-rw-r--r--src/common/multi_level_queue.h14
-rw-r--r--src/core/hle/kernel/scheduler.cpp15
-rw-r--r--src/tests/common/bit_utils.cpp39
-rw-r--r--src/tests/common/multi_level_queue.cpp2
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
64inline u32 CountTrailingZeroes32(u32 value) { 63inline 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
14namespace Common { 15namespace 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 */
16template <typename T, std::size_t Depth> 25template <typename T, std::size_t Depth>
17class MultiLevelQueue { 26class MultiLevelQueue {
18public: 27public:
@@ -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
177void Scheduler::SetThreadPriority(Thread* thread, u32 priority) { 178void 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
9namespace Common { 9namespace Common {
10 10
11inline u32 CTZ32(u32 value) { 11TEST_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);
20inline 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
30TEST_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
12TEST_CASE("MultiLevelQueue", "[common]") { 12TEST_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);