Size npages; /* Length of span in pages. */
uint16 size_class; /* Size class. */
uint16 ninitialized; /* Maximum number of objects ever allocated. */
- uint16 nallocatable; /* Number of objects currently allocated. */
+ uint16 nallocatable; /* Number of objects currently allocatable. */
uint16 firstfree; /* First object on free list. */
+ uint16 nmax; /* Maximum number of objects ever possible. */
+ uint16 fclass; /* Current fullness class. */
};
#define SB_SPAN_NOTHING_FREE ((uint16) -1)
+#define SB_SUPERBLOCK_SIZE (SB_PAGES_PER_SUPERBLOCK * FPM_PAGE_SIZE)
/*
* Small allocations are handled by dividing a relatively large chunk of
return result;
}
+/*
+ * Free memory allocated via sb_alloc.
+ */
+void
+sb_free(void *ptr)
+{
+ sb_region *region;
+ char *fpm_base;
+ char *base = NULL;
+ sb_span *span;
+ LWLock *lock = NULL;
+ char *superblock;
+ Size pageno;
+ Size obsize;
+
+ /* Locate the containing superblock. */
+ region = sb_lookup_region(ptr);
+ fpm_base = fpm_segment_base(region->fpm);
+ pageno = fpm_pointer_to_page(fpm_base, ptr);
+ span = sb_map_get(region->pagemap, pageno);
+
+ /*
+ * If this is a shared-memory region, we might need locking. If so,
+ * lock the heap.
+ */
+ if (region->seg != NULL)
+ {
+ sb_heap *heap = relptr_access(fpm_base, span->parent);
+ base = fpm_base;
+ lock = relptr_access(fpm_base, heap->lock);
+ if (lock != NULL)
+ LWLockAcquire(lock, LW_EXCLUSIVE);
+ }
+
+ /* Put the object on the superblock's freelist. */
+ superblock = relptr_access(base, span->start);
+ obsize = sb_size_classes[span->size_class];
+ Assert(((char *) ptr) >= superblock);
+ Assert(((char *) ptr) < superblock + SB_SUPERBLOCK_SIZE);
+ Assert((((char *) ptr) - superblock) % obsize == 0);
+ * (Size *) ptr = span->firstfree;
+ 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(fpm_base, span->parent);
+ sb_span *nextspan = relptr_access(base, span->nextspan);
+ sb_span *prevspan = relptr_access(base, span->prevspan);
+ sb_span *new_nextspan;
+
+ /* Remove from current list. */
+ relptr_store(base, span->prevspan, (sb_span *) NULL);
+ if (nextspan != NULL)
+ relptr_copy(nextspan->prevspan, span->prevspan);
+ if (prevspan != NULL)
+ relptr_copy(prevspan->nextspan, span->nextspan);
+ else
+ relptr_copy(heap->spans[span->fclass], span->nextspan);
+
+ /* Add to correct list. */
+ span->fclass = SB_FULLNESS_CLASSES - 2;
+ relptr_copy(span->nextspan, heap->spans[SB_FULLNESS_CLASSES - 2]);
+ relptr_store(base, span->prevspan, (sb_span *) NULL);
+ new_nextspan = relptr_access(base,
+ heap->spans[SB_FULLNESS_CLASSES - 2]);
+ relptr_store(base, new_nextspan->prevspan, span);
+ relptr_copy(heap->spans[SB_FULLNESS_CLASSES - 2],
+ new_nextspan->prevspan);
+ }
+ else if (span->nallocatable == span->nmax)
+ {
+ /*
+ * XXX. Deallocate the span; and if that causes the span of spans
+ * to need deallocation, do that, too.
+ */
+ }
+
+ /* If we locked the heap, release the lock. */
+ if (lock != NULL)
+ LWLockRelease(lock);
+}
+
/*
* Free all memory used by an allocator.
*
if (size_class == SB_SCLASS_SPAN_OF_SPANS)
nmax = FPM_PAGE_SIZE / obsize;
else
- nmax = (FPM_PAGE_SIZE * SB_PAGES_PER_SUPERBLOCK) / obsize;
+ nmax = SB_SUPERBLOCK_SIZE / obsize;
/*
* If fullness class 1 is empty, try to find something to put in it by
relptr_copy(prevspan->nextspan, span->nextspan);
else
relptr_copy(heap->spans[fclass], span->nextspan);
+ span->fclass = tfclass;
}
/* Advance to next span on list. */
if (size_class == SB_SCLASS_SPAN_OF_SPANS)
span->nallocatable = FPM_PAGE_SIZE / obsize;
else if (size_class != SB_SCLASS_SPAN_LARGE)
- span->nallocatable = (FPM_PAGE_SIZE * SB_PAGES_PER_SUPERBLOCK) / obsize;
+ span->nallocatable = SB_SUPERBLOCK_SIZE / obsize;
span->firstfree = SB_SPAN_NOTHING_FREE;
+ span->nmax = span->nallocatable;
+ span->fclass = 1;
}
/*
nextspan = relptr_access(base, span->nextspan);
if (nextspan != NULL)
relptr_store(base, nextspan->prevspan, span);
+ span->fclass = toclass;
return true;
}