#include "storage/smgr.h"
#include "tcop/tcopprot.h"
#include "utils/rel.h"
-#include "utils/balloc.h"
#include "utils/tuplesort.h"
{
_bt_buildadd(wstate, state, itup);
if (should_free)
- BlockAllocatorFree(itup);
+ pfree(itup);
itup = tuplesort_getindextuple(btspool->sortstate,
true, &should_free);
}
{
_bt_buildadd(wstate, state, itup2);
if (should_free2)
- BlockAllocatorFree(itup2);
+ pfree(itup2);
itup2 = tuplesort_getindextuple(btspool2->sortstate,
true, &should_free2);
}
_bt_buildadd(wstate, state, itup);
if (should_free)
- BlockAllocatorFree(itup);
+ pfree(itup);
}
}
* Free memory allocated via BlockAllocatorAlloc.
*/
void
-BlockAllocatorFree(void *ptr)
+BlockAllocatorFree(AllocatorRegion *aregion, void *ptr)
{
- AllocatorRegion *region;
char *fpm_base;
char *base = NULL;
BlockAllocatorSpan *span;
uint16 size_class;
/* Locate the containing span. */
- region = LookupAllocatorRegion(ptr);
- fpm_base = fpm_segment_base(region->fpm);
+ fpm_base = fpm_segment_base(aregion->fpm);
pageno = fpm_pointer_to_page(fpm_base, ptr);
- span = BlockAllocatorMapGet(region->pagemap, pageno);
+ span = BlockAllocatorMapGet(aregion->pagemap, pageno);
/*
* If this is a shared-memory region, we might need locking. If so,
* lock the heap.
*/
- if (region->seg != NULL)
+ if (aregion->seg != NULL)
{
BlockAllocatorHeap *heap = relptr_access(fpm_base, span->parent);
base = fpm_base;
BlockAllocatorUnlinkSpan(base, heap, span);
first_page = fpm_pointer_to_page(fpm_base,
relptr_access(base, span->start));
- FreePageManagerPut(region->fpm, first_page, span->npages);
- BlockAllocatorFree(span);
+ FreePageManagerPut(aregion->fpm, first_page, span->npages);
+ pfree(span);
/* We're done, but must release any lock first. */
if (lock != NULL)
BlockAllocatorUnlinkSpan(base, heap, span);
first_page = fpm_pointer_to_page(fpm_base,
relptr_access(base, span->start));
- FreePageManagerPut(region->fpm, first_page, span->npages);
+ FreePageManagerPut(aregion->fpm, first_page, span->npages);
/*
* Span-of-spans blocks store the span which describes them
* type, we need to separately free the span object also.
*/
if (size_class != BA_SCLASS_BLOCK_OF_SPANS)
- BlockAllocatorFree(span);
+ pfree(span);
}
/* If we locked the heap, release the lock. */
return balloc_size_classes[size_class];
}
+/*
+ * Given a pointer, and the AllocatorRegion which contains it, find the
+ * memory context.
+ */
+MemoryContext
+BlockAllocatorGetChunkContext(AllocatorRegion *aregion, void *ptr)
+{
+ char *fpm_base;
+ BlockAllocatorSpan *span;
+ BlockAllocatorHeap *heap;
+ BlockAllocatorHeap *heap0;
+ BlockAllocatorContext *context;
+ Size pageno;
+
+ /* Locate the containing block. */
+ fpm_base = fpm_segment_base(aregion->fpm);
+ pageno = fpm_pointer_to_page(fpm_base, ptr);
+ span = BlockAllocatorMapGet(aregion->pagemap, pageno);
+
+ /* Follow the parent poiner to find the containing heap. */
+ heap = relptr_access(fpm_base, span->parent);
+
+ /*
+ * Department of incredible ugliness: neither the heap nor the span
+ * actually contains a pointer to the context. However, we know which
+ * heap this has to be based on the size class. Hello, pointer
+ * arithmetic!
+ */
+ heap0 = heap - span->size_class;
+ context = (BlockAllocatorContext *)
+ (((char *) heap0) - offsetof(BlockAllocatorContext, heaps[0]));
+
+ Assert(IsA(context, BlockAllocatorContext));
+
+ return &context->header;
+}
+
/*
* Unneeded callback provided by the MemoryContext machinery.
*/
Assert(pointer != NULL);
Assert(pointer == (void *) MAXALIGN(pointer));
+ /*
+ * If allocator regions are in use, then this pointer might be within
+ * such a region, in which case it won't have a chunk header. So, we have
+ * to test for and handle that case first.
+ */
+ if (aregion_private_pages_allocated > 0)
+ {
+ AllocatorRegion *aregion;
+
+ aregion = LookupAllocatorRegion(pointer);
+ if (aregion != NULL)
+ return BlockAllocatorGetChunkContext(aregion, pointer);
+ }
+
/*
* OK, it's probably safe to look at the chunk header.
*/
if (pointer == NULL || pointer != (void *) MAXALIGN(pointer))
return false;
+ /*
+ * If allocator regions are in use, then this pointer might be within
+ * such a region, in which case it won't have a chunk header. So, we have
+ * to test for and handle that case first.
+ */
+ if (aregion_private_pages_allocated > 0)
+ {
+ AllocatorRegion *aregion;
+
+ aregion = LookupAllocatorRegion(pointer);
+ if (aregion != NULL)
+ return BlockAllocatorGetChunkContext(aregion, pointer) == context;
+ }
+
/*
* OK, it's probably safe to look at the chunk header.
*/
Assert(pointer != NULL);
Assert(pointer == (void *) MAXALIGN(pointer));
+ /*
+ * If allocator regions are in use, then this pointer might be within
+ * such a region, in which case it won't have a chunk header. So, we have
+ * to test for and handle that case first.
+ */
+ if (aregion_private_pages_allocated > 0)
+ {
+ AllocatorRegion *aregion;
+
+ aregion = LookupAllocatorRegion(pointer);
+ if (aregion != NULL)
+ {
+ BlockAllocatorFree(aregion, pointer);
+ return;
+ }
+ }
+
/*
* OK, it's probably safe to look at the chunk header.
*/
#define BALLOC_H
#include "storage/lwlock.h"
-#include "utils/relptr.h"
struct AllocatorRegion;
typedef struct BlockAllocatorContext BlockAllocatorContext;
/* MemoryContetMethods for block allocator */
extern void *BlockAllocatorAlloc(MemoryContext, Size);
-extern void BlockAllocatorFree(void *ptr); /* WRONG SIGNATURE */
+extern void BlockAllocatorFree(struct AllocatorRegion *, void *ptr);
/* REALLOC IS MISSING! */
extern void BlockAllocatorInit(MemoryContext);
extern void BlockAllocatorReset(MemoryContext);
extern void BlockAllocatorDelete(MemoryContext);
extern Size BlockAllocatorGetChunkSpace(struct AllocatorRegion *, void *ptr);
extern Size BlockAllocatorGetAllocSpace(Size size); /* EXTRA FUNCTION */
+extern MemoryContext BlockAllocatorGetChunkContext(struct AllocatorRegion *,
+ void *ptr);
/* IS_EMPTY IS MISSING! */
/* STATS IS MISSING! */
/* CHECK IS MISSING */