Finish up sb_free.
authorRobert Haas <rhaas@postgresql.org>
Tue, 29 Apr 2014 17:17:41 +0000 (13:17 -0400)
committerRobert Haas <rhaas@postgresql.org>
Tue, 29 Apr 2014 17:17:41 +0000 (13:17 -0400)
src/backend/utils/mmgr/sb_alloc.c

index 70eb9c75a064a680b3d2341117e6786e67b9ff0d..7082047d2074deefd7884aa7d931250306f0d795 100644 (file)
@@ -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;