diff options
| author | 2020-04-01 09:19:10 -0400 | |
|---|---|---|
| committer | 2020-06-18 16:29:27 -0400 | |
| commit | b6655aa2e492e326e319b09e832c1612bf27acf4 (patch) | |
| tree | 831c7ca6bb0b85562ffd322d6e47f6545a087cb1 /src | |
| parent | Common/uint128: Correct MSVC Compilation in old versions. (diff) | |
| download | yuzu-b6655aa2e492e326e319b09e832c1612bf27acf4.tar.gz yuzu-b6655aa2e492e326e319b09e832c1612bf27acf4.tar.xz yuzu-b6655aa2e492e326e319b09e832c1612bf27acf4.zip | |
Common/Fiber: Implement Rewind on Boost Context.
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/fiber.cpp | 39 | ||||
| -rw-r--r-- | src/common/fiber.h | 2 |
2 files changed, 39 insertions, 2 deletions
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp index f61479e13..6ea314d75 100644 --- a/src/common/fiber.cpp +++ b/src/common/fiber.cpp | |||
| @@ -113,7 +113,11 @@ std::shared_ptr<Fiber> Fiber::ThreadToFiber() { | |||
| 113 | 113 | ||
| 114 | struct Fiber::FiberImpl { | 114 | struct Fiber::FiberImpl { |
| 115 | alignas(64) std::array<u8, default_stack_size> stack; | 115 | alignas(64) std::array<u8, default_stack_size> stack; |
| 116 | u8* stack_limit; | ||
| 117 | alignas(64) std::array<u8, default_stack_size> rewind_stack; | ||
| 118 | u8* rewind_stack_limit; | ||
| 116 | boost::context::detail::fcontext_t context; | 119 | boost::context::detail::fcontext_t context; |
| 120 | boost::context::detail::fcontext_t rewind_context; | ||
| 117 | }; | 121 | }; |
| 118 | 122 | ||
| 119 | void Fiber::start(boost::context::detail::transfer_t& transfer) { | 123 | void Fiber::start(boost::context::detail::transfer_t& transfer) { |
| @@ -125,21 +129,43 @@ void Fiber::start(boost::context::detail::transfer_t& transfer) { | |||
| 125 | UNREACHABLE(); | 129 | UNREACHABLE(); |
| 126 | } | 130 | } |
| 127 | 131 | ||
| 132 | void Fiber::onRewind(boost::context::detail::transfer_t& [[maybe_unused]] transfer) { | ||
| 133 | ASSERT(impl->context != nullptr); | ||
| 134 | impl->context = impl->rewind_context; | ||
| 135 | impl->rewind_context = nullptr; | ||
| 136 | u8* tmp = impl->stack_limit; | ||
| 137 | impl->stack_limit = impl->rewind_stack_limit; | ||
| 138 | impl->rewind_stack_limit = tmp; | ||
| 139 | rewind_point(rewind_parameter); | ||
| 140 | UNREACHABLE(); | ||
| 141 | } | ||
| 142 | |||
| 128 | void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) { | 143 | void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) { |
| 129 | auto fiber = static_cast<Fiber*>(transfer.data); | 144 | auto fiber = static_cast<Fiber*>(transfer.data); |
| 130 | fiber->start(transfer); | 145 | fiber->start(transfer); |
| 131 | } | 146 | } |
| 132 | 147 | ||
| 148 | void Fiber::RewindStartFunc(boost::context::detail::transfer_t transfer) { | ||
| 149 | auto fiber = static_cast<Fiber*>(transfer.data); | ||
| 150 | fiber->onRewind(transfer); | ||
| 151 | } | ||
| 152 | |||
| 133 | Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter) | 153 | Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter) |
| 134 | : guard{}, entry_point{std::move(entry_point_func)}, start_parameter{start_parameter}, | 154 | : guard{}, entry_point{std::move(entry_point_func)}, start_parameter{start_parameter}, |
| 135 | previous_fiber{} { | 155 | previous_fiber{} { |
| 136 | impl = std::make_unique<FiberImpl>(); | 156 | impl = std::make_unique<FiberImpl>(); |
| 137 | u8* stack_limit = impl->stack.data(); | 157 | impl->stack_limit = impl->stack.data(); |
| 138 | u8* stack_base = stack_limit + default_stack_size; | 158 | impl->rewind_stack_limit = impl->rewind_stack.data(); |
| 159 | u8* stack_base = impl->stack_limit + default_stack_size; | ||
| 139 | impl->context = | 160 | impl->context = |
| 140 | boost::context::detail::make_fcontext(stack_base, impl->stack.size(), FiberStartFunc); | 161 | boost::context::detail::make_fcontext(stack_base, impl->stack.size(), FiberStartFunc); |
| 141 | } | 162 | } |
| 142 | 163 | ||
| 164 | void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter) { | ||
| 165 | rewind_point = std::move(rewind_func); | ||
| 166 | rewind_parameter = start_parameter; | ||
| 167 | } | ||
| 168 | |||
| 143 | Fiber::Fiber() { | 169 | Fiber::Fiber() { |
| 144 | impl = std::make_unique<FiberImpl>(); | 170 | impl = std::make_unique<FiberImpl>(); |
| 145 | } | 171 | } |
| @@ -161,6 +187,15 @@ void Fiber::Exit() { | |||
| 161 | guard.unlock(); | 187 | guard.unlock(); |
| 162 | } | 188 | } |
| 163 | 189 | ||
| 190 | void Fiber::Rewind() { | ||
| 191 | ASSERT(rewind_point); | ||
| 192 | ASSERT(impl->rewind_context == nullptr); | ||
| 193 | u8* stack_base = impl->rewind_stack_limit + default_stack_size; | ||
| 194 | impl->rewind_context = | ||
| 195 | boost::context::detail::make_fcontext(stack_base, impl->stack.size(), RewindStartFunc); | ||
| 196 | boost::context::detail::jump_fcontext(impl->rewind_context, this); | ||
| 197 | } | ||
| 198 | |||
| 164 | void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { | 199 | void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { |
| 165 | ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); | 200 | ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); |
| 166 | ASSERT_MSG(to != nullptr, "Next fiber is null!"); | 201 | ASSERT_MSG(to != nullptr, "Next fiber is null!"); |
diff --git a/src/common/fiber.h b/src/common/fiber.h index 3bbd506b5..cab7bc4b5 100644 --- a/src/common/fiber.h +++ b/src/common/fiber.h | |||
| @@ -70,8 +70,10 @@ private: | |||
| 70 | static void FiberStartFunc(void* fiber_parameter); | 70 | static void FiberStartFunc(void* fiber_parameter); |
| 71 | static void RewindStartFunc(void* fiber_parameter); | 71 | static void RewindStartFunc(void* fiber_parameter); |
| 72 | #else | 72 | #else |
| 73 | void onRewind(boost::context::detail::transfer_t& transfer); | ||
| 73 | void start(boost::context::detail::transfer_t& transfer); | 74 | void start(boost::context::detail::transfer_t& transfer); |
| 74 | static void FiberStartFunc(boost::context::detail::transfer_t transfer); | 75 | static void FiberStartFunc(boost::context::detail::transfer_t transfer); |
| 76 | static void RewindStartFunc(boost::context::detail::transfer_t transfer); | ||
| 75 | #endif | 77 | #endif |
| 76 | 78 | ||
| 77 | struct FiberImpl; | 79 | struct FiberImpl; |