mirror of
https://github.com/SerenityOS/serenity.git
synced 2026-11-07 04:29:30 -10:00
Kernel/Memory: Allow subclassing VirtualRange
This will be used for GPU virtual address ranges. Use an explicit Self template parameter instead of just using `VirtualRangeBase` as argument/return type to make different subclasses intentionally incompatible with each other. This will e.g. not allow comparing CPU virtual address ranges with GPU virtual address ranges. Don't put expand_to_page_boundaries() in the new base class since this function assumes a CPU page size of 4K. Additionally, since this is a static member function, deducing this would not work and we would have to use CRTP for this function (but we could still use deducing this for the other ones).
This commit is contained in:
1 parent
25538bf0f0
commit
30d5f2c1fc
1 file changed
+35
-24
@@ -13,10 +13,11 @@
|
||||
|
||||
namespace Kernel::Memory {
|
||||
|
||||
class VirtualRange {
|
||||
template<typename VirtualAddress>
|
||||
class VirtualRangeBase {
|
||||
public:
|
||||
VirtualRange() = delete;
|
||||
VirtualRange(VirtualAddress base, size_t size)
|
||||
VirtualRangeBase() = delete;
|
||||
VirtualRangeBase(VirtualAddress base, size_t size)
|
||||
: m_base(base)
|
||||
, m_size(size)
|
||||
{
|
||||
@@ -30,9 +31,10 @@ public:
|
||||
|
||||
VirtualAddress end() const { return m_base.offset(m_size); }
|
||||
|
||||
bool operator==(VirtualRange const& other) const
|
||||
template<typename Self>
|
||||
bool operator==(this Self const& self, Self const& other)
|
||||
{
|
||||
return m_base == other.m_base && m_size == other.m_size;
|
||||
return self.m_base == other.m_base && self.m_size == other.m_size;
|
||||
}
|
||||
|
||||
bool contains(VirtualAddress base, size_t size) const
|
||||
@@ -42,39 +44,43 @@ public:
|
||||
return base >= m_base && base.offset(size) <= end();
|
||||
}
|
||||
|
||||
bool contains(VirtualRange const& other) const
|
||||
template<typename Self>
|
||||
bool contains(this Self const& self, Self const& other)
|
||||
{
|
||||
return contains(other.base(), other.size());
|
||||
return self.contains(other.base(), other.size());
|
||||
}
|
||||
|
||||
Vector<VirtualRange, 2> carve(VirtualRange const& taken) const
|
||||
template<typename Self>
|
||||
Vector<Self, 2> carve(this Self const& self, Self const& taken)
|
||||
{
|
||||
VERIFY((taken.size() % PAGE_SIZE) == 0);
|
||||
|
||||
Vector<VirtualRange, 2> parts;
|
||||
if (taken == *this)
|
||||
Vector<Self, 2> parts;
|
||||
if (taken == self)
|
||||
return {};
|
||||
if (taken.base() > base())
|
||||
parts.unchecked_append({ base(), taken.base().get() - base().get() });
|
||||
if (taken.end() < end())
|
||||
parts.unchecked_append({ taken.end(), end().get() - taken.end().get() });
|
||||
if (taken.base() > self.base())
|
||||
parts.unchecked_append({ self.base(), taken.base().get() - self.base().get() });
|
||||
if (taken.end() < self.end())
|
||||
parts.unchecked_append({ taken.end(), self.end().get() - taken.end().get() });
|
||||
return parts;
|
||||
}
|
||||
|
||||
VirtualRange intersect(VirtualRange const& other) const
|
||||
template<typename Self>
|
||||
Self intersect(this Self const& self, Self const& other)
|
||||
{
|
||||
if (*this == other) {
|
||||
return *this;
|
||||
if (self == other) {
|
||||
return self;
|
||||
}
|
||||
auto new_base = max(base(), other.base());
|
||||
auto new_end = min(end(), other.end());
|
||||
auto new_base = max(self.base(), other.base());
|
||||
auto new_end = min(self.end(), other.end());
|
||||
VERIFY(new_base < new_end);
|
||||
return VirtualRange(new_base, (new_end - new_base).get());
|
||||
return Self(new_base, (new_end - new_base).get());
|
||||
}
|
||||
|
||||
bool intersects(VirtualRange const& other) const
|
||||
template<typename Self>
|
||||
bool intersects(this Self const& self, Self const& other)
|
||||
{
|
||||
auto a = *this;
|
||||
auto a = self;
|
||||
auto b = other;
|
||||
|
||||
if (a.base() > b.base())
|
||||
@@ -83,13 +89,18 @@ public:
|
||||
return a.base() < b.end() && b.base() < a.end();
|
||||
}
|
||||
|
||||
static ErrorOr<VirtualRange> expand_to_page_boundaries(FlatPtr address, size_t size);
|
||||
|
||||
private:
|
||||
VirtualAddress m_base;
|
||||
size_t m_size { 0 };
|
||||
};
|
||||
|
||||
class VirtualRange : public VirtualRangeBase<VirtualAddress> {
|
||||
using VirtualRangeBase::VirtualRangeBase;
|
||||
|
||||
public:
|
||||
static ErrorOr<VirtualRange> expand_to_page_boundaries(FlatPtr address, size_t size);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
|
||||
Reference in new issue
Block a user