diff options
author | Hendiadyoin1 <leon2002.la@gmail.com> | 2022-02-14 13:40:14 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-03-14 23:30:08 +0100 |
commit | 1a739b5d6ea4257e8e2b607e43152047016346e4 (patch) | |
tree | 47aafcddf4b24adc5509ca22c4c73c34709798e1 /Kernel | |
parent | 05381753c2364ca42542b516a8fd64fbc0e45c9e (diff) | |
download | serenity-1a739b5d6ea4257e8e2b607e43152047016346e4.zip |
Kernel: Try to reuse empty slabheaps before expanding the kmalloc-heap
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Heap/kmalloc.cpp | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/Kernel/Heap/kmalloc.cpp b/Kernel/Heap/kmalloc.cpp index eeeb4c4bc0..d7b62e40f2 100644 --- a/Kernel/Heap/kmalloc.cpp +++ b/Kernel/Heap/kmalloc.cpp @@ -168,6 +168,31 @@ public: return total; } + bool try_purge() + { + bool did_purge = false; + + // Note: We cannot remove children from the list when using a structured loop, + // Because we need to advance the iterator before we delete the underlying + // value, so we have to iterate manually + + auto block = m_usable_blocks.begin(); + while (block != m_usable_blocks.end()) { + if (block->allocated_bytes() != 0) { + ++block; + continue; + } + auto& block_to_remove = *block; + ++block; + block_to_remove.list_node.remove(); + block_to_remove.~KmallocSlabBlock(); + kfree_aligned(&block_to_remove); + + did_purge = true; + } + return did_purge; + } + private: size_t m_slab_size { 0 }; @@ -205,6 +230,22 @@ struct KmallocGlobalData { return ptr; } + // NOTE: This size calculation is a mirror of kmalloc_aligned(KmallocSlabBlock) + if (size <= KmallocSlabBlock::block_size * 2 + sizeof(ptrdiff_t) + sizeof(size_t)) { + // FIXME: We should propagate a freed pointer, to find the specific subheap it belonged to + // This would save us iterating over them in the next step and remove a recursion + bool did_purge = false; + for (auto& slabheap : slabheaps) { + if (slabheap.try_purge()) { + dbgln_if(KMALLOC_DEBUG, "Kmalloc purged block(s) from slabheap of size {} to avoid expansion", slabheap.slab_size()); + did_purge = true; + break; + } + } + if (did_purge) + return allocate(size); + } + if (!try_expand(size)) { PANIC("OOM when trying to expand kmalloc heap."); } |