Kernel: Make AnonymousVMObject construction OOM-aware

This commit moves the allocation of the resources required for
AnonymousVMObject from its constructors to its factory functions.

We're making this change to expose the fallibility of the allocation.
This commit is contained in:
creator1creeper1 2022-01-12 16:23:48 +01:00 committed by Idan Horowitz
parent d1f265e851
commit 3879e70447
Notes: sideshowbarker 2024-07-17 20:50:18 +09:00
2 changed files with 28 additions and 21 deletions

View File

@ -43,7 +43,8 @@ ErrorOr<NonnullRefPtr<VMObject>> AnonymousVMObject::try_clone()
// one and this one, as well as the clone have sufficient resources // one and this one, as well as the clone have sufficient resources
// to cow all pages as needed // to cow all pages as needed
auto new_shared_committed_cow_pages = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) SharedCommittedCowPages(move(committed_pages)))); auto new_shared_committed_cow_pages = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) SharedCommittedCowPages(move(committed_pages))));
auto clone = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousVMObject(*this, *new_shared_committed_cow_pages))); auto new_physical_pages = TRY(this->try_clone_physical_pages());
auto clone = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousVMObject(*this, *new_shared_committed_cow_pages, move(new_physical_pages))));
m_shared_committed_cow_pages = move(new_shared_committed_cow_pages); m_shared_committed_cow_pages = move(new_shared_committed_cow_pages);
@ -73,7 +74,9 @@ ErrorOr<NonnullRefPtr<AnonymousVMObject>> AnonymousVMObject::try_create_with_siz
committed_pages = TRY(MM.commit_user_physical_pages(ceil_div(size, static_cast<size_t>(PAGE_SIZE)))); committed_pages = TRY(MM.commit_user_physical_pages(ceil_div(size, static_cast<size_t>(PAGE_SIZE))));
} }
return adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousVMObject(size, strategy, move(committed_pages))); auto new_physical_pages = TRY(VMObject::try_create_physical_pages(size));
return adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousVMObject(move(new_physical_pages), strategy, move(committed_pages)));
} }
ErrorOr<NonnullRefPtr<AnonymousVMObject>> AnonymousVMObject::try_create_physically_contiguous_with_size(size_t size) ErrorOr<NonnullRefPtr<AnonymousVMObject>> AnonymousVMObject::try_create_physically_contiguous_with_size(size_t size)
@ -82,7 +85,9 @@ ErrorOr<NonnullRefPtr<AnonymousVMObject>> AnonymousVMObject::try_create_physical
if (contiguous_physical_pages.is_empty()) if (contiguous_physical_pages.is_empty())
return ENOMEM; return ENOMEM;
return adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousVMObject(contiguous_physical_pages.span())); auto new_physical_pages = TRY(FixedArray<RefPtr<PhysicalPage>>::try_create(contiguous_physical_pages.span()));
return adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousVMObject(move(new_physical_pages)));
} }
ErrorOr<NonnullRefPtr<AnonymousVMObject>> AnonymousVMObject::try_create_purgeable_with_size(size_t size, AllocationStrategy strategy) ErrorOr<NonnullRefPtr<AnonymousVMObject>> AnonymousVMObject::try_create_purgeable_with_size(size_t size, AllocationStrategy strategy)
@ -92,14 +97,17 @@ ErrorOr<NonnullRefPtr<AnonymousVMObject>> AnonymousVMObject::try_create_purgeabl
committed_pages = TRY(MM.commit_user_physical_pages(ceil_div(size, static_cast<size_t>(PAGE_SIZE)))); committed_pages = TRY(MM.commit_user_physical_pages(ceil_div(size, static_cast<size_t>(PAGE_SIZE))));
} }
auto vmobject = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousVMObject(size, strategy, move(committed_pages)))); auto new_physical_pages = TRY(VMObject::try_create_physical_pages(size));
auto vmobject = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousVMObject(move(new_physical_pages), strategy, move(committed_pages))));
vmobject->m_purgeable = true; vmobject->m_purgeable = true;
return vmobject; return vmobject;
} }
ErrorOr<NonnullRefPtr<AnonymousVMObject>> AnonymousVMObject::try_create_with_physical_pages(Span<NonnullRefPtr<PhysicalPage>> physical_pages) ErrorOr<NonnullRefPtr<AnonymousVMObject>> AnonymousVMObject::try_create_with_physical_pages(Span<NonnullRefPtr<PhysicalPage>> physical_pages)
{ {
return adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousVMObject(physical_pages)); auto new_physical_pages = TRY(FixedArray<RefPtr<PhysicalPage>>::try_create(physical_pages));
return adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousVMObject(move(new_physical_pages)));
} }
ErrorOr<NonnullRefPtr<AnonymousVMObject>> AnonymousVMObject::try_create_for_physical_range(PhysicalAddress paddr, size_t size) ErrorOr<NonnullRefPtr<AnonymousVMObject>> AnonymousVMObject::try_create_for_physical_range(PhysicalAddress paddr, size_t size)
@ -110,11 +118,13 @@ ErrorOr<NonnullRefPtr<AnonymousVMObject>> AnonymousVMObject::try_create_for_phys
return ENOMEM; return ENOMEM;
} }
return adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousVMObject(paddr, size)); auto new_physical_pages = TRY(VMObject::try_create_physical_pages(size));
return adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousVMObject(paddr, move(new_physical_pages)));
} }
AnonymousVMObject::AnonymousVMObject(size_t size, AllocationStrategy strategy, Optional<CommittedPhysicalPageSet> committed_pages) AnonymousVMObject::AnonymousVMObject(FixedArray<RefPtr<PhysicalPage>>&& new_physical_pages, AllocationStrategy strategy, Optional<CommittedPhysicalPageSet> committed_pages)
: VMObject(VMObject::must_create_physical_pages_but_fixme_should_propagate_errors(size)) : VMObject(move(new_physical_pages))
, m_unused_committed_pages(move(committed_pages)) , m_unused_committed_pages(move(committed_pages))
{ {
if (strategy == AllocationStrategy::AllocateNow) { if (strategy == AllocationStrategy::AllocateNow) {
@ -128,24 +138,21 @@ AnonymousVMObject::AnonymousVMObject(size_t size, AllocationStrategy strategy, O
} }
} }
AnonymousVMObject::AnonymousVMObject(PhysicalAddress paddr, size_t size) AnonymousVMObject::AnonymousVMObject(PhysicalAddress paddr, FixedArray<RefPtr<PhysicalPage>>&& new_physical_pages)
: VMObject(VMObject::must_create_physical_pages_but_fixme_should_propagate_errors(size)) : VMObject(move(new_physical_pages))
{ {
VERIFY(paddr.page_base() == paddr); VERIFY(paddr.page_base() == paddr);
for (size_t i = 0; i < page_count(); ++i) for (size_t i = 0; i < page_count(); ++i)
physical_pages()[i] = PhysicalPage::create(paddr.offset(i * PAGE_SIZE), MayReturnToFreeList::No); physical_pages()[i] = PhysicalPage::create(paddr.offset(i * PAGE_SIZE), MayReturnToFreeList::No);
} }
AnonymousVMObject::AnonymousVMObject(Span<NonnullRefPtr<PhysicalPage>> physical_pages) AnonymousVMObject::AnonymousVMObject(FixedArray<RefPtr<PhysicalPage>>&& new_physical_pages)
: VMObject(VMObject::must_create_physical_pages_but_fixme_should_propagate_errors(physical_pages.size() * PAGE_SIZE)) : VMObject(move(new_physical_pages))
{ {
for (size_t i = 0; i < physical_pages.size(); ++i) {
m_physical_pages[i] = physical_pages[i];
}
} }
AnonymousVMObject::AnonymousVMObject(AnonymousVMObject const& other, NonnullRefPtr<SharedCommittedCowPages> shared_committed_cow_pages) AnonymousVMObject::AnonymousVMObject(AnonymousVMObject const& other, NonnullRefPtr<SharedCommittedCowPages> shared_committed_cow_pages, FixedArray<RefPtr<PhysicalPage>>&& new_physical_pages)
: VMObject(other.must_clone_physical_pages_but_fixme_should_propagate_errors()) : VMObject(move(new_physical_pages))
, m_shared_committed_cow_pages(move(shared_committed_cow_pages)) , m_shared_committed_cow_pages(move(shared_committed_cow_pages))
, m_purgeable(other.m_purgeable) , m_purgeable(other.m_purgeable)
{ {

View File

@ -41,10 +41,10 @@ public:
private: private:
class SharedCommittedCowPages; class SharedCommittedCowPages;
explicit AnonymousVMObject(size_t, AllocationStrategy, Optional<CommittedPhysicalPageSet>); explicit AnonymousVMObject(FixedArray<RefPtr<PhysicalPage>>&&, AllocationStrategy, Optional<CommittedPhysicalPageSet>);
explicit AnonymousVMObject(PhysicalAddress, size_t); explicit AnonymousVMObject(PhysicalAddress, FixedArray<RefPtr<PhysicalPage>>&&);
explicit AnonymousVMObject(Span<NonnullRefPtr<PhysicalPage>>); explicit AnonymousVMObject(FixedArray<RefPtr<PhysicalPage>>&&);
explicit AnonymousVMObject(AnonymousVMObject const&, NonnullRefPtr<SharedCommittedCowPages>); explicit AnonymousVMObject(AnonymousVMObject const&, NonnullRefPtr<SharedCommittedCowPages>, FixedArray<RefPtr<PhysicalPage>>&&);
virtual StringView class_name() const override { return "AnonymousVMObject"sv; } virtual StringView class_name() const override { return "AnonymousVMObject"sv; }