| | |
| | |
| |
|
| | #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; |
| | }; |
| | } |
| |
|