sb_reset_allocator
authorRobert Haas <rhaas@postgresql.org>
Wed, 26 Mar 2014 23:53:44 +0000 (16:53 -0700)
committerRobert Haas <rhaas@postgresql.org>
Wed, 26 Mar 2014 23:53:44 +0000 (16:53 -0700)
src/backend/utils/mmgr/sb_alloc.c
src/include/utils/sb_alloc.h

index 30dd5c5c5c43c466fd23b94c232cfcfd69c9f8da..dacb90ecae8e86431d6ed6e73268947c1f27c284 100644 (file)
@@ -273,6 +273,67 @@ sb_alloc(sb_allocator *a, Size size, int flags)
        return result;          
 }
 
+/*
+ * Free all memory used by an allocator.
+ *
+ * NB: It's not safe to do this while the allocator is in use!
+ */
+void
+sb_reset_allocator(sb_allocator *a)
+{
+       char *base = NULL;
+       int     num_heaps;
+       int heapno;
+
+       /*
+        * For shared memory allocation, pointers are relative to the start of the
+        * region.
+        */
+       if (!a->private)
+       {
+               sb_region *region = sb_lookup_region(a);
+               if (region == NULL)
+                       elog(ERROR, "sb_region not found");
+               base = region->region_start;
+       }
+
+       /*
+        * Iterate through heaps back to front.  We do it this way so that
+        * spans-of-spans are freed last.
+        */
+       num_heaps = a->heaps_per_size_class * (int) a->num_size_classes;
+       for (heapno = num_heaps; heapno >= 0; --heapno)
+       {
+               sb_heap *heap = &a->heaps[heapno];
+               Size    fclass;
+
+               for (fclass = 0; fclass < SB_FULLNESS_CLASSES; ++fclass)
+               {
+                       sb_region *region;
+                       char *superblock;
+                       sb_span *span;
+                       char *fpm_base;
+                       Size first_page;
+
+                       span = relptr_access(base, heap->spans[fclass]);
+                       superblock = base + span->first_page * FPM_PAGE_SIZE;
+                       region = sb_lookup_region(superblock);
+                       Assert(region != NULL);
+                       fpm_base = fpm_segment_base(region->fpm);
+                       /*
+                        * XXX.  Here's where the wheels are going to come
+                        * off if it turns out that malloc returns somethign that isn't
+                        * page-aligned.... what do we do about this?  Maybe we should
+                        * rejigger things so that the fpm base is NULL for all private
+                        * stuff.
+                        */
+                       first_page = (superblock - fpm_base) / FPM_PAGE_SIZE;
+                       FreePageManagerPut(region->fpm, first_page, span->npages);
+
+               }
+       }
+}
+
 /*
  * Allocate an object from the provided heap.  Caller is responsible for
  * any required locking.
index 5794bee4d1032c52d1b75064152e1cdb4f3c28fb..0ed528b6d1274378986821194429c9e83be4d33b 100644 (file)
@@ -69,6 +69,7 @@ typedef struct sb_allocator
 extern sb_allocator *sb_create_private_allocator(void);
 extern void *sb_alloc(sb_allocator *, Size, int flags);
 extern void sb_free(void *ptr);
+extern void sb_reset_allocator(sb_allocator *a);
 extern void sb_destroy_private_allocator(sb_allocator *);
 
 #endif         /* SB_ALLOC_H */