From: Robert Haas Date: Tue, 13 May 2014 16:02:40 +0000 (-0400) Subject: Partially integrate with MemoryContext stuff. X-Git-Url: http://waps.l3s.uni-hannover.de/gitweb/?a=commitdiff_plain;h=42ac64fa73625ff53ca66ec71cff0def685fb232;p=users%2Frhaas%2Fpostgres.git Partially integrate with MemoryContext stuff. --- diff --git a/src/backend/utils/mmgr/balloc.c b/src/backend/utils/mmgr/balloc.c index f501791cab..16e5763210 100644 --- a/src/backend/utils/mmgr/balloc.c +++ b/src/backend/utils/mmgr/balloc.c @@ -36,6 +36,7 @@ #include "miscadmin.h" #include "nodes/memnodes.h" #include "utils/aregion.h" +#include "utils/memutils.h" typedef struct BlockAllocatorHeap BlockAllocatorHeap; typedef struct BlockAllocatorSpan BlockAllocatorSpan; @@ -182,11 +183,29 @@ static bool BlockAllocatorTransferFirstSpan(char *base, 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; @@ -194,9 +213,13 @@ BlockAllocatorContextCreate(void) 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), @@ -213,20 +236,22 @@ BlockAllocatorContextCreate(void) (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); /* @@ -236,9 +261,9 @@ BlockAllocatorAlloc(BlockAllocatorContext *context, Size size) * 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; @@ -250,17 +275,17 @@ BlockAllocatorAlloc(BlockAllocatorContext *context, Size size) 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; } @@ -273,7 +298,7 @@ BlockAllocatorAlloc(BlockAllocatorContext *context, Size size) !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); @@ -324,9 +349,9 @@ BlockAllocatorAlloc(BlockAllocatorContext *context, Size size) 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; } @@ -536,14 +561,24 @@ BlockAllocatorGetChunkSpace(void *ptr) 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; @@ -551,7 +586,7 @@ BlockAllocatorReset(BlockAllocatorContext *context) * 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) @@ -565,7 +600,7 @@ BlockAllocatorReset(BlockAllocatorContext *context) */ 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) @@ -594,6 +629,17 @@ BlockAllocatorReset(BlockAllocatorContext *context) } } +/* + * 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. diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 83bb97502b..f3200fb33d 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -217,7 +217,7 @@ struct Tuplesortstate int maxTapes; /* number of tapes (Knuth's T) */ int tapeRange; /* maxTapes-1 (Knuth's P) */ MemoryContext sortcontext; /* memory context holding all sort data */ - BlockAllocatorContext *sortallocator; /* block allocator for sort data */ + MemoryContext sortallocator; /* block allocator for sort data */ LogicalTapeSet *tapeset; /* logtape.c object for tapes in a temp file */ /* @@ -730,7 +730,8 @@ tuplesort_begin_index_btree(Relation heapRel, { Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess); MemoryContext oldcontext; - state->sortallocator = BlockAllocatorContextCreate(); + state->sortallocator = BlockAllocatorContextCreate(CurrentMemoryContext, + "sort allocator"); oldcontext = MemoryContextSwitchTo(state->sortcontext); diff --git a/src/include/nodes/memnodes.h b/src/include/nodes/memnodes.h index ad77509b0c..db4fb7776b 100644 --- a/src/include/nodes/memnodes.h +++ b/src/include/nodes/memnodes.h @@ -21,10 +21,10 @@ * A logical context in which memory allocations occur. * * MemoryContext itself is an abstract type that can have multiple - * implementations, though for now we have only AllocSetContext. - * The function pointers in MemoryContextMethods define one specific - * implementation of MemoryContext --- they are a virtual function table - * in C++ terms. + * implementations. Currently, we have AllocSetContext and + * BlockAllocatorContext. The function pointers in MemoryContextMethods + * define one specific implementation of MemoryContext --- they are a virtual + * function table in C++ terms. * * Node types that are actual implementations of memory contexts must * begin with the same fields as MemoryContext. @@ -76,6 +76,7 @@ typedef struct MemoryContextData */ #define MemoryContextIsValid(context) \ ((context) != NULL && \ - (IsA((context), AllocSetContext))) + (IsA((context), AllocSetContext) || \ + IsA((context), BlockAllocatorContext))) #endif /* MEMNODES_H */ diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 7b0088fdb5..92e0871686 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -246,6 +246,7 @@ typedef enum NodeTag */ T_MemoryContext = 600, T_AllocSetContext, + T_BlockAllocatorContext, /* * TAGS FOR VALUE NODES (value.h) diff --git a/src/include/utils/balloc.h b/src/include/utils/balloc.h index 4fadac2333..e970349a20 100644 --- a/src/include/utils/balloc.h +++ b/src/include/utils/balloc.h @@ -22,17 +22,21 @@ typedef struct BlockAllocatorContext BlockAllocatorContext; /* 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 */