From bc862338e099ff8f3b580df32b42614b0dc9b615 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Wed, 4 Jun 2014 15:04:04 -0400 Subject: [PATCH] More MemoryContext integration. --- src/backend/access/nbtree/nbtsort.c | 7 ++-- src/backend/utils/mmgr/balloc.c | 55 +++++++++++++++++++++++------ src/backend/utils/mmgr/mcxt.c | 45 +++++++++++++++++++++++ src/backend/utils/sort/tuplesort.c | 2 +- src/include/utils/balloc.h | 5 +-- 5 files changed, 97 insertions(+), 17 deletions(-) diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index be5e46d29c..048b215118 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -72,7 +72,6 @@ #include "storage/smgr.h" #include "tcop/tcopprot.h" #include "utils/rel.h" -#include "utils/balloc.h" #include "utils/tuplesort.h" @@ -770,7 +769,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2) { _bt_buildadd(wstate, state, itup); if (should_free) - BlockAllocatorFree(itup); + pfree(itup); itup = tuplesort_getindextuple(btspool->sortstate, true, &should_free); } @@ -778,7 +777,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2) { _bt_buildadd(wstate, state, itup2); if (should_free2) - BlockAllocatorFree(itup2); + pfree(itup2); itup2 = tuplesort_getindextuple(btspool2->sortstate, true, &should_free2); } @@ -797,7 +796,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2) _bt_buildadd(wstate, state, itup); if (should_free) - BlockAllocatorFree(itup); + pfree(itup); } } diff --git a/src/backend/utils/mmgr/balloc.c b/src/backend/utils/mmgr/balloc.c index 2c54cb9b30..2fc256df60 100644 --- a/src/backend/utils/mmgr/balloc.c +++ b/src/backend/utils/mmgr/balloc.c @@ -359,9 +359,8 @@ BlockAllocatorAlloc(MemoryContext context, Size size) * Free memory allocated via BlockAllocatorAlloc. */ void -BlockAllocatorFree(void *ptr) +BlockAllocatorFree(AllocatorRegion *aregion, void *ptr) { - AllocatorRegion *region; char *fpm_base; char *base = NULL; BlockAllocatorSpan *span; @@ -372,16 +371,15 @@ BlockAllocatorFree(void *ptr) 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; @@ -403,8 +401,8 @@ BlockAllocatorFree(void *ptr) 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) @@ -458,7 +456,7 @@ BlockAllocatorFree(void *ptr) 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 @@ -467,7 +465,7 @@ BlockAllocatorFree(void *ptr) * 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. */ @@ -559,6 +557,43 @@ BlockAllocatorGetChunkSpace(AllocatorRegion *aregion, void *ptr) 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. */ diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index 7b1cc74a46..0835dd9246 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -389,6 +389,20 @@ GetMemoryChunkContext(void *pointer) 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. */ @@ -500,6 +514,20 @@ MemoryContextContains(MemoryContext context, void *pointer) 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. */ @@ -758,6 +786,23 @@ pfree(void *pointer) 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. */ diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index ad88d1a8e1..d4e9591ac9 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -3378,7 +3378,7 @@ writetup_index(Tuplesortstate *state, int tapenum, SortTuple *stup) (void *) &tuplen, sizeof(tuplen)); FREEMEM(state, GetMemoryChunkSpace(tuple)); - BlockAllocatorFree(tuple); + pfree(tuple); } static void diff --git a/src/include/utils/balloc.h b/src/include/utils/balloc.h index 7758b778ea..7845a1e28a 100644 --- a/src/include/utils/balloc.h +++ b/src/include/utils/balloc.h @@ -15,7 +15,6 @@ #define BALLOC_H #include "storage/lwlock.h" -#include "utils/relptr.h" struct AllocatorRegion; typedef struct BlockAllocatorContext BlockAllocatorContext; @@ -29,13 +28,15 @@ extern MemoryContext BlockAllocatorContextCreate(MemoryContext parent, /* 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 */ -- 2.39.5