| |
| |
|
|
| #pragma once |
|
|
| #include <concepts> |
| #include <functional> |
| #include <mutex> |
| #include <vector> |
|
|
| #include "common/common_types.h" |
|
|
| namespace Common { |
| template <typename VaType, size_t AddressSpaceBits> |
| concept AddressSpaceValid = std::is_unsigned_v<VaType> && sizeof(VaType) * 8 >= |
| AddressSpaceBits; |
|
|
| struct EmptyStruct {}; |
|
|
| |
| |
| |
| template <typename VaType, VaType UnmappedVa, typename PaType, PaType UnmappedPa, |
| bool PaContigSplit, size_t AddressSpaceBits, typename ExtraBlockInfo = EmptyStruct> |
| requires AddressSpaceValid<VaType, AddressSpaceBits> |
| class FlatAddressSpaceMap { |
| public: |
| |
| static constexpr VaType VaMaximum{(1ULL << (AddressSpaceBits - 1)) + |
| ((1ULL << (AddressSpaceBits - 1)) - 1)}; |
|
|
| explicit FlatAddressSpaceMap(VaType va_limit, |
| std::function<void(VaType, VaType)> unmap_callback = {}); |
|
|
| FlatAddressSpaceMap() = default; |
|
|
| void Map(VaType virt, PaType phys, VaType size, ExtraBlockInfo extra_info = {}) { |
| std::scoped_lock lock(block_mutex); |
| MapLocked(virt, phys, size, extra_info); |
| } |
|
|
| void Unmap(VaType virt, VaType size) { |
| std::scoped_lock lock(block_mutex); |
| UnmapLocked(virt, size); |
| } |
|
|
| VaType GetVALimit() const { |
| return va_limit; |
| } |
|
|
| protected: |
| |
| |
| |
| |
| struct Block { |
| |
| VaType virt{UnmappedVa}; |
| |
| PaType phys{UnmappedPa}; |
| [[no_unique_address]] ExtraBlockInfo extra_info; |
|
|
| Block() = default; |
|
|
| Block(VaType virt_, PaType phys_, ExtraBlockInfo extra_info_) |
| : virt(virt_), phys(phys_), extra_info(extra_info_) {} |
|
|
| bool Valid() const { |
| return virt != UnmappedVa; |
| } |
|
|
| bool Mapped() const { |
| return phys != UnmappedPa; |
| } |
|
|
| bool Unmapped() const { |
| return phys == UnmappedPa; |
| } |
|
|
| bool operator<(const VaType& p_virt) const { |
| return virt < p_virt; |
| } |
| }; |
|
|
| |
| |
| |
| |
| void MapLocked(VaType virt, PaType phys, VaType size, ExtraBlockInfo extra_info); |
|
|
| |
| |
| |
| |
| void UnmapLocked(VaType virt, VaType size); |
|
|
| std::mutex block_mutex; |
| std::vector<Block> blocks{Block{}}; |
|
|
| |
| VaType va_limit{VaMaximum}; |
|
|
| private: |
| |
| std::function<void(VaType, VaType)> unmap_callback{}; |
| }; |
|
|
| |
| |
| |
| |
| template <typename VaType, VaType UnmappedVa, size_t AddressSpaceBits> |
| requires AddressSpaceValid<VaType, AddressSpaceBits> |
| class FlatAllocator |
| : public FlatAddressSpaceMap<VaType, UnmappedVa, bool, false, false, AddressSpaceBits> { |
| private: |
| using Base = FlatAddressSpaceMap<VaType, UnmappedVa, bool, false, false, AddressSpaceBits>; |
|
|
| public: |
| explicit FlatAllocator(VaType virt_start, VaType va_limit = Base::VaMaximum); |
|
|
| |
| |
| |
| VaType Allocate(VaType size); |
|
|
| |
| |
| |
| void AllocateFixed(VaType virt, VaType size); |
|
|
| |
| |
| |
| void Free(VaType virt, VaType size); |
|
|
| VaType GetVAStart() const { |
| return virt_start; |
| } |
|
|
| private: |
| |
| VaType virt_start; |
|
|
| |
| |
| |
| |
| VaType current_linear_alloc_end; |
| }; |
| } |
|
|