From 8d0e3c542258cc50081af93aa85e0e3cbf8900c3 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 5 Feb 2020 14:13:16 -0400 Subject: Tests: Add tests for fibers and refactor/fix Fiber class --- src/tests/CMakeLists.txt | 1 + src/tests/common/fibers.cpp | 214 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 src/tests/common/fibers.cpp (limited to 'src/tests') diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index c7038b217..47ef30aa9 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -1,6 +1,7 @@ add_executable(tests common/bit_field.cpp common/bit_utils.cpp + common/fibers.cpp common/multi_level_queue.cpp common/param_package.cpp common/ring_buffer.cpp diff --git a/src/tests/common/fibers.cpp b/src/tests/common/fibers.cpp new file mode 100644 index 000000000..ff840afa6 --- /dev/null +++ b/src/tests/common/fibers.cpp @@ -0,0 +1,214 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "common/common_types.h" +#include "common/fiber.h" +#include "common/spin_lock.h" + +namespace Common { + +class TestControl1 { +public: + TestControl1() = default; + + void DoWork(); + + void ExecuteThread(u32 id); + + std::unordered_map ids; + std::vector> thread_fibers; + std::vector> work_fibers; + std::vector items; + std::vector results; +}; + +static void WorkControl1(void* control) { + TestControl1* test_control = static_cast(control); + test_control->DoWork(); +} + +void TestControl1::DoWork() { + std::thread::id this_id = std::this_thread::get_id(); + u32 id = ids[this_id]; + u32 value = items[id]; + for (u32 i = 0; i < id; i++) { + value++; + } + results[id] = value; + Fiber::YieldTo(work_fibers[id], thread_fibers[id]); +} + +void TestControl1::ExecuteThread(u32 id) { + std::thread::id this_id = std::this_thread::get_id(); + ids[this_id] = id; + auto thread_fiber = Fiber::ThreadToFiber(); + thread_fibers[id] = thread_fiber; + work_fibers[id] = std::make_shared(std::function{WorkControl1}, this); + items[id] = rand() % 256; + Fiber::YieldTo(thread_fibers[id], work_fibers[id]); + thread_fibers[id]->Exit(); +} + +static void ThreadStart1(u32 id, TestControl1& test_control) { + test_control.ExecuteThread(id); +} + + +TEST_CASE("Fibers::Setup", "[common]") { + constexpr u32 num_threads = 7; + TestControl1 test_control{}; + test_control.thread_fibers.resize(num_threads, nullptr); + test_control.work_fibers.resize(num_threads, nullptr); + test_control.items.resize(num_threads, 0); + test_control.results.resize(num_threads, 0); + std::vector threads; + for (u32 i = 0; i < num_threads; i++) { + threads.emplace_back(ThreadStart1, i, std::ref(test_control)); + } + for (u32 i = 0; i < num_threads; i++) { + threads[i].join(); + } + for (u32 i = 0; i < num_threads; i++) { + REQUIRE(test_control.items[i] + i == test_control.results[i]); + } +} + +class TestControl2 { +public: + TestControl2() = default; + + void DoWork1() { + trap2 = false; + while (trap.load()); + for (u32 i = 0; i < 12000; i++) { + value1 += i; + } + Fiber::YieldTo(fiber1, fiber3); + std::thread::id this_id = std::this_thread::get_id(); + u32 id = ids[this_id]; + assert1 = id == 1; + value2 += 5000; + Fiber::YieldTo(fiber1, thread_fibers[id]); + } + + void DoWork2() { + while (trap2.load()); + value2 = 2000; + trap = false; + Fiber::YieldTo(fiber2, fiber1); + assert3 = false; + } + + void DoWork3() { + std::thread::id this_id = std::this_thread::get_id(); + u32 id = ids[this_id]; + assert2 = id == 0; + value1 += 1000; + Fiber::YieldTo(fiber3, thread_fibers[id]); + } + + void ExecuteThread(u32 id); + + void CallFiber1() { + std::thread::id this_id = std::this_thread::get_id(); + u32 id = ids[this_id]; + Fiber::YieldTo(thread_fibers[id], fiber1); + } + + void CallFiber2() { + std::thread::id this_id = std::this_thread::get_id(); + u32 id = ids[this_id]; + Fiber::YieldTo(thread_fibers[id], fiber2); + } + + void Exit(); + + bool assert1{}; + bool assert2{}; + bool assert3{true}; + u32 value1{}; + u32 value2{}; + std::atomic trap{true}; + std::atomic trap2{true}; + std::unordered_map ids; + std::vector> thread_fibers; + std::shared_ptr fiber1; + std::shared_ptr fiber2; + std::shared_ptr fiber3; +}; + +static void WorkControl2_1(void* control) { + TestControl2* test_control = static_cast(control); + test_control->DoWork1(); +} + +static void WorkControl2_2(void* control) { + TestControl2* test_control = static_cast(control); + test_control->DoWork2(); +} + +static void WorkControl2_3(void* control) { + TestControl2* test_control = static_cast(control); + test_control->DoWork3(); +} + +void TestControl2::ExecuteThread(u32 id) { + std::thread::id this_id = std::this_thread::get_id(); + ids[this_id] = id; + auto thread_fiber = Fiber::ThreadToFiber(); + thread_fibers[id] = thread_fiber; +} + +void TestControl2::Exit() { + std::thread::id this_id = std::this_thread::get_id(); + u32 id = ids[this_id]; + thread_fibers[id]->Exit(); +} + +static void ThreadStart2_1(u32 id, TestControl2& test_control) { + test_control.ExecuteThread(id); + test_control.CallFiber1(); + test_control.Exit(); +} + +static void ThreadStart2_2(u32 id, TestControl2& test_control) { + test_control.ExecuteThread(id); + test_control.CallFiber2(); + test_control.Exit(); +} + +TEST_CASE("Fibers::InterExchange", "[common]") { + TestControl2 test_control{}; + test_control.thread_fibers.resize(2, nullptr); + test_control.fiber1 = std::make_shared(std::function{WorkControl2_1}, &test_control); + test_control.fiber2 = std::make_shared(std::function{WorkControl2_2}, &test_control); + test_control.fiber3 = std::make_shared(std::function{WorkControl2_3}, &test_control); + std::thread thread1(ThreadStart2_1, 0, std::ref(test_control)); + std::thread thread2(ThreadStart2_2, 1, std::ref(test_control)); + thread1.join(); + thread2.join(); + REQUIRE(test_control.assert1); + REQUIRE(test_control.assert2); + REQUIRE(test_control.assert3); + REQUIRE(test_control.value2 == 7000); + u32 cal_value = 0; + for (u32 i = 0; i < 12000; i++) { + cal_value += i; + } + cal_value += 1000; + REQUIRE(test_control.value1 == cal_value); +} + + +} // namespace Common -- cgit v1.2.3 From be320a9e10fda32a984b12cdfe3aaf09cc67b39a Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 5 Feb 2020 15:48:20 -0400 Subject: Common: Polish Fiber class, add comments, asserts and more tests. --- src/tests/common/fibers.cpp | 95 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) (limited to 'src/tests') 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) { test_control.ExecuteThread(id); } - +/** This test checks for fiber setup configuration and validates that fibers are + * doing all the work required. + */ TEST_CASE("Fibers::Setup", "[common]") { constexpr u32 num_threads = 7; TestControl1 test_control{}; @@ -188,6 +190,10 @@ static void ThreadStart2_2(u32 id, TestControl2& test_control) { test_control.Exit(); } +/** This test checks for fiber thread exchange configuration and validates that fibers are + * that a fiber has been succesfully transfered from one thread to another and that the TLS + * region of the thread is kept while changing fibers. + */ TEST_CASE("Fibers::InterExchange", "[common]") { TestControl2 test_control{}; test_control.thread_fibers.resize(2, nullptr); @@ -210,5 +216,92 @@ TEST_CASE("Fibers::InterExchange", "[common]") { REQUIRE(test_control.value1 == cal_value); } +class TestControl3 { +public: + TestControl3() = default; + + void DoWork1() { + value1 += 1; + Fiber::YieldTo(fiber1, fiber2); + std::thread::id this_id = std::this_thread::get_id(); + u32 id = ids[this_id]; + value3 += 1; + Fiber::YieldTo(fiber1, thread_fibers[id]); + } + + void DoWork2() { + value2 += 1; + std::thread::id this_id = std::this_thread::get_id(); + u32 id = ids[this_id]; + Fiber::YieldTo(fiber2, thread_fibers[id]); + } + + void ExecuteThread(u32 id); + + void CallFiber1() { + std::thread::id this_id = std::this_thread::get_id(); + u32 id = ids[this_id]; + Fiber::YieldTo(thread_fibers[id], fiber1); + } + + void Exit(); + + u32 value1{}; + u32 value2{}; + u32 value3{}; + std::unordered_map ids; + std::vector> thread_fibers; + std::shared_ptr fiber1; + std::shared_ptr fiber2; +}; + +static void WorkControl3_1(void* control) { + TestControl3* test_control = static_cast(control); + test_control->DoWork1(); +} + +static void WorkControl3_2(void* control) { + TestControl3* test_control = static_cast(control); + test_control->DoWork2(); +} + +void TestControl3::ExecuteThread(u32 id) { + std::thread::id this_id = std::this_thread::get_id(); + ids[this_id] = id; + auto thread_fiber = Fiber::ThreadToFiber(); + thread_fibers[id] = thread_fiber; +} + +void TestControl3::Exit() { + std::thread::id this_id = std::this_thread::get_id(); + u32 id = ids[this_id]; + thread_fibers[id]->Exit(); +} + +static void ThreadStart3(u32 id, TestControl3& test_control) { + test_control.ExecuteThread(id); + test_control.CallFiber1(); + test_control.Exit(); +} + +/** This test checks for one two threads racing for starting the same fiber. + * It checks execution occured in an ordered manner and by no time there were + * two contexts at the same time. + */ +TEST_CASE("Fibers::StartRace", "[common]") { + TestControl3 test_control{}; + test_control.thread_fibers.resize(2, nullptr); + test_control.fiber1 = std::make_shared(std::function{WorkControl3_1}, &test_control); + test_control.fiber2 = std::make_shared(std::function{WorkControl3_2}, &test_control); + std::thread thread1(ThreadStart3, 0, std::ref(test_control)); + std::thread thread2(ThreadStart3, 1, std::ref(test_control)); + thread1.join(); + thread2.join(); + REQUIRE(test_control.value1 == 1); + REQUIRE(test_control.value2 == 1); + REQUIRE(test_control.value3 == 1); +} + + } // namespace Common -- cgit v1.2.3 From 0f8e5a146563d1f245f8f62cb931dc1e0b55de2f Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 8 Feb 2020 12:48:57 -0400 Subject: Tests: Add base tests to host timing --- src/tests/CMakeLists.txt | 1 + src/tests/core/host_timing.cpp | 150 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 src/tests/core/host_timing.cpp (limited to 'src/tests') diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 47ef30aa9..3f750b51c 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -8,6 +8,7 @@ add_executable(tests core/arm/arm_test_common.cpp core/arm/arm_test_common.h core/core_timing.cpp + core/host_timing.cpp tests.cpp ) diff --git a/src/tests/core/host_timing.cpp b/src/tests/core/host_timing.cpp new file mode 100644 index 000000000..ca9c8e50a --- /dev/null +++ b/src/tests/core/host_timing.cpp @@ -0,0 +1,150 @@ +// Copyright 2016 Dolphin Emulator Project / 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include + +#include +#include +#include +#include +#include + +#include "common/file_util.h" +#include "core/core.h" +#include "core/host_timing.h" + +// Numbers are chosen randomly to make sure the correct one is given. +static constexpr std::array CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}}; +static constexpr int MAX_SLICE_LENGTH = 10000; // Copied from CoreTiming internals +static constexpr std::array calls_order{{2,0,1,4,3}}; +static std::array delays{}; + +static std::bitset callbacks_ran_flags; +static u64 expected_callback = 0; +static s64 lateness = 0; + +template +void HostCallbackTemplate(u64 userdata, s64 nanoseconds_late) { + static_assert(IDX < CB_IDS.size(), "IDX out of range"); + callbacks_ran_flags.set(IDX); + REQUIRE(CB_IDS[IDX] == userdata); + REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]); + delays[IDX] = nanoseconds_late; + ++expected_callback; +} + +static u64 callbacks_done = 0; + +struct ScopeInit final { + ScopeInit() { + core_timing.Initialize(); + } + ~ScopeInit() { + core_timing.Shutdown(); + } + + Core::HostTiming::CoreTiming core_timing; +}; + +TEST_CASE("HostTiming[BasicOrder]", "[core]") { + ScopeInit guard; + auto& core_timing = guard.core_timing; + std::vector> events; + events.resize(5); + events[0] = + Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>); + events[1] = + Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>); + events[2] = + Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>); + events[3] = + Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>); + events[4] = + Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>); + + expected_callback = 0; + + core_timing.SyncPause(true); + + u64 one_micro = 1000U; + for (std::size_t i = 0; i < events.size(); i++) { + u64 order = calls_order[i]; + core_timing.ScheduleEvent(i*one_micro + 100U, events[order], CB_IDS[order]); + } + /// test pause + REQUIRE(callbacks_ran_flags.none()); + + core_timing.Pause(false); // No need to sync + + while (core_timing.HasPendingEvents()); + + REQUIRE(callbacks_ran_flags.all()); + + for (std::size_t i = 0; i < delays.size(); i++) { + const double delay = static_cast(delays[i]); + const double micro = delay / 1000.0f; + const double mili = micro / 1000.0f; + printf("HostTimer Pausing Delay[%zu]: %.3f %.6f\n", i, micro, mili); + } +} + +#pragma optimize("", off) +u64 TestTimerSpeed(Core::HostTiming::CoreTiming& core_timing) { + u64 start = core_timing.GetGlobalTimeNs().count(); + u64 placebo = 0; + for (std::size_t i = 0; i < 1000; i++) { + placebo += core_timing.GetGlobalTimeNs().count(); + } + u64 end = core_timing.GetGlobalTimeNs().count(); + return (end - start); +} +#pragma optimize("", on) + +TEST_CASE("HostTiming[BasicOrderNoPausing]", "[core]") { + ScopeInit guard; + auto& core_timing = guard.core_timing; + std::vector> events; + events.resize(5); + events[0] = + Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>); + events[1] = + Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>); + events[2] = + Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>); + events[3] = + Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>); + events[4] = + Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>); + + core_timing.SyncPause(true); + core_timing.SyncPause(false); + + expected_callback = 0; + + u64 start = core_timing.GetGlobalTimeNs().count(); + u64 one_micro = 1000U; + for (std::size_t i = 0; i < events.size(); i++) { + u64 order = calls_order[i]; + core_timing.ScheduleEvent(i*one_micro + 100U, events[order], CB_IDS[order]); + } + u64 end = core_timing.GetGlobalTimeNs().count(); + const double scheduling_time = static_cast(end - start); + const double timer_time = static_cast(TestTimerSpeed(core_timing)); + + while (core_timing.HasPendingEvents()); + + REQUIRE(callbacks_ran_flags.all()); + + for (std::size_t i = 0; i < delays.size(); i++) { + const double delay = static_cast(delays[i]); + const double micro = delay / 1000.0f; + const double mili = micro / 1000.0f; + printf("HostTimer No Pausing Delay[%zu]: %.3f %.6f\n", i, micro, mili); + } + + const double micro = scheduling_time / 1000.0f; + const double mili = micro / 1000.0f; + printf("HostTimer No Pausing Scheduling Time: %.3f %.6f\n", micro, mili); + printf("HostTimer No Pausing Timer Time: %.3f %.6f\n", timer_time / 1000.f, timer_time / 1000000.f); +} -- cgit v1.2.3 From 234b5ff6a999d7d69cdcdf214e0c3984cdab11cf Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 9 Feb 2020 16:53:22 -0400 Subject: Common: Implement WallClock Interface and implement a native clock for x64 --- src/tests/core/host_timing.cpp | 45 ++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 26 deletions(-) (limited to 'src/tests') diff --git a/src/tests/core/host_timing.cpp b/src/tests/core/host_timing.cpp index ca9c8e50a..3d0532d02 100644 --- a/src/tests/core/host_timing.cpp +++ b/src/tests/core/host_timing.cpp @@ -17,7 +17,7 @@ // Numbers are chosen randomly to make sure the correct one is given. static constexpr std::array CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}}; static constexpr int MAX_SLICE_LENGTH = 10000; // Copied from CoreTiming internals -static constexpr std::array calls_order{{2,0,1,4,3}}; +static constexpr std::array calls_order{{2, 0, 1, 4, 3}}; static std::array delays{}; static std::bitset callbacks_ran_flags; @@ -52,16 +52,11 @@ TEST_CASE("HostTiming[BasicOrder]", "[core]") { auto& core_timing = guard.core_timing; std::vector> events; events.resize(5); - events[0] = - Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>); - events[1] = - Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>); - events[2] = - Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>); - events[3] = - Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>); - events[4] = - Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>); + events[0] = Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>); + events[1] = Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>); + events[2] = Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>); + events[3] = Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>); + events[4] = Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>); expected_callback = 0; @@ -70,14 +65,15 @@ TEST_CASE("HostTiming[BasicOrder]", "[core]") { u64 one_micro = 1000U; for (std::size_t i = 0; i < events.size(); i++) { u64 order = calls_order[i]; - core_timing.ScheduleEvent(i*one_micro + 100U, events[order], CB_IDS[order]); + core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]); } /// test pause REQUIRE(callbacks_ran_flags.none()); core_timing.Pause(false); // No need to sync - while (core_timing.HasPendingEvents()); + while (core_timing.HasPendingEvents()) + ; REQUIRE(callbacks_ran_flags.all()); @@ -106,16 +102,11 @@ TEST_CASE("HostTiming[BasicOrderNoPausing]", "[core]") { auto& core_timing = guard.core_timing; std::vector> events; events.resize(5); - events[0] = - Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>); - events[1] = - Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>); - events[2] = - Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>); - events[3] = - Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>); - events[4] = - Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>); + events[0] = Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>); + events[1] = Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>); + events[2] = Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>); + events[3] = Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>); + events[4] = Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>); core_timing.SyncPause(true); core_timing.SyncPause(false); @@ -126,13 +117,14 @@ TEST_CASE("HostTiming[BasicOrderNoPausing]", "[core]") { u64 one_micro = 1000U; for (std::size_t i = 0; i < events.size(); i++) { u64 order = calls_order[i]; - core_timing.ScheduleEvent(i*one_micro + 100U, events[order], CB_IDS[order]); + core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]); } u64 end = core_timing.GetGlobalTimeNs().count(); const double scheduling_time = static_cast(end - start); const double timer_time = static_cast(TestTimerSpeed(core_timing)); - while (core_timing.HasPendingEvents()); + while (core_timing.HasPendingEvents()) + ; REQUIRE(callbacks_ran_flags.all()); @@ -146,5 +138,6 @@ TEST_CASE("HostTiming[BasicOrderNoPausing]", "[core]") { const double micro = scheduling_time / 1000.0f; const double mili = micro / 1000.0f; printf("HostTimer No Pausing Scheduling Time: %.3f %.6f\n", micro, mili); - printf("HostTimer No Pausing Timer Time: %.3f %.6f\n", timer_time / 1000.f, timer_time / 1000000.f); + printf("HostTimer No Pausing Timer Time: %.3f %.6f\n", timer_time / 1000.f, + timer_time / 1000000.f); } -- cgit v1.2.3 From 1bd706344e2381e11245b2f0bdc291429e46c634 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 10 Feb 2020 13:33:13 -0400 Subject: Common/Tests: Clang Format. --- src/tests/common/fibers.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'src/tests') diff --git a/src/tests/common/fibers.cpp b/src/tests/common/fibers.cpp index 358393a19..d63194dd4 100644 --- a/src/tests/common/fibers.cpp +++ b/src/tests/common/fibers.cpp @@ -92,7 +92,8 @@ public: void DoWork1() { trap2 = false; - while (trap.load()); + while (trap.load()) + ; for (u32 i = 0; i < 12000; i++) { value1 += i; } @@ -105,7 +106,8 @@ public: } void DoWork2() { - while (trap2.load()); + while (trap2.load()) + ; value2 = 2000; trap = false; Fiber::YieldTo(fiber2, fiber1); @@ -197,9 +199,12 @@ static void ThreadStart2_2(u32 id, TestControl2& test_control) { TEST_CASE("Fibers::InterExchange", "[common]") { TestControl2 test_control{}; test_control.thread_fibers.resize(2, nullptr); - test_control.fiber1 = std::make_shared(std::function{WorkControl2_1}, &test_control); - test_control.fiber2 = std::make_shared(std::function{WorkControl2_2}, &test_control); - test_control.fiber3 = std::make_shared(std::function{WorkControl2_3}, &test_control); + test_control.fiber1 = + std::make_shared(std::function{WorkControl2_1}, &test_control); + test_control.fiber2 = + std::make_shared(std::function{WorkControl2_2}, &test_control); + test_control.fiber3 = + std::make_shared(std::function{WorkControl2_3}, &test_control); std::thread thread1(ThreadStart2_1, 0, std::ref(test_control)); std::thread thread2(ThreadStart2_2, 1, std::ref(test_control)); thread1.join(); @@ -291,8 +296,10 @@ static void ThreadStart3(u32 id, TestControl3& test_control) { TEST_CASE("Fibers::StartRace", "[common]") { TestControl3 test_control{}; test_control.thread_fibers.resize(2, nullptr); - test_control.fiber1 = std::make_shared(std::function{WorkControl3_1}, &test_control); - test_control.fiber2 = std::make_shared(std::function{WorkControl3_2}, &test_control); + test_control.fiber1 = + std::make_shared(std::function{WorkControl3_1}, &test_control); + test_control.fiber2 = + std::make_shared(std::function{WorkControl3_2}, &test_control); std::thread thread1(ThreadStart3, 0, std::ref(test_control)); std::thread thread2(ThreadStart3, 1, std::ref(test_control)); thread1.join(); @@ -302,6 +309,4 @@ TEST_CASE("Fibers::StartRace", "[common]") { REQUIRE(test_control.value3 == 1); } - - } // namespace Common -- cgit v1.2.3 From 1f7dd36499786d373b143a4437d4c32e077a32aa Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 10 Feb 2020 14:45:08 -0400 Subject: Common/Tests: Address Feedback --- src/tests/common/fibers.cpp | 20 ++++++++++---------- src/tests/core/host_timing.cpp | 28 ++++++++++++++-------------- 2 files changed, 24 insertions(+), 24 deletions(-) (limited to 'src/tests') diff --git a/src/tests/common/fibers.cpp b/src/tests/common/fibers.cpp index d63194dd4..0d3d5153d 100644 --- a/src/tests/common/fibers.cpp +++ b/src/tests/common/fibers.cpp @@ -34,7 +34,7 @@ public: }; static void WorkControl1(void* control) { - TestControl1* test_control = static_cast(control); + auto* test_control = static_cast(control); test_control->DoWork(); } @@ -70,8 +70,8 @@ static void ThreadStart1(u32 id, TestControl1& test_control) { TEST_CASE("Fibers::Setup", "[common]") { constexpr u32 num_threads = 7; TestControl1 test_control{}; - test_control.thread_fibers.resize(num_threads, nullptr); - test_control.work_fibers.resize(num_threads, nullptr); + test_control.thread_fibers.resize(num_threads); + test_control.work_fibers.resize(num_threads); test_control.items.resize(num_threads, 0); test_control.results.resize(num_threads, 0); std::vector threads; @@ -153,17 +153,17 @@ public: }; static void WorkControl2_1(void* control) { - TestControl2* test_control = static_cast(control); + auto* test_control = static_cast(control); test_control->DoWork1(); } static void WorkControl2_2(void* control) { - TestControl2* test_control = static_cast(control); + auto* test_control = static_cast(control); test_control->DoWork2(); } static void WorkControl2_3(void* control) { - TestControl2* test_control = static_cast(control); + auto* test_control = static_cast(control); test_control->DoWork3(); } @@ -198,7 +198,7 @@ static void ThreadStart2_2(u32 id, TestControl2& test_control) { */ TEST_CASE("Fibers::InterExchange", "[common]") { TestControl2 test_control{}; - test_control.thread_fibers.resize(2, nullptr); + test_control.thread_fibers.resize(2); test_control.fiber1 = std::make_shared(std::function{WorkControl2_1}, &test_control); test_control.fiber2 = @@ -261,12 +261,12 @@ public: }; static void WorkControl3_1(void* control) { - TestControl3* test_control = static_cast(control); + auto* test_control = static_cast(control); test_control->DoWork1(); } static void WorkControl3_2(void* control) { - TestControl3* test_control = static_cast(control); + auto* test_control = static_cast(control); test_control->DoWork2(); } @@ -295,7 +295,7 @@ static void ThreadStart3(u32 id, TestControl3& test_control) { */ TEST_CASE("Fibers::StartRace", "[common]") { TestControl3 test_control{}; - test_control.thread_fibers.resize(2, nullptr); + test_control.thread_fibers.resize(2); test_control.fiber1 = std::make_shared(std::function{WorkControl3_1}, &test_control); test_control.fiber2 = diff --git a/src/tests/core/host_timing.cpp b/src/tests/core/host_timing.cpp index 3d0532d02..ed060be55 100644 --- a/src/tests/core/host_timing.cpp +++ b/src/tests/core/host_timing.cpp @@ -50,13 +50,13 @@ struct ScopeInit final { TEST_CASE("HostTiming[BasicOrder]", "[core]") { ScopeInit guard; auto& core_timing = guard.core_timing; - std::vector> events; - events.resize(5); - events[0] = Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>); - events[1] = Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>); - events[2] = Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>); - events[3] = Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>); - events[4] = Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>); + std::vector> events{ + Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>), + Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>), + Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>), + Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>), + Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>), + }; expected_callback = 0; @@ -100,13 +100,13 @@ u64 TestTimerSpeed(Core::HostTiming::CoreTiming& core_timing) { TEST_CASE("HostTiming[BasicOrderNoPausing]", "[core]") { ScopeInit guard; auto& core_timing = guard.core_timing; - std::vector> events; - events.resize(5); - events[0] = Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>); - events[1] = Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>); - events[2] = Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>); - events[3] = Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>); - events[4] = Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>); + std::vector> events{ + Core::HostTiming::CreateEvent("callbackA", HostCallbackTemplate<0>), + Core::HostTiming::CreateEvent("callbackB", HostCallbackTemplate<1>), + Core::HostTiming::CreateEvent("callbackC", HostCallbackTemplate<2>), + Core::HostTiming::CreateEvent("callbackD", HostCallbackTemplate<3>), + Core::HostTiming::CreateEvent("callbackE", HostCallbackTemplate<4>), + }; core_timing.SyncPause(true); core_timing.SyncPause(false); -- cgit v1.2.3 From 137d862d9b275209b3d62a413396a15e9e14b4b4 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 27 Feb 2020 16:32:47 -0400 Subject: Common/Fiber: Implement Rewinding. --- src/tests/common/fibers.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'src/tests') diff --git a/src/tests/common/fibers.cpp b/src/tests/common/fibers.cpp index 0d3d5153d..12536b6d8 100644 --- a/src/tests/common/fibers.cpp +++ b/src/tests/common/fibers.cpp @@ -309,4 +309,50 @@ TEST_CASE("Fibers::StartRace", "[common]") { REQUIRE(test_control.value3 == 1); } +class TestControl4; + +static void WorkControl4(void* control); + +class TestControl4 { +public: + TestControl4() { + fiber1 = std::make_shared(std::function{WorkControl4}, this); + goal_reached = false; + rewinded = false; + } + + void Execute() { + thread_fiber = Fiber::ThreadToFiber(); + Fiber::YieldTo(thread_fiber, fiber1); + thread_fiber->Exit(); + } + + void DoWork() { + fiber1->SetRewindPoint(std::function{WorkControl4}, this); + if (rewinded) { + goal_reached = true; + Fiber::YieldTo(fiber1, thread_fiber); + } + rewinded = true; + fiber1->Rewind(); + } + + std::shared_ptr fiber1; + std::shared_ptr thread_fiber; + bool goal_reached; + bool rewinded; +}; + +static void WorkControl4(void* control) { + auto* test_control = static_cast(control); + test_control->DoWork(); +} + +TEST_CASE("Fibers::Rewind", "[common]") { + TestControl4 test_control{}; + test_control.Execute(); + REQUIRE(test_control.goal_reached); + REQUIRE(test_control.rewinded); +} + } // namespace Common -- cgit v1.2.3 From 45d29436b32bbee1bdf1344e3dc3db365dc42937 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 14 May 2020 14:10:49 -0400 Subject: Tests/HostTiming: Correct GCC Compile error. --- src/tests/core/host_timing.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'src/tests') diff --git a/src/tests/core/host_timing.cpp b/src/tests/core/host_timing.cpp index ed060be55..556254098 100644 --- a/src/tests/core/host_timing.cpp +++ b/src/tests/core/host_timing.cpp @@ -22,7 +22,6 @@ static std::array delays{}; static std::bitset callbacks_ran_flags; static u64 expected_callback = 0; -static s64 lateness = 0; template void HostCallbackTemplate(u64 userdata, s64 nanoseconds_late) { @@ -34,8 +33,6 @@ void HostCallbackTemplate(u64 userdata, s64 nanoseconds_late) { ++expected_callback; } -static u64 callbacks_done = 0; - struct ScopeInit final { ScopeInit() { core_timing.Initialize(); @@ -47,6 +44,20 @@ struct ScopeInit final { Core::HostTiming::CoreTiming core_timing; }; +#pragma optimize("", off) + +static u64 TestTimerSpeed(Core::HostTiming::CoreTiming& core_timing) { + u64 start = core_timing.GetGlobalTimeNs().count(); + u64 placebo = 0; + for (std::size_t i = 0; i < 1000; i++) { + placebo += core_timing.GetGlobalTimeNs().count(); + } + u64 end = core_timing.GetGlobalTimeNs().count(); + return (end - start); +} + +#pragma optimize("", on) + TEST_CASE("HostTiming[BasicOrder]", "[core]") { ScopeInit guard; auto& core_timing = guard.core_timing; @@ -85,18 +96,6 @@ TEST_CASE("HostTiming[BasicOrder]", "[core]") { } } -#pragma optimize("", off) -u64 TestTimerSpeed(Core::HostTiming::CoreTiming& core_timing) { - u64 start = core_timing.GetGlobalTimeNs().count(); - u64 placebo = 0; - for (std::size_t i = 0; i < 1000; i++) { - placebo += core_timing.GetGlobalTimeNs().count(); - } - u64 end = core_timing.GetGlobalTimeNs().count(); - return (end - start); -} -#pragma optimize("", on) - TEST_CASE("HostTiming[BasicOrderNoPausing]", "[core]") { ScopeInit guard; auto& core_timing = guard.core_timing; -- cgit v1.2.3