1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-20 02:15:08 +00:00

Kernel: Handle OOM when adding memory regions to Spaces :^)

This commit is contained in:
Idan Horowitz 2021-07-15 01:18:00 +03:00 committed by Andreas Kling
parent e94dfb7355
commit be475cd6a8
3 changed files with 30 additions and 18 deletions

View file

@ -102,8 +102,13 @@ KResultOr<FlatPtr> Process::sys$fork(RegisterState& regs)
return ENOMEM; return ENOMEM;
} }
auto& child_region = child->space().add_region(region_clone.release_nonnull()); auto* child_region = child->space().add_region(region_clone.release_nonnull());
child_region.map(child->space().page_directory(), ShouldFlushTLB::No); if (!child_region) {
dbgln("fork: Cannot add region, insufficient memory");
// TODO: tear down new process?
return ENOMEM;
}
child_region->map(child->space().page_directory(), ShouldFlushTLB::No);
if (region == m_master_tls_region.unsafe_ptr()) if (region == m_master_tls_region.unsafe_ptr())
child->m_master_tls_region = child_region; child->m_master_tls_region = child_region;

View file

@ -156,16 +156,18 @@ KResultOr<Region*> Space::try_allocate_split_region(Region const& source_region,
m_process, range, source_region.vmobject(), offset_in_vmobject, KString::try_create(source_region.name()), source_region.access(), source_region.is_cacheable() ? Region::Cacheable::Yes : Region::Cacheable::No, source_region.is_shared()); m_process, range, source_region.vmobject(), offset_in_vmobject, KString::try_create(source_region.name()), source_region.access(), source_region.is_cacheable() ? Region::Cacheable::Yes : Region::Cacheable::No, source_region.is_shared());
if (!new_region) if (!new_region)
return ENOMEM; return ENOMEM;
auto& region = add_region(new_region.release_nonnull()); auto* region = add_region(new_region.release_nonnull());
region.set_syscall_region(source_region.is_syscall_region()); if (!region)
region.set_mmap(source_region.is_mmap()); return ENOMEM;
region.set_stack(source_region.is_stack()); region->set_syscall_region(source_region.is_syscall_region());
region->set_mmap(source_region.is_mmap());
region->set_stack(source_region.is_stack());
size_t page_offset_in_source_region = (offset_in_vmobject - source_region.offset_in_vmobject()) / PAGE_SIZE; size_t page_offset_in_source_region = (offset_in_vmobject - source_region.offset_in_vmobject()) / PAGE_SIZE;
for (size_t i = 0; i < region.page_count(); ++i) { for (size_t i = 0; i < region->page_count(); ++i) {
if (source_region.should_cow(page_offset_in_source_region + i)) if (source_region.should_cow(page_offset_in_source_region + i))
region.set_should_cow(i, true); region->set_should_cow(i, true);
} }
return &region; return region;
} }
KResultOr<Region*> Space::allocate_region(Range const& range, StringView name, int prot, AllocationStrategy strategy) KResultOr<Region*> Space::allocate_region(Range const& range, StringView name, int prot, AllocationStrategy strategy)
@ -179,7 +181,10 @@ KResultOr<Region*> Space::allocate_region(Range const& range, StringView name, i
return ENOMEM; return ENOMEM;
if (!region->map(page_directory())) if (!region->map(page_directory()))
return ENOMEM; return ENOMEM;
return &add_region(region.release_nonnull()); auto* added_region = add_region(region.release_nonnull());
if (!added_region)
return ENOMEM;
return added_region;
} }
KResultOr<Region*> Space::allocate_region_with_vmobject(Range const& range, NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, StringView name, int prot, bool shared) KResultOr<Region*> Space::allocate_region_with_vmobject(Range const& range, NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, StringView name, int prot, bool shared)
@ -202,14 +207,16 @@ KResultOr<Region*> Space::allocate_region_with_vmobject(Range const& range, Nonn
auto region = Region::try_create_user_accessible(m_process, range, move(vmobject), offset_in_vmobject, KString::try_create(name), prot_to_region_access_flags(prot), Region::Cacheable::Yes, shared); auto region = Region::try_create_user_accessible(m_process, range, move(vmobject), offset_in_vmobject, KString::try_create(name), prot_to_region_access_flags(prot), Region::Cacheable::Yes, shared);
if (!region) { if (!region) {
dbgln("allocate_region_with_vmobject: Unable to allocate Region"); dbgln("allocate_region_with_vmobject: Unable to allocate Region");
return nullptr; return ENOMEM;
} }
auto& region_ref = add_region(region.release_nonnull()); auto* added_region = add_region(region.release_nonnull());
if (!region_ref.map(page_directory())) { if (!added_region)
return ENOMEM;
if (!added_region->map(page_directory())) {
// FIXME: What is an appropriate error code here, really? // FIXME: What is an appropriate error code here, really?
return ENOMEM; return ENOMEM;
} }
return &region_ref; return added_region;
} }
bool Space::deallocate_region(Region& region) bool Space::deallocate_region(Region& region)
@ -284,12 +291,12 @@ Vector<Region*> Space::find_regions_intersecting(const Range& range)
return regions; return regions;
} }
Region& Space::add_region(NonnullOwnPtr<Region> region) Region* Space::add_region(NonnullOwnPtr<Region> region)
{ {
auto* ptr = region.ptr(); auto* ptr = region.ptr();
ScopedSpinLock lock(m_lock); ScopedSpinLock lock(m_lock);
m_regions.insert(region->vaddr().get(), move(region)); auto success = m_regions.try_insert(region->vaddr().get(), move(region));
return *ptr; return success ? ptr : nullptr;
} }
// Carve out a virtual address range from a region and return the two regions on either side // Carve out a virtual address range from a region and return the two regions on either side

View file

@ -24,7 +24,7 @@ public:
PageDirectory& page_directory() { return *m_page_directory; } PageDirectory& page_directory() { return *m_page_directory; }
const PageDirectory& page_directory() const { return *m_page_directory; } const PageDirectory& page_directory() const { return *m_page_directory; }
Region& add_region(NonnullOwnPtr<Region>); Region* add_region(NonnullOwnPtr<Region>);
size_t region_count() const { return m_regions.size(); } size_t region_count() const { return m_regions.size(); }