{
/* Remove the span from the free list. */
mspan_unlink_span(base, span);
- mspan_initialize_span(base, mgr, cxt, span, span_type);
- /* XXX. Update page map entries. */
+ /* Reinitialize span for new usage. */
+ mspan_initialize_span(base, mgr, cxt, span, span_type);
+ /* If needed, shrink or split the span. */
if (span->npages > pages)
{
- /* XXX. Split the span. */
- /*
- * XXX. Note that if we split a span than abutts the boundary,
- * we should instead destroy it and move back the boundary.
- */
+ if (base != NULL &&
+ span->first_page + span->npages >= mgr->boundary)
+ {
+ Size newboundary;
+ Size nreturned;
+
+ /*
+ * The span is adjacent to the boundary, so we can just shrink
+ * it and move the boundary backwards. But we need to clear
+ * any page map entries in the region we're returning, to
+ * prevent confusion down the road.
+ */
+ Assert(span->first_page + span->npages == mgr->boundary);
+ newboundary = span->first_page + pages;
+ nreturned = mgr->boundary - newboundary;
+ mspan_update_page_map(base, mgr, newboundary, nreturned, 0);
+ mgr->boundary = newboundary;
+ span->npages = pages;
+ }
+ else
+ {
+ /*
+ * XXX. The span isn't adjacent to the boundary. If there's
+ * a free span following this one, we can transfer the excess
+ * pages from this span to that span. If not, we need to
+ * allocate a new span to contain the free pages.
+ */
+ }
}
+
+ /*
+ * Make page map entries for the new span.
+ *
+ * If this is anything other than a large allocation, we could
+ * potentially see requests to free objects located anywhere within
+ * the span, so page map entries are needed for every page of the span.
+ * But for a large object, the first and last page are good enough;
+ * we should never get a request to free something in the middle of
+ * such a span, and the only other lookups we expect are for the pages
+ * end pages to check whether this is a free span that can be
+ * consolidated.
+ */
+ Assert(span->npages == pages);
+ if (span_type != MSPAN_TYPE_LARGE)
+ mspan_update_page_map(base, mgr, span->first_page,
+ span->npages, (((char *) span) - base) | 1);
+ else
+ {
+ mspan_update_page_map(base, mgr, span->first_page, 1,
+ (((char *) span) - base) | 1);
+ mspan_update_page_map(base, mgr,
+ span->first_page + span->npages - 1, 1,
+ (((char *) span) - base) | 1);
+ }
+
+ return span;
}
/*
/*
* If this is a span-of-spans, allocate a descriptor for the new span
- * out of the span itself. Otherwise, we
+ * out of the span itself. If it's not, span shuold already be non-NULL;
+ * see above.
*/
if (span_type == MSPAN_TYPE_SPAN_OF_SPANS)
{