From: Robert Haas Date: Tue, 29 Apr 2014 17:17:41 +0000 (-0400) Subject: Finish up sb_free. X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=5f2d36c19c4c99d81987f607cc9db9df23c49d7f;p=users%2Frhaas%2Fpostgres.git Finish up sb_free. --- diff --git a/src/backend/utils/mmgr/sb_alloc.c b/src/backend/utils/mmgr/sb_alloc.c index 70eb9c75a0..7082047d20 100644 --- a/src/backend/utils/mmgr/sb_alloc.c +++ b/src/backend/utils/mmgr/sb_alloc.c @@ -347,9 +347,13 @@ sb_free(void *ptr) FreePageManagerPut(region->fpm, first_page, span->npages); /* - * XXX. Free the span, and possibly the span-of-spans which contains - * it. + * Span-of-spans superblocks store the span which describes them + * within the superblock itself, so freeing the storage implicitly + * frees the descriptor also. If this is a superblock of any other + * type, we need to separately free the span object also. */ + if (span->size_class != SB_SCLASS_SPAN_OF_SPANS) + sb_free(span); } /* If we locked the heap, release the lock. */ @@ -516,10 +520,12 @@ sb_ensure_active_superblock(char *base, sb_region *region, sb_allocator *a, /* * Compute the number of objects that will fit in a superblock of this - * size class. + * size class. Span-of-spans superblocks are just a single page, and the + * first object isn't available for use because it describes the + * span-of-spans itself. */ if (size_class == SB_SCLASS_SPAN_OF_SPANS) - nmax = FPM_PAGE_SIZE / obsize; + nmax = FPM_PAGE_SIZE / obsize - 1; else nmax = SB_SUPERBLOCK_SIZE / obsize; @@ -635,12 +641,6 @@ sb_ensure_active_superblock(char *base, sb_region *region, sb_allocator *a, for (i = 0; i < npages; ++i) sb_map_set(region->pagemap, first_page + i, span); - /* For a span-of-spans, record that we allocated ourselves. */ - if (size_class == SB_SCLASS_SPAN_OF_SPANS) - { - span->ninitialized = 1; - span->nallocatable--; - } return true; } @@ -665,7 +665,17 @@ sb_init_span(char *base, sb_span *span, sb_heap *heap, char *ptr, span->size_class = size_class; span->ninitialized = 0; if (size_class == SB_SCLASS_SPAN_OF_SPANS) - span->nallocatable = FPM_PAGE_SIZE / obsize; + { + /* + * A span-of-spans contains its own descriptor, so mark one object + * as initialized and reduce the count of allocatable objects by one. + * Doing this here has the side effect of also reducing nmax by one, + * which is important to make sure we free this object at the correct + * time. + */ + span->ninitialized = 1; + span->nallocatable = FPM_PAGE_SIZE / obsize - 1; + } else if (size_class != SB_SCLASS_SPAN_LARGE) span->nallocatable = SB_SUPERBLOCK_SIZE / obsize; span->firstfree = SB_SPAN_NOTHING_FREE;