Add debugging code, fix bugs.
authorRobert Haas <rhaas@postgresql.org>
Fri, 28 Mar 2014 05:51:44 +0000 (22:51 -0700)
committerRobert Haas <rhaas@postgresql.org>
Fri, 28 Mar 2014 05:51:44 +0000 (22:51 -0700)
src/backend/utils/mmgr/sb_alloc.c
src/backend/utils/mmgr/sb_region.c
src/include/utils/sb_region.h

index dacb90ecae8e86431d6ed6e73268947c1f27c284..44ff9671610d5bcea04926e615642cd63387de3a 100644 (file)
@@ -316,20 +316,25 @@ sb_reset_allocator(sb_allocator *a)
                        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);
-
+                       while (span != NULL)
+                       {
+                               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);
+
+                               span = relptr_access(base, span->nextspan);
+                       }
                }
        }
 }
index b98d56c2a62d654944cf17c7d62a029a779e037c..6c442269b75e2790b68361c9379f893586618059 100644 (file)
@@ -111,10 +111,86 @@ static Size sb_private_pages_allocated;
 static bool sb_adjust_lookup(sb_region *region, bool insert);
 static bool sb_adjust_lookup_leaf(sb_lookup_leaf *leaf, sb_region *region,
                                          bool insert);
+static void sb_dump_regions_leaf(sb_region *last_region, sb_lookup_leaf *leaf);
 #if SIZEOF_SIZE_T > 4
 static sb_lookup_leaf *sb_find_leaf(Size highbits, bool insert);
 #endif
 
+/*
+ * Dump debugging information for sb_region objects.
+ */
+void
+sb_dump_regions(void)
+{
+#if SIZEOF_SIZE_T > 4
+       sb_region *last_region = NULL;
+
+       if (lookup_root.l2 != NULL)
+       {
+               int i;
+               int j;
+
+               for (i = 0; i < SB_LOOKUP_ROOT_ENTRIES; ++i)
+               {
+                       sb_lookup_l2 *l2 = lookup_root.l2[i];
+
+                       if (l2 == NULL)
+                               continue;
+                       for (j = 0; j < SB_LOOKUP_L2_ENTRIES; ++j)
+                       {
+                               sb_lookup_leaf *leaf = l2->leaf[j];
+
+                               if (leaf != NULL)
+                               {
+                                       sb_dump_regions_leaf(last_region, leaf);
+                                       last_region = leaf->region[leaf->nused - 1];
+                               }
+                       }
+               }
+       }
+       else
+       {
+               bool    first = true;
+               Size    highbits = 0;
+
+               for (;;)
+               {
+                       int             i;
+                       int             j;
+                       int             n = -1;
+                       sb_lookup_l2 *l2;
+
+                       /* Find next L2 entry to visit. */
+                       for (i = 0; i < SB_LOOKUP_ROOT_CACHE_SIZE; ++i)
+                       {
+                               if (lookup_root.cache_value[i] != NULL &&
+                                       (first || lookup_root.cache_key[i] > highbits))
+                                       n = i;
+                       }
+                       if (n == -1)
+                               break;
+                       first = false;
+                       highbits = lookup_root.cache_key[n];
+
+                       /* Dump this L2 entry. */
+                       l2 = lookup_root.cache_value[n];
+                       for (j = 0; j < SB_LOOKUP_L2_ENTRIES; ++j)
+                       {
+                               sb_lookup_leaf *leaf = l2->leaf[j];
+
+                               if (leaf != NULL)
+                               {
+                                       sb_dump_regions_leaf(last_region, leaf);
+                                       last_region = leaf->region[leaf->nused - 1];
+                               }
+                       }
+               }
+       }
+#else
+       sb_dump_regions_leaf(NULL, lookup_root_leaf);
+#endif
+}
+
 /*
  * Find the region to which a pointer belongs.
  */
@@ -493,6 +569,28 @@ sb_adjust_lookup_leaf(sb_lookup_leaf *leaf, sb_region *region, bool insert)
        return true;
 }
 
+/*
+ * Dump debugging information for the regions covered by a single
+ * sb_lookup_leaf.  Skip the first one if it's the same as last_region.
+ */
+static void
+sb_dump_regions_leaf(sb_region *last_region, sb_lookup_leaf *leaf)
+{
+       int i;
+
+       for (i = 0; i < leaf->nused; ++i)
+       {
+               sb_region *region = leaf->region[i];
+
+               if (i == 0 && region == last_region)
+                       continue;
+               fprintf(stderr, "== region at %p [%zu bytes, %zu usable pages] ==\n",
+                               region->region_start, region->region_size,
+                               region->usable_pages);
+               fprintf(stderr, "%s\n\n", FreePageManagerDump(region->fpm));
+       }
+}
+
 #if SIZEOF_SIZE_T > 4
 static sb_lookup_leaf *
 sb_find_leaf(Size highbits, bool insert)
@@ -543,15 +641,15 @@ sb_find_leaf(Size highbits, bool insert)
                        return NULL;
                if (unused != -1)
                {
-                       lookup_root.cache_key[i] = highbits;
-                       lookup_root.cache_value[i] = l2;
+                       lookup_root.cache_key[unused] = highbits;
+                       lookup_root.cache_value[unused] = l2;
                }
                else if (lookup_root.l2 != NULL)
                        lookup_root.l2[rootbits] = l2;
                else
                {
-                       lookup_root.l2 = malloc(sizeof(sb_lookup_l2 *)
-                                                                       * SB_LOOKUP_ROOT_ENTRIES);
+                       lookup_root.l2 = calloc(SB_LOOKUP_ROOT_ENTRIES,
+                                                                       sizeof(sb_lookup_l2 *));
                        if (lookup_root.l2 == NULL)
                        {
                                free(l2);
index c5264fcdebf297e5d0a3675b4da49d2a622e54e7..5bb01f38195ba13b8919593951c3a777d7a59a38 100644 (file)
@@ -58,6 +58,7 @@ extern sb_shared_region *sb_create_shared_region(dsm_segment *seg,
                                                char *lwlock_tranche_name);
 extern sb_allocator *sb_attach_shared_region(dsm_segment *,
                                                sb_shared_region *);
+extern void sb_dump_regions(void);
 
 /* For internal use by cooperating modules. */
 extern sb_region *sb_lookup_region(void *);