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);
+ }
}
}
}
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.
*/
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)
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);