From e6a1542264e00b0f7ab08081cd8b9a4ac45b3a59 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Wed, 19 Mar 2014 16:28:25 -0400 Subject: [PATCH] sb_private_region_for_allocator, part one. --- src/backend/utils/mmgr/sb_region.c | 83 ++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/src/backend/utils/mmgr/sb_region.c b/src/backend/utils/mmgr/sb_region.c index 2e7609c985..8ae176320c 100644 --- a/src/backend/utils/mmgr/sb_region.c +++ b/src/backend/utils/mmgr/sb_region.c @@ -153,16 +153,93 @@ sb_lookup_region(void *ptr) return NULL; } +/* + * When a backend-private sb_allocator needs more memory, it calls this + * function. We search the existing backend-private regions for one capable + * of satisfying the request; if none found, we must create a new region. + */ +sb_region * +sb_private_region_for_allocator(Size npages) +{ + int freelist = Min(fls(npages), NUM_PRIVATE_FREELISTS); + + Assert(npages > 0); + + while (freelist < NUM_PRIVATE_FREELISTS) + { + dlist_mutable_iter iter; + Size threshold = 1 << (freelist - 1); + + dlist_foreach_modify(iter, &private_freelist[freelist]) + { + sb_region *region; + Size largest; + + region = dlist_container(sb_region, fl_node, iter.cur); + + /* Skip regions that are certain not to have space. */ + if (region->contiguous_pages < npages) + continue; + + /* + * The region we're examining was at one point reported to + * have adequate space, but subsequent allocations might have + * eroded that, so recheck. If there's enough, we're done! + * + * NB: For larger allocations this might be suboptimal, because + * we might carve space out of a chunk that's bigger than we + * really need rather than locating the best fit across all + * chunks. It shouldn't be too far off, though, because + * chunks with way more contiguous space available will be on + * a higher-numbered freelist. For really large allocations, + * it's probably better to malloc() directly than go through + * this machinery. + */ + largest = FreePageManagerInquireLargest(region->fpm); + region->contiguous_pages = largest; + if (largest >= npages) + return region; + + /* + * The region we're examining not only doesn't have enough + * contiguous freespace to satisfy this allocation, but it + * doesn't even belong in this bucket. Move it to the right place. + */ + if (largest < threshold) + { + int new_freelist = Min(fls(npages), NUM_PRIVATE_FREELISTS); + + dlist_delete(iter.cur); + dlist_push_head(&private_freelist[new_freelist], + ®ion->fl_node); + } + } + + /* Try next freelist. */ + ++freelist; + } + + /* + * There is no existing backend-private region with enough freespace + * to satisfy the allocation request. Create a new one. + */ + + /* XXX. Not implemented yet. */ + + return NULL; +} + /* * When a free page manager detects that the maximum contiguous freespace in * a backend-private region has increased, it calls this function. Our job - * is to move the region to a higher-numbered freelist if necessary. + * is to free the region completely if there are no remaining allocatons, + * and otherwise to */ void sb_report_contiguous_freespace(sb_region *region, Size npages) { - Size old_freelist; - Size new_freelist; + int old_freelist; + int new_freelist; /* This should only be called for private regions. */ Assert(region->seg == NULL); -- 2.39.5