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);