diff --git a/AK/Bitmap.h b/AK/Bitmap.h index bb92a22fbb..dd76c1666b 100644 --- a/AK/Bitmap.h +++ b/AK/Bitmap.h @@ -285,6 +285,35 @@ public: return {}; } + Optional find_best_fit(size_t minimum_length) const + { + size_t start = 0; + size_t best_region_start = 0; + size_t best_region_size = max_size; + bool found = false; + + while (true) { + // Look for the next block which is bigger than requested length. + auto length_of_found_range = find_next_range_of_unset_bits(start, minimum_length, best_region_size); + if (length_of_found_range.has_value()) { + if (best_region_size > length_of_found_range.value() || !found) { + best_region_start = start; + best_region_size = length_of_found_range.value(); + found = true; + } + start += length_of_found_range.value(); + } else { + // There are no ranges which can fit requested length. + break; + } + } + + if (found) { + return best_region_start; + } + return {}; + } + Bitmap() : m_size(0) , m_owned(true) diff --git a/Kernel/Heap/kmalloc.cpp b/Kernel/Heap/kmalloc.cpp index 2ae70fdba8..239dcf57e3 100644 --- a/Kernel/Heap/kmalloc.cpp +++ b/Kernel/Heap/kmalloc.cpp @@ -150,7 +150,16 @@ void* kmalloc_impl(size_t size) size_t chunks_needed = (real_size + CHUNK_SIZE - 1) / CHUNK_SIZE; Bitmap bitmap_wrapper = Bitmap::wrap(alloc_map, POOL_SIZE / CHUNK_SIZE); - auto first_chunk = bitmap_wrapper.find_first_fit(chunks_needed); + Optional first_chunk; + + // Choose the right politic for allocation. + constexpr u32 best_fit_threshold = 128; + if (chunks_needed < best_fit_threshold) { + first_chunk = bitmap_wrapper.find_first_fit(chunks_needed); + } else { + first_chunk = bitmap_wrapper.find_best_fit(chunks_needed); + } + if (!first_chunk.has_value()) { klog() << "kmalloc(): PANIC! Out of memory (no suitable block for size " << size << ")"; Kernel::dump_backtrace();