common: fiber: Use boost::context instead of native fibers on Windows.

merge-requests/60/head
bunnei 2020-11-13 15:17:47 +07:00
parent 7b642c7781
commit c042a89113
3 changed files with 9 additions and 116 deletions

@ -6,17 +6,16 @@
#include "common/fiber.h" #include "common/fiber.h"
#include "common/spin_lock.h" #include "common/spin_lock.h"
#if defined(_WIN32) || defined(WIN32)
#include <windows.h>
#else
#include <boost/context/detail/fcontext.hpp> #include <boost/context/detail/fcontext.hpp>
#endif
namespace Common { namespace Common {
constexpr std::size_t default_stack_size = 256 * 1024; // 256kb constexpr std::size_t default_stack_size = 256 * 1024;
struct Fiber::FiberImpl { struct Fiber::FiberImpl {
alignas(64) std::array<u8, default_stack_size> stack;
alignas(64) std::array<u8, default_stack_size> rewind_stack;
SpinLock guard{}; SpinLock guard{};
std::function<void(void*)> entry_point; std::function<void(void*)> entry_point;
std::function<void(void*)> rewind_point; std::function<void(void*)> rewind_point;
@ -26,17 +25,10 @@ struct Fiber::FiberImpl {
bool is_thread_fiber{}; bool is_thread_fiber{};
bool released{}; bool released{};
#if defined(_WIN32) || defined(WIN32) u8* stack_limit{};
LPVOID handle = nullptr; u8* rewind_stack_limit{};
LPVOID rewind_handle = nullptr; boost::context::detail::fcontext_t context{};
#else boost::context::detail::fcontext_t rewind_context{};
alignas(64) std::array<u8, default_stack_size> stack;
alignas(64) std::array<u8, default_stack_size> rewind_stack;
u8* stack_limit;
u8* rewind_stack_limit;
boost::context::detail::fcontext_t context;
boost::context::detail::fcontext_t rewind_context;
#endif
}; };
void Fiber::SetStartParameter(void* new_parameter) { void Fiber::SetStartParameter(void* new_parameter) {
@ -48,95 +40,6 @@ void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewin
impl->rewind_parameter = rewind_param; impl->rewind_parameter = rewind_param;
} }
#if defined(_WIN32) || defined(WIN32)
void Fiber::Start() {
ASSERT(impl->previous_fiber != nullptr);
impl->previous_fiber->impl->guard.unlock();
impl->previous_fiber.reset();
impl->entry_point(impl->start_parameter);
UNREACHABLE();
}
void Fiber::OnRewind() {
ASSERT(impl->handle != nullptr);
DeleteFiber(impl->handle);
impl->handle = impl->rewind_handle;
impl->rewind_handle = nullptr;
impl->rewind_point(impl->rewind_parameter);
UNREACHABLE();
}
void Fiber::FiberStartFunc(void* fiber_parameter) {
auto* fiber = static_cast<Fiber*>(fiber_parameter);
fiber->Start();
}
void Fiber::RewindStartFunc(void* fiber_parameter) {
auto* fiber = static_cast<Fiber*>(fiber_parameter);
fiber->OnRewind();
}
Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter)
: impl{std::make_unique<FiberImpl>()} {
impl->entry_point = std::move(entry_point_func);
impl->start_parameter = start_parameter;
impl->handle = CreateFiber(default_stack_size, &FiberStartFunc, this);
}
Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {}
Fiber::~Fiber() {
if (impl->released) {
return;
}
// Make sure the Fiber is not being used
const bool locked = impl->guard.try_lock();
ASSERT_MSG(locked, "Destroying a fiber that's still running");
if (locked) {
impl->guard.unlock();
}
DeleteFiber(impl->handle);
}
void Fiber::Exit() {
ASSERT_MSG(impl->is_thread_fiber, "Exitting non main thread fiber");
if (!impl->is_thread_fiber) {
return;
}
ConvertFiberToThread();
impl->guard.unlock();
impl->released = true;
}
void Fiber::Rewind() {
ASSERT(impl->rewind_point);
ASSERT(impl->rewind_handle == nullptr);
impl->rewind_handle = CreateFiber(default_stack_size, &RewindStartFunc, this);
SwitchToFiber(impl->rewind_handle);
}
void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) {
ASSERT_MSG(from != nullptr, "Yielding fiber is null!");
ASSERT_MSG(to != nullptr, "Next fiber is null!");
to->impl->guard.lock();
to->impl->previous_fiber = from;
SwitchToFiber(to->impl->handle);
ASSERT(from->impl->previous_fiber != nullptr);
from->impl->previous_fiber->impl->guard.unlock();
from->impl->previous_fiber.reset();
}
std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()};
fiber->impl->guard.lock();
fiber->impl->handle = ConvertThreadToFiber(nullptr);
fiber->impl->is_thread_fiber = true;
return fiber;
}
#else
void Fiber::Start(boost::context::detail::transfer_t& transfer) { void Fiber::Start(boost::context::detail::transfer_t& transfer) {
ASSERT(impl->previous_fiber != nullptr); ASSERT(impl->previous_fiber != nullptr);
impl->previous_fiber->impl->context = transfer.fctx; impl->previous_fiber->impl->context = transfer.fctx;
@ -229,5 +132,4 @@ std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
return fiber; return fiber;
} }
#endif
} // namespace Common } // namespace Common

@ -7,11 +7,9 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#if !defined(_WIN32) && !defined(WIN32)
namespace boost::context::detail { namespace boost::context::detail {
struct transfer_t; struct transfer_t;
} }
#endif
namespace Common { namespace Common {
@ -59,17 +57,10 @@ public:
private: private:
Fiber(); Fiber();
#if defined(_WIN32) || defined(WIN32)
void OnRewind();
void Start();
static void FiberStartFunc(void* fiber_parameter);
static void RewindStartFunc(void* fiber_parameter);
#else
void OnRewind(boost::context::detail::transfer_t& transfer); void OnRewind(boost::context::detail::transfer_t& transfer);
void Start(boost::context::detail::transfer_t& transfer); void Start(boost::context::detail::transfer_t& transfer);
static void FiberStartFunc(boost::context::detail::transfer_t transfer); static void FiberStartFunc(boost::context::detail::transfer_t transfer);
static void RewindStartFunc(boost::context::detail::transfer_t transfer); static void RewindStartFunc(boost::context::detail::transfer_t transfer);
#endif
struct FiberImpl; struct FiberImpl;
std::unique_ptr<FiberImpl> impl; std::unique_ptr<FiberImpl> impl;

@ -502,7 +502,7 @@ void KernelCore::InvalidateAllInstructionCaches() {
physical_core.ArmInterface().ClearInstructionCache(); physical_core.ArmInterface().ClearInstructionCache();
} }
} else { } else {
ASSERT_MSG(false, "UNIMPLEMENTED!!!!!!!!!!!"); UNIMPLEMENTED();
} }
} }