LWLockAcquire(lock, LW_EXCLUSIVE);
}
- /* XXX. What about large objects? */
-
/* Compute the object size. */
size_class = span->size_class;
obsize = sb_size_classes[size_class];
+ /* If it's a large object, free the entire span. */
+ if (size_class == SB_SCLASS_SPAN_LARGE)
+ {
+ sb_heap *heap = relptr_access(base, span->parent);
+ Size first_page;
+
+ sb_unlink_span(base, heap, span);
+ first_page = fpm_pointer_to_page(fpm_base,
+ relptr_access(base, span->start));
+ FreePageManagerPut(region->fpm, first_page, span->npages);
+ sb_free(span);
+
+ /* We're done, but must release any lock first. */
+ if (lock != NULL)
+ LWLockRelease(lock);
+ }
+
/* Put the object on the superblock's freelist. */
superblock = relptr_access(base, span->start);
Assert(((char *) ptr) >= superblock);
span->firstfree = (((char *) ptr) - superblock) / obsize;
span->nallocatable++;
- /*
- * If the superblock was previously completely full, we need to move it
- * out of the highest-numbered fullness class so that it can potentially
- * be used for new allocations.
- */
if (span->nallocatable == 1 && span->fclass == SB_FULLNESS_CLASSES - 1)
{
sb_heap *heap = relptr_access(base, span->parent);
sb_span *new_nextspan;
- /* Move to next lower-numbered list. */
+ /*
+ * The superblock is completely full and is located in the
+ * highest-numbered fullness class, which is never scanned for free
+ * chunks. We must move it to the next-lower fullness class.
+ */
+
sb_unlink_span(base, heap, span);
span->fclass = SB_FULLNESS_CLASSES - 2;
relptr_copy(span->nextspan, heap->spans[SB_FULLNESS_CLASSES - 2]);
relptr_store(base, new_nextspan->prevspan, span);
relptr_store(base, heap->spans[SB_FULLNESS_CLASSES - 2], span);
}
- else if (span->nallocatable == span->nmax)
+ else if (span->nallocatable == span->nmax && (span->fclass != 1 ||
+ !relptr_is_null(span->prevspan)))
{
sb_heap *heap = relptr_access(base, span->parent);
Size first_page;
+ /*
+ * This entire superblock is free, and it's not the active superblock
+ * for this size class. Return the memory to the free page manager.
+ * We don't do this for the active superblock to prevent hysteresis:
+ * if we repeatedly allocate and free the only chunk in the active
+ * superblock, it will be very inefficient if we deallocate and
+ * reallocate the superblock every time.
+ */
sb_unlink_span(base, heap, span);
first_page = fpm_pointer_to_page(fpm_base,
relptr_access(base, span->start));