mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-07 13:00:15 +02:00
120 lines
3.4 KiB
C++
120 lines
3.4 KiB
C++
// SPDX-License-Identifier: MIT
|
|
#pragma once
|
|
#include <FEXCore/Core/Context.h>
|
|
#include <FEXCore/Core/CoreState.h>
|
|
#include <FEXCore/Core/SignalDelegator.h>
|
|
#include <FEXCore/Utils/Event.h>
|
|
#include <FEXCore/Utils/InterruptableConditionVariable.h>
|
|
#include <FEXCore/Utils/Threads.h>
|
|
#include <FEXCore/Utils/TypeDefines.h>
|
|
#include <FEXCore/fextl/memory.h>
|
|
#include <FEXCore/fextl/vector.h>
|
|
|
|
#include <shared_mutex>
|
|
#include <type_traits>
|
|
|
|
namespace FEXCore {
|
|
class LookupCache;
|
|
class CompileService;
|
|
struct JITSymbolBuffer;
|
|
} // namespace FEXCore
|
|
|
|
namespace FEXCore::Context {
|
|
class Context;
|
|
}
|
|
|
|
namespace FEXCore::CPU {
|
|
class CPUBackend;
|
|
} // namespace FEXCore::CPU
|
|
|
|
namespace FEXCore::Frontend {
|
|
class Decoder;
|
|
}
|
|
|
|
namespace FEXCore::IR {
|
|
class OpDispatchBuilder;
|
|
class PassManager;
|
|
} // namespace FEXCore::IR
|
|
|
|
namespace FEXCore::Profiler {
|
|
struct ThreadStats;
|
|
};
|
|
|
|
namespace FEXCore::Core {
|
|
|
|
// Special-purpose replacement for std::unique_ptr to allow InternalThreadState to be standard layout.
|
|
// Since a NonMovableUniquePtr is neither copyable nor movable, its only function is to own and release the contained object.
|
|
template<typename T>
|
|
struct NonMovableUniquePtr {
|
|
NonMovableUniquePtr() noexcept = default;
|
|
NonMovableUniquePtr(const NonMovableUniquePtr&) = delete;
|
|
NonMovableUniquePtr& operator=(const NonMovableUniquePtr& UPtr) = delete;
|
|
|
|
NonMovableUniquePtr& operator=(fextl::unique_ptr<T> UPtr) noexcept {
|
|
Ptr = UPtr.release();
|
|
return *this;
|
|
}
|
|
|
|
~NonMovableUniquePtr() {
|
|
fextl::default_delete<T> {}(Ptr);
|
|
}
|
|
|
|
T* operator->() const noexcept {
|
|
return Ptr;
|
|
}
|
|
|
|
std::add_lvalue_reference_t<T> operator*() const noexcept {
|
|
return *Ptr;
|
|
}
|
|
|
|
T* get() const noexcept {
|
|
return Ptr;
|
|
}
|
|
|
|
operator bool() const noexcept {
|
|
return Ptr != nullptr;
|
|
}
|
|
|
|
private:
|
|
T* Ptr = nullptr;
|
|
};
|
|
static_assert(!std::is_move_constructible_v<NonMovableUniquePtr<int>>);
|
|
static_assert(!std::is_move_assignable_v<NonMovableUniquePtr<int>>);
|
|
|
|
struct InternalThreadState : public FEXCore::Allocator::FEXAllocOperators {
|
|
FEXCore::Core::CpuStateFrame* const CurrentFrame = &BaseFrameState;
|
|
|
|
FEXCore::Context::Context* const CTX;
|
|
|
|
NonMovableUniquePtr<FEXCore::IR::OpDispatchBuilder> OpDispatcher;
|
|
|
|
NonMovableUniquePtr<FEXCore::CPU::CPUBackend> CPUBackend;
|
|
NonMovableUniquePtr<FEXCore::LookupCache> LookupCache;
|
|
|
|
NonMovableUniquePtr<FEXCore::Frontend::Decoder> FrontendDecoder;
|
|
NonMovableUniquePtr<FEXCore::IR::PassManager> PassManager;
|
|
NonMovableUniquePtr<JITSymbolBuffer> SymbolBuffer;
|
|
|
|
std::shared_ptr<FEXCore::CompileService> CompileService;
|
|
|
|
std::shared_mutex ObjectCacheRefCounter {};
|
|
|
|
// This pointer is owned by the frontend.
|
|
FEXCore::Profiler::ThreadStats* ThreadStats {};
|
|
|
|
///< Data pointer for exclusive use by the frontend
|
|
void* FrontendPtr;
|
|
|
|
// BaseFrameState should always be at the end, directly before the interrupt fault page
|
|
alignas(16) FEXCore::Core::CpuStateFrame BaseFrameState {};
|
|
|
|
// Can be reprotected as RO to trigger an interrupt at generated code block entrypoints
|
|
alignas(FEXCore::Utils::FEX_PAGE_SIZE) uint8_t InterruptFaultPage[FEXCore::Utils::FEX_PAGE_SIZE];
|
|
};
|
|
static_assert(std::is_standard_layout_v<FEXCore::Core::InternalThreadState>);
|
|
static_assert(
|
|
(offsetof(FEXCore::Core::InternalThreadState, InterruptFaultPage) - offsetof(FEXCore::Core::InternalThreadState, BaseFrameState)) < 4096,
|
|
"Fault page is outside of immediate range from CPU state");
|
|
|
|
} // namespace FEXCore::Core
|