// // BionicAllocator is a general purpose allocator designed to provide the same // functionality as the malloc/free/realloc/memalign libc functions. // // On alloc: // If size is > 1k allocator proxies malloc call directly to mmap. // If size <= 1k allocator uses BionicSmallObjectAllocator for the size // rounded up to the nearest power of two. // // On free: // // For a pointer allocated using proxy-to-mmap allocator unmaps // the memory. // // For a pointer allocated using BionicSmallObjectAllocator it adds // the block to free_blocks_list in the corresponding page. If the number of // free pages reaches 2, BionicSmallObjectAllocator munmaps one of the pages // keeping the other one in reserve.
// Memory management for large objects is fairly straightforward, but for small // objects it is more complicated. If you are changing this code, one simple // way to evaluate the memory usage change is by running 'dd' and examine the // memory usage by 'showmap $(pidof dd)'. 'dd' is nice in that: // 1. It links in quite a few libraries, so you get some linker memory use. // 2. When run with no arguments, it sits waiting for input, so it is easy to // examine its memory usage with showmap. // 3. Since it does nothing while waiting for input, the memory usage is // determinisitic.
// This type is used for large allocations (with size >1k) staticconst uint32_t kLargeObject = 111;
// Allocated pointers must be at least 16-byte aligned. Round up the size of // page_info to multiple of 16. static constexpr size_t kPageInfoSize = __builtin_align_up(sizeof(page_info), 16);
staticinline uint16_t log2(size_t number) {
uint16_t result = 0;
number--;
// Fully allocated pages are de-managed and removed from the page list, so // every page from the page list must be useable. Let's just take the first // one.
small_object_page_info* page = page_list_;
CHECK(page->free_block_list != nullptr);
if (page->free_blocks_cnt == blocks_per_page_) {
free_pages_cnt_--;
}
page->free_blocks_cnt--;
memset(block_record, 0, block_size_);
if (page->free_blocks_cnt == 0) { // De-manage fully allocated pages. These pages will be managed again if // a block is freed.
remove_from_page_list(page);
}
if (page->free_blocks_cnt == blocks_per_page_) { if (++free_pages_cnt_ > 1) { // if we already have a free page - unmap this one.
free_page(page);
}
} elseif (page->free_blocks_cnt == 1) { // We just freed from a full page. Add this page back to the list.
add_to_page_list(page);
}
}
for (size_t i = 0; i < kSmallObjectAllocatorsCount; ++i) {
uint32_t type = i + kSmallObjectMinSizeLog2; new (allocators + i) BionicSmallObjectAllocator(type, 1 << type);
}
void* BionicAllocator::memalign(size_t align, size_t size) { // The Bionic allocator only supports alignment up to one page, which is good // enough for ELF TLS.
align = MIN(align, page_size());
align = MAX(align, 16);
align = stdc_bit_ceil(align);
size = MAX(size, align); return alloc_impl(align, size);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.