summaryrefslogtreecommitdiff
path: root/src/tests/common/fibers.cpp
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-02-05 15:48:20 -0400
committerGravatar Fernando Sahmkow2020-06-18 16:29:15 -0400
commitbe320a9e10fda32a984b12cdfe3aaf09cc67b39a (patch)
treef2bb28be6adc2a416b59393bb8f438636e9c79c1 /src/tests/common/fibers.cpp
parentTests: Add tests for fibers and refactor/fix Fiber class (diff)
downloadyuzu-be320a9e10fda32a984b12cdfe3aaf09cc67b39a.tar.gz
yuzu-be320a9e10fda32a984b12cdfe3aaf09cc67b39a.tar.xz
yuzu-be320a9e10fda32a984b12cdfe3aaf09cc67b39a.zip
Common: Polish Fiber class, add comments, asserts and more tests.
Diffstat (limited to 'src/tests/common/fibers.cpp')
-rw-r--r--src/tests/common/fibers.cpp95
1 files changed, 94 insertions, 1 deletions
diff --git a/src/tests/common/fibers.cpp b/src/tests/common/fibers.cpp
index ff840afa6..358393a19 100644
--- a/src/tests/common/fibers.cpp
+++ b/src/tests/common/fibers.cpp
@@ -64,7 +64,9 @@ static void ThreadStart1(u32 id, TestControl1& test_control) {
64 test_control.ExecuteThread(id); 64 test_control.ExecuteThread(id);
65} 65}
66 66
67 67/** This test checks for fiber setup configuration and validates that fibers are
68 * doing all the work required.
69 */
68TEST_CASE("Fibers::Setup", "[common]") { 70TEST_CASE("Fibers::Setup", "[common]") {
69 constexpr u32 num_threads = 7; 71 constexpr u32 num_threads = 7;
70 TestControl1 test_control{}; 72 TestControl1 test_control{};
@@ -188,6 +190,10 @@ static void ThreadStart2_2(u32 id, TestControl2& test_control) {
188 test_control.Exit(); 190 test_control.Exit();
189} 191}
190 192
193/** This test checks for fiber thread exchange configuration and validates that fibers are
194 * that a fiber has been succesfully transfered from one thread to another and that the TLS
195 * region of the thread is kept while changing fibers.
196 */
191TEST_CASE("Fibers::InterExchange", "[common]") { 197TEST_CASE("Fibers::InterExchange", "[common]") {
192 TestControl2 test_control{}; 198 TestControl2 test_control{};
193 test_control.thread_fibers.resize(2, nullptr); 199 test_control.thread_fibers.resize(2, nullptr);
@@ -210,5 +216,92 @@ TEST_CASE("Fibers::InterExchange", "[common]") {
210 REQUIRE(test_control.value1 == cal_value); 216 REQUIRE(test_control.value1 == cal_value);
211} 217}
212 218
219class TestControl3 {
220public:
221 TestControl3() = default;
222
223 void DoWork1() {
224 value1 += 1;
225 Fiber::YieldTo(fiber1, fiber2);
226 std::thread::id this_id = std::this_thread::get_id();
227 u32 id = ids[this_id];
228 value3 += 1;
229 Fiber::YieldTo(fiber1, thread_fibers[id]);
230 }
231
232 void DoWork2() {
233 value2 += 1;
234 std::thread::id this_id = std::this_thread::get_id();
235 u32 id = ids[this_id];
236 Fiber::YieldTo(fiber2, thread_fibers[id]);
237 }
238
239 void ExecuteThread(u32 id);
240
241 void CallFiber1() {
242 std::thread::id this_id = std::this_thread::get_id();
243 u32 id = ids[this_id];
244 Fiber::YieldTo(thread_fibers[id], fiber1);
245 }
246
247 void Exit();
248
249 u32 value1{};
250 u32 value2{};
251 u32 value3{};
252 std::unordered_map<std::thread::id, u32> ids;
253 std::vector<std::shared_ptr<Common::Fiber>> thread_fibers;
254 std::shared_ptr<Common::Fiber> fiber1;
255 std::shared_ptr<Common::Fiber> fiber2;
256};
257
258static void WorkControl3_1(void* control) {
259 TestControl3* test_control = static_cast<TestControl3*>(control);
260 test_control->DoWork1();
261}
262
263static void WorkControl3_2(void* control) {
264 TestControl3* test_control = static_cast<TestControl3*>(control);
265 test_control->DoWork2();
266}
267
268void TestControl3::ExecuteThread(u32 id) {
269 std::thread::id this_id = std::this_thread::get_id();
270 ids[this_id] = id;
271 auto thread_fiber = Fiber::ThreadToFiber();
272 thread_fibers[id] = thread_fiber;
273}
274
275void TestControl3::Exit() {
276 std::thread::id this_id = std::this_thread::get_id();
277 u32 id = ids[this_id];
278 thread_fibers[id]->Exit();
279}
280
281static void ThreadStart3(u32 id, TestControl3& test_control) {
282 test_control.ExecuteThread(id);
283 test_control.CallFiber1();
284 test_control.Exit();
285}
286
287/** This test checks for one two threads racing for starting the same fiber.
288 * It checks execution occured in an ordered manner and by no time there were
289 * two contexts at the same time.
290 */
291TEST_CASE("Fibers::StartRace", "[common]") {
292 TestControl3 test_control{};
293 test_control.thread_fibers.resize(2, nullptr);
294 test_control.fiber1 = std::make_shared<Fiber>(std::function<void(void*)>{WorkControl3_1}, &test_control);
295 test_control.fiber2 = std::make_shared<Fiber>(std::function<void(void*)>{WorkControl3_2}, &test_control);
296 std::thread thread1(ThreadStart3, 0, std::ref(test_control));
297 std::thread thread2(ThreadStart3, 1, std::ref(test_control));
298 thread1.join();
299 thread2.join();
300 REQUIRE(test_control.value1 == 1);
301 REQUIRE(test_control.value2 == 1);
302 REQUIRE(test_control.value3 == 1);
303}
304
305
213 306
214} // namespace Common 307} // namespace Common