summaryrefslogtreecommitdiff
path: root/src/tests
diff options
context:
space:
mode:
authorGravatar Liam2022-07-02 12:33:49 -0400
committerGravatar Liam2022-07-02 12:33:49 -0400
commited0319cfed2c99e6366aaf725d96bb28a9332e4d (patch)
tree1598e6d320005e0d177106e28ebc6728234f1f24 /src/tests
parentMerge pull request #7454 from FernandoS27/new-core-timing (diff)
downloadyuzu-ed0319cfed2c99e6366aaf725d96bb28a9332e4d.tar.gz
yuzu-ed0319cfed2c99e6366aaf725d96bb28a9332e4d.tar.xz
yuzu-ed0319cfed2c99e6366aaf725d96bb28a9332e4d.zip
common/fiber: make fibers easier to use
Diffstat (limited to 'src/tests')
-rw-r--r--src/tests/common/fibers.cpp123
1 files changed, 35 insertions, 88 deletions
diff --git a/src/tests/common/fibers.cpp b/src/tests/common/fibers.cpp
index cfc84d423..4e29f9199 100644
--- a/src/tests/common/fibers.cpp
+++ b/src/tests/common/fibers.cpp
@@ -43,7 +43,15 @@ class TestControl1 {
43public: 43public:
44 TestControl1() = default; 44 TestControl1() = default;
45 45
46 void DoWork(); 46 void DoWork() {
47 const u32 id = thread_ids.Get();
48 u32 value = items[id];
49 for (u32 i = 0; i < id; i++) {
50 value++;
51 }
52 results[id] = value;
53 Fiber::YieldTo(work_fibers[id], *thread_fibers[id]);
54 }
47 55
48 void ExecuteThread(u32 id); 56 void ExecuteThread(u32 id);
49 57
@@ -54,35 +62,16 @@ public:
54 std::vector<u32> results; 62 std::vector<u32> results;
55}; 63};
56 64
57static void WorkControl1(void* control) {
58 auto* test_control = static_cast<TestControl1*>(control);
59 test_control->DoWork();
60}
61
62void TestControl1::DoWork() {
63 const u32 id = thread_ids.Get();
64 u32 value = items[id];
65 for (u32 i = 0; i < id; i++) {
66 value++;
67 }
68 results[id] = value;
69 Fiber::YieldTo(work_fibers[id], *thread_fibers[id]);
70}
71
72void TestControl1::ExecuteThread(u32 id) { 65void TestControl1::ExecuteThread(u32 id) {
73 thread_ids.Register(id); 66 thread_ids.Register(id);
74 auto thread_fiber = Fiber::ThreadToFiber(); 67 auto thread_fiber = Fiber::ThreadToFiber();
75 thread_fibers[id] = thread_fiber; 68 thread_fibers[id] = thread_fiber;
76 work_fibers[id] = std::make_shared<Fiber>(std::function<void(void*)>{WorkControl1}, this); 69 work_fibers[id] = std::make_shared<Fiber>([this] { DoWork(); });
77 items[id] = rand() % 256; 70 items[id] = rand() % 256;
78 Fiber::YieldTo(thread_fibers[id], *work_fibers[id]); 71 Fiber::YieldTo(thread_fibers[id], *work_fibers[id]);
79 thread_fibers[id]->Exit(); 72 thread_fibers[id]->Exit();
80} 73}
81 74
82static void ThreadStart1(u32 id, TestControl1& test_control) {
83 test_control.ExecuteThread(id);
84}
85
86/** This test checks for fiber setup configuration and validates that fibers are 75/** This test checks for fiber setup configuration and validates that fibers are
87 * doing all the work required. 76 * doing all the work required.
88 */ 77 */
@@ -95,7 +84,7 @@ TEST_CASE("Fibers::Setup", "[common]") {
95 test_control.results.resize(num_threads, 0); 84 test_control.results.resize(num_threads, 0);
96 std::vector<std::thread> threads; 85 std::vector<std::thread> threads;
97 for (u32 i = 0; i < num_threads; i++) { 86 for (u32 i = 0; i < num_threads; i++) {
98 threads.emplace_back(ThreadStart1, i, std::ref(test_control)); 87 threads.emplace_back([&test_control, i] { test_control.ExecuteThread(i); });
99 } 88 }
100 for (u32 i = 0; i < num_threads; i++) { 89 for (u32 i = 0; i < num_threads; i++) {
101 threads[i].join(); 90 threads[i].join();
@@ -167,21 +156,6 @@ public:
167 std::shared_ptr<Common::Fiber> fiber3; 156 std::shared_ptr<Common::Fiber> fiber3;
168}; 157};
169 158
170static void WorkControl2_1(void* control) {
171 auto* test_control = static_cast<TestControl2*>(control);
172 test_control->DoWork1();
173}
174
175static void WorkControl2_2(void* control) {
176 auto* test_control = static_cast<TestControl2*>(control);
177 test_control->DoWork2();
178}
179
180static void WorkControl2_3(void* control) {
181 auto* test_control = static_cast<TestControl2*>(control);
182 test_control->DoWork3();
183}
184
185void TestControl2::ExecuteThread(u32 id) { 159void TestControl2::ExecuteThread(u32 id) {
186 thread_ids.Register(id); 160 thread_ids.Register(id);
187 auto thread_fiber = Fiber::ThreadToFiber(); 161 auto thread_fiber = Fiber::ThreadToFiber();
@@ -193,18 +167,6 @@ void TestControl2::Exit() {
193 thread_fibers[id]->Exit(); 167 thread_fibers[id]->Exit();
194} 168}
195 169
196static void ThreadStart2_1(u32 id, TestControl2& test_control) {
197 test_control.ExecuteThread(id);
198 test_control.CallFiber1();
199 test_control.Exit();
200}
201
202static void ThreadStart2_2(u32 id, TestControl2& test_control) {
203 test_control.ExecuteThread(id);
204 test_control.CallFiber2();
205 test_control.Exit();
206}
207
208/** This test checks for fiber thread exchange configuration and validates that fibers are 170/** This test checks for fiber thread exchange configuration and validates that fibers are
209 * that a fiber has been successfully transferred from one thread to another and that the TLS 171 * that a fiber has been successfully transferred from one thread to another and that the TLS
210 * region of the thread is kept while changing fibers. 172 * region of the thread is kept while changing fibers.
@@ -212,14 +174,19 @@ static void ThreadStart2_2(u32 id, TestControl2& test_control) {
212TEST_CASE("Fibers::InterExchange", "[common]") { 174TEST_CASE("Fibers::InterExchange", "[common]") {
213 TestControl2 test_control{}; 175 TestControl2 test_control{};
214 test_control.thread_fibers.resize(2); 176 test_control.thread_fibers.resize(2);
215 test_control.fiber1 = 177 test_control.fiber1 = std::make_shared<Fiber>([&test_control] { test_control.DoWork1(); });
216 std::make_shared<Fiber>(std::function<void(void*)>{WorkControl2_1}, &test_control); 178 test_control.fiber2 = std::make_shared<Fiber>([&test_control] { test_control.DoWork2(); });
217 test_control.fiber2 = 179 test_control.fiber3 = std::make_shared<Fiber>([&test_control] { test_control.DoWork3(); });
218 std::make_shared<Fiber>(std::function<void(void*)>{WorkControl2_2}, &test_control); 180 std::thread thread1{[&test_control] {
219 test_control.fiber3 = 181 test_control.ExecuteThread(0);
220 std::make_shared<Fiber>(std::function<void(void*)>{WorkControl2_3}, &test_control); 182 test_control.CallFiber1();
221 std::thread thread1(ThreadStart2_1, 0, std::ref(test_control)); 183 test_control.Exit();
222 std::thread thread2(ThreadStart2_2, 1, std::ref(test_control)); 184 }};
185 std::thread thread2{[&test_control] {
186 test_control.ExecuteThread(1);
187 test_control.CallFiber2();
188 test_control.Exit();
189 }};
223 thread1.join(); 190 thread1.join();
224 thread2.join(); 191 thread2.join();
225 REQUIRE(test_control.assert1); 192 REQUIRE(test_control.assert1);
@@ -270,16 +237,6 @@ public:
270 std::shared_ptr<Common::Fiber> fiber2; 237 std::shared_ptr<Common::Fiber> fiber2;
271}; 238};
272 239
273static void WorkControl3_1(void* control) {
274 auto* test_control = static_cast<TestControl3*>(control);
275 test_control->DoWork1();
276}
277
278static void WorkControl3_2(void* control) {
279 auto* test_control = static_cast<TestControl3*>(control);
280 test_control->DoWork2();
281}
282
283void TestControl3::ExecuteThread(u32 id) { 240void TestControl3::ExecuteThread(u32 id) {
284 thread_ids.Register(id); 241 thread_ids.Register(id);
285 auto thread_fiber = Fiber::ThreadToFiber(); 242 auto thread_fiber = Fiber::ThreadToFiber();
@@ -291,12 +248,6 @@ void TestControl3::Exit() {
291 thread_fibers[id]->Exit(); 248 thread_fibers[id]->Exit();
292} 249}
293 250
294static void ThreadStart3(u32 id, TestControl3& test_control) {
295 test_control.ExecuteThread(id);
296 test_control.CallFiber1();
297 test_control.Exit();
298}
299
300/** This test checks for one two threads racing for starting the same fiber. 251/** This test checks for one two threads racing for starting the same fiber.
301 * It checks execution occurred in an ordered manner and by no time there were 252 * It checks execution occurred in an ordered manner and by no time there were
302 * two contexts at the same time. 253 * two contexts at the same time.
@@ -304,12 +255,15 @@ static void ThreadStart3(u32 id, TestControl3& test_control) {
304TEST_CASE("Fibers::StartRace", "[common]") { 255TEST_CASE("Fibers::StartRace", "[common]") {
305 TestControl3 test_control{}; 256 TestControl3 test_control{};
306 test_control.thread_fibers.resize(2); 257 test_control.thread_fibers.resize(2);
307 test_control.fiber1 = 258 test_control.fiber1 = std::make_shared<Fiber>([&test_control] { test_control.DoWork1(); });
308 std::make_shared<Fiber>(std::function<void(void*)>{WorkControl3_1}, &test_control); 259 test_control.fiber2 = std::make_shared<Fiber>([&test_control] { test_control.DoWork2(); });
309 test_control.fiber2 = 260 const auto race_function{[&test_control](u32 id) {
310 std::make_shared<Fiber>(std::function<void(void*)>{WorkControl3_2}, &test_control); 261 test_control.ExecuteThread(id);
311 std::thread thread1(ThreadStart3, 0, std::ref(test_control)); 262 test_control.CallFiber1();
312 std::thread thread2(ThreadStart3, 1, std::ref(test_control)); 263 test_control.Exit();
264 }};
265 std::thread thread1([&] { race_function(0); });
266 std::thread thread2([&] { race_function(1); });
313 thread1.join(); 267 thread1.join();
314 thread2.join(); 268 thread2.join();
315 REQUIRE(test_control.value1 == 1); 269 REQUIRE(test_control.value1 == 1);
@@ -319,12 +273,10 @@ TEST_CASE("Fibers::StartRace", "[common]") {
319 273
320class TestControl4; 274class TestControl4;
321 275
322static void WorkControl4(void* control);
323
324class TestControl4 { 276class TestControl4 {
325public: 277public:
326 TestControl4() { 278 TestControl4() {
327 fiber1 = std::make_shared<Fiber>(std::function<void(void*)>{WorkControl4}, this); 279 fiber1 = std::make_shared<Fiber>([this] { DoWork(); });
328 goal_reached = false; 280 goal_reached = false;
329 rewinded = false; 281 rewinded = false;
330 } 282 }
@@ -336,7 +288,7 @@ public:
336 } 288 }
337 289
338 void DoWork() { 290 void DoWork() {
339 fiber1->SetRewindPoint(std::function<void(void*)>{WorkControl4}, this); 291 fiber1->SetRewindPoint([this] { DoWork(); });
340 if (rewinded) { 292 if (rewinded) {
341 goal_reached = true; 293 goal_reached = true;
342 Fiber::YieldTo(fiber1, *thread_fiber); 294 Fiber::YieldTo(fiber1, *thread_fiber);
@@ -351,11 +303,6 @@ public:
351 bool rewinded; 303 bool rewinded;
352}; 304};
353 305
354static void WorkControl4(void* control) {
355 auto* test_control = static_cast<TestControl4*>(control);
356 test_control->DoWork();
357}
358
359TEST_CASE("Fibers::Rewind", "[common]") { 306TEST_CASE("Fibers::Rewind", "[common]") {
360 TestControl4 test_control{}; 307 TestControl4 test_control{};
361 test_control.Execute(); 308 test_control.Execute();