#include "miscadmin.h"
#include "nodes/memnodes.h"
#include "utils/aregion.h"
+#include "utils/memutils.h"
typedef struct BlockAllocatorHeap BlockAllocatorHeap;
typedef struct BlockAllocatorSpan BlockAllocatorSpan;
static void BlockAllocatorUnlinkSpan(char *base, BlockAllocatorHeap *heap,
BlockAllocatorSpan *span);
+/*
+ * This is the virtual function table for BlockAllocatorContext.
+ */
+static MemoryContextMethods BlockAllocatorMethods = {
+ BlockAllocatorAlloc,
+ NULL, /* XXX BlockAllocatorFree, */
+ NULL, /* XXX BlockAllocatorRealloc, */
+ BlockAllocatorInit,
+ BlockAllocatorReset,
+ BlockAllocatorDelete,
+ NULL, /* XXX BlockAllocatorGetChunkSpace, */
+ NULL, /* XXX BlockAllocatorIsEmpty, */
+ NULL /* XXX BlockAllocatorStats */
+#ifdef MEMORY_CONTEXT_CHECKING
+ ,NULL /* XXX BlockAllocatorCheck */
+#endif
+};
+
/*
* Create a backend-private allocator.
*/
-BlockAllocatorContext *
-BlockAllocatorContextCreate(void)
+MemoryContext
+BlockAllocatorContextCreate(MemoryContext parent, const char *name)
{
Size allocator_size;
int heapno;
BlockAllocatorContext *context;
char *base = NULL;
- allocator_size = offsetof(BlockAllocatorContext, heaps);
- allocator_size += sizeof(BlockAllocatorHeap) * BA_NUM_SIZE_CLASSES;
- context = malloc(allocator_size);
+ allocator_size = sizeof(BlockAllocatorContext);
+ context = (BlockAllocatorContext *)
+ MemoryContextCreate(T_BlockAllocatorContext,
+ sizeof(BlockAllocatorContext),
+ &BlockAllocatorMethods,
+ parent,
+ name);
if (context == NULL)
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
(BlockAllocatorSpan *) NULL);
}
- return context;
+ return (MemoryContext) context;
}
/*
* Allocate memory.
*/
void *
-BlockAllocatorAlloc(BlockAllocatorContext *context, Size size)
+BlockAllocatorAlloc(MemoryContext context, Size size)
{
+ BlockAllocatorContext *bcontext = (BlockAllocatorContext *) context;
AllocatorRegion *region = NULL;
char *base = NULL;
uint16 size_class;
char *result;
+ Assert(IsA(bcontext, BlockAllocatorContext));
Assert(size > 0);
/*
* a region; we'll only need to grab a region if we can't allocate out of
* an existing block.
*/
- if (!context->private)
+ if (!bcontext->private)
{
- region = LookupAllocatorRegion(context);
+ region = LookupAllocatorRegion(bcontext);
if (region == NULL)
elog(ERROR, "AllocatorRegion not found");
base = region->region_start;
Size npages = fpm_size_to_pages(size);
Size first_page;
BlockAllocatorSpan *span;
- BlockAllocatorHeap *heap = &context->heaps[BA_SCLASS_SPAN_LARGE];
+ BlockAllocatorHeap *heap = &bcontext->heaps[BA_SCLASS_SPAN_LARGE];
LWLock *lock = relptr_access(base, heap->lock);
void *ptr;
/* Obtain a span object. */
span = (BlockAllocatorSpan *)
- BlockAllocatorAllocGuts(base, region, context,
+ BlockAllocatorAllocGuts(base, region, bcontext,
BA_SCLASS_BLOCK_OF_SPANS);
if (span == NULL)
{
- BlockAllocatorMemoryError(context);
+ BlockAllocatorMemoryError(bcontext);
return NULL;
}
!FreePageManagerGet(region->fpm, npages, &first_page))
{
/* XXX. Free the span. */
- BlockAllocatorMemoryError(context);
+ BlockAllocatorMemoryError(bcontext);
return NULL;
}
ptr = fpm_page_to_pointer(fpm_segment_base(region->fpm), first_page);
Assert(size_class == 0 || size > balloc_size_classes[size_class - 1]);
/* Attempt the actual allocation. */
- result = BlockAllocatorAllocGuts(base, region, context, size_class);
+ result = BlockAllocatorAllocGuts(base, region, bcontext, size_class);
if (result == NULL)
- BlockAllocatorMemoryError(context);
+ BlockAllocatorMemoryError(bcontext);
return result;
}
return balloc_size_classes[size_class];
}
+/*
+ * Unneeded callback provided by the MemoryContext machinery.
+ */
+void
+BlockAllocatorInit(MemoryContext context)
+{
+ /* Nothing to do. */
+}
+
/*
* Free all memory used by an allocator.
*
* NB: It's not safe to do this while the allocator is in use!
*/
void
-BlockAllocatorReset(BlockAllocatorContext *context)
+BlockAllocatorReset(MemoryContext context)
{
+ BlockAllocatorContext *bcontext = (BlockAllocatorContext *) context;
char *base = NULL;
int heapno;
* For shared memory allocation, pointers are relative to the start of the
* region.
*/
- if (!context->private)
+ if (!bcontext->private)
{
AllocatorRegion *region = LookupAllocatorRegion(context);
if (region == NULL)
*/
for (heapno = BA_NUM_SIZE_CLASSES - 1; heapno >= 0; --heapno)
{
- BlockAllocatorHeap *heap = &context->heaps[heapno];
+ BlockAllocatorHeap *heap = &bcontext->heaps[heapno];
int fclass;
for (fclass = 0; fclass < BA_FULLNESS_CLASSES; ++fclass)
}
}
+/*
+ * Prepare to delete a context.
+ */
+void
+BlockAllocatorDelete(MemoryContext context)
+{
+ /* Currently, we don't need to do anything except reset the context. */
+ Assert(IsA(context, BlockAllocatorContext));
+ BlockAllocatorReset(context);
+}
+
/*
* Allocate an object of the requested size class from the given allocator.
* If necessary, steal or create another block.
/* Number of pages (see FPM_PAGE_SIZE) per block-allocator chunk. */
#define BLOCK_ALLOCATOR_PAGES_PER_CHUNK 16
-/* Functions to manipulate allocators. */
-extern BlockAllocatorContext *BlockAllocatorContextCreate(void);
-extern void BlockAllocatorReset(BlockAllocatorContext *);
-extern void BlockAllocatorDelete(BlockAllocatorContext *);
-
-/* Functions to allocate and free memory. */
-extern void *BlockAllocatorAlloc(BlockAllocatorContext *, Size);
-extern void BlockAllocatorFree(void *ptr);
-
-/* Reporting functions. */
-extern Size BlockAllocatorGetAllocSpace(Size size);
-extern Size BlockAllocatorGetChunkSpace(void *ptr);
+/* Create a new BlockAllocatorContext. */
+extern MemoryContext BlockAllocatorContextCreate(MemoryContext parent,
+ const char *name);
+
+/* MemoryContetMethods for block allocator */
+extern void *BlockAllocatorAlloc(MemoryContext, Size);
+extern void BlockAllocatorFree(void *ptr); /* WRONG SIGNATURE */
+/* REALLOC IS MISSING! */
+extern void BlockAllocatorInit(MemoryContext);
+extern void BlockAllocatorReset(MemoryContext);
+extern void BlockAllocatorDelete(MemoryContext);
+extern Size BlockAllocatorGetChunkSpace(void *ptr); /* WRONG SIGNATURE */
+extern Size BlockAllocatorGetAllocSpace(Size size); /* EXTRA FUNCTION */
+/* IS_EMPTY IS MISSING! */
+/* STATS IS MISSING! */
+/* CHECK IS MISSING */
#endif /* BALLOC_H */