summaryrefslogtreecommitdiff
path: root/src/common/fiber.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2020-11-13 15:17:47 -0800
committerGravatar bunnei2020-11-29 01:31:51 -0800
commitc042a89113617f75e81163f103ef82d6d714cd87 (patch)
tree865b1aa1c9d2c153d89209efc738f00589e97052 /src/common/fiber.cpp
parenthle: kernel: multicore: Replace n-JITs impl. with 4 JITs. (diff)
downloadyuzu-c042a89113617f75e81163f103ef82d6d714cd87.tar.gz
yuzu-c042a89113617f75e81163f103ef82d6d714cd87.tar.xz
yuzu-c042a89113617f75e81163f103ef82d6d714cd87.zip
common: fiber: Use boost::context instead of native fibers on Windows.
Diffstat (limited to 'src/common/fiber.cpp')
-rw-r--r--src/common/fiber.cpp114
1 files changed, 8 insertions, 106 deletions
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp
index 3e3029cd1..3978c8624 100644
--- a/src/common/fiber.cpp
+++ b/src/common/fiber.cpp
@@ -6,17 +6,16 @@
6#include "common/fiber.h" 6#include "common/fiber.h"
7#include "common/spin_lock.h" 7#include "common/spin_lock.h"
8 8
9#if defined(_WIN32) || defined(WIN32)
10#include <windows.h>
11#else
12#include <boost/context/detail/fcontext.hpp> 9#include <boost/context/detail/fcontext.hpp>
13#endif
14 10
15namespace Common { 11namespace Common {
16 12
17constexpr std::size_t default_stack_size = 256 * 1024; // 256kb 13constexpr std::size_t default_stack_size = 256 * 1024;
18 14
19struct Fiber::FiberImpl { 15struct Fiber::FiberImpl {
16 alignas(64) std::array<u8, default_stack_size> stack;
17 alignas(64) std::array<u8, default_stack_size> rewind_stack;
18
20 SpinLock guard{}; 19 SpinLock guard{};
21 std::function<void(void*)> entry_point; 20 std::function<void(void*)> entry_point;
22 std::function<void(void*)> rewind_point; 21 std::function<void(void*)> rewind_point;
@@ -26,17 +25,10 @@ struct Fiber::FiberImpl {
26 bool is_thread_fiber{}; 25 bool is_thread_fiber{};
27 bool released{}; 26 bool released{};
28 27
29#if defined(_WIN32) || defined(WIN32) 28 u8* stack_limit{};
30 LPVOID handle = nullptr; 29 u8* rewind_stack_limit{};
31 LPVOID rewind_handle = nullptr; 30 boost::context::detail::fcontext_t context{};
32#else 31 boost::context::detail::fcontext_t rewind_context{};
33 alignas(64) std::array<u8, default_stack_size> stack;
34 alignas(64) std::array<u8, default_stack_size> rewind_stack;
35 u8* stack_limit;
36 u8* rewind_stack_limit;
37 boost::context::detail::fcontext_t context;
38 boost::context::detail::fcontext_t rewind_context;
39#endif
40}; 32};
41 33
42void Fiber::SetStartParameter(void* new_parameter) { 34void Fiber::SetStartParameter(void* new_parameter) {
@@ -48,95 +40,6 @@ void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewin
48 impl->rewind_parameter = rewind_param; 40 impl->rewind_parameter = rewind_param;
49} 41}
50 42
51#if defined(_WIN32) || defined(WIN32)
52
53void Fiber::Start() {
54 ASSERT(impl->previous_fiber != nullptr);
55 impl->previous_fiber->impl->guard.unlock();
56 impl->previous_fiber.reset();
57 impl->entry_point(impl->start_parameter);
58 UNREACHABLE();
59}
60
61void Fiber::OnRewind() {
62 ASSERT(impl->handle != nullptr);
63 DeleteFiber(impl->handle);
64 impl->handle = impl->rewind_handle;
65 impl->rewind_handle = nullptr;
66 impl->rewind_point(impl->rewind_parameter);
67 UNREACHABLE();
68}
69
70void Fiber::FiberStartFunc(void* fiber_parameter) {
71 auto* fiber = static_cast<Fiber*>(fiber_parameter);
72 fiber->Start();
73}
74
75void Fiber::RewindStartFunc(void* fiber_parameter) {
76 auto* fiber = static_cast<Fiber*>(fiber_parameter);
77 fiber->OnRewind();
78}
79
80Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter)
81 : impl{std::make_unique<FiberImpl>()} {
82 impl->entry_point = std::move(entry_point_func);
83 impl->start_parameter = start_parameter;
84 impl->handle = CreateFiber(default_stack_size, &FiberStartFunc, this);
85}
86
87Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {}
88
89Fiber::~Fiber() {
90 if (impl->released) {
91 return;
92 }
93 // Make sure the Fiber is not being used
94 const bool locked = impl->guard.try_lock();
95 ASSERT_MSG(locked, "Destroying a fiber that's still running");
96 if (locked) {
97 impl->guard.unlock();
98 }
99 DeleteFiber(impl->handle);
100}
101
102void Fiber::Exit() {
103 ASSERT_MSG(impl->is_thread_fiber, "Exitting non main thread fiber");
104 if (!impl->is_thread_fiber) {
105 return;
106 }
107 ConvertFiberToThread();
108 impl->guard.unlock();
109 impl->released = true;
110}
111
112void Fiber::Rewind() {
113 ASSERT(impl->rewind_point);
114 ASSERT(impl->rewind_handle == nullptr);
115 impl->rewind_handle = CreateFiber(default_stack_size, &RewindStartFunc, this);
116 SwitchToFiber(impl->rewind_handle);
117}
118
119void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) {
120 ASSERT_MSG(from != nullptr, "Yielding fiber is null!");
121 ASSERT_MSG(to != nullptr, "Next fiber is null!");
122 to->impl->guard.lock();
123 to->impl->previous_fiber = from;
124 SwitchToFiber(to->impl->handle);
125 ASSERT(from->impl->previous_fiber != nullptr);
126 from->impl->previous_fiber->impl->guard.unlock();
127 from->impl->previous_fiber.reset();
128}
129
130std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
131 std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()};
132 fiber->impl->guard.lock();
133 fiber->impl->handle = ConvertThreadToFiber(nullptr);
134 fiber->impl->is_thread_fiber = true;
135 return fiber;
136}
137
138#else
139
140void Fiber::Start(boost::context::detail::transfer_t& transfer) { 43void Fiber::Start(boost::context::detail::transfer_t& transfer) {
141 ASSERT(impl->previous_fiber != nullptr); 44 ASSERT(impl->previous_fiber != nullptr);
142 impl->previous_fiber->impl->context = transfer.fctx; 45 impl->previous_fiber->impl->context = transfer.fctx;
@@ -229,5 +132,4 @@ std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
229 return fiber; 132 return fiber;
230} 133}
231 134
232#endif
233} // namespace Common 135} // namespace Common