Partially integrate with MemoryContext stuff.
authorRobert Haas <rhaas@postgresql.org>
Tue, 13 May 2014 16:02:40 +0000 (12:02 -0400)
committerRobert Haas <rhaas@postgresql.org>
Tue, 13 May 2014 16:02:40 +0000 (12:02 -0400)
src/backend/utils/mmgr/balloc.c
src/backend/utils/sort/tuplesort.c
src/include/nodes/memnodes.h
src/include/nodes/nodes.h
src/include/utils/balloc.h

index f501791caba1bc02cc7145e069fe6ad4a19b4b21..16e5763210495a22e24a72a012b571de7c6a51c2 100644 (file)
@@ -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.
index 83bb97502b56f38e4d2eb696b4c332bc1b979fe2..f3200fb33d186e7c27f126c10015d30793fb1b82 100644 (file)
@@ -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);
 
index ad77509b0ca23f02386d85320a043b6c53beb04a..db4fb7776b7810c9b04cfa857c63120e6495949a 100644 (file)
  *             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 */
index 7b0088fdb502d182825e84abaaceca88f6f6f19e..92e08716865036d1694d051b187c0a90e7e99469 100644 (file)
@@ -246,6 +246,7 @@ typedef enum NodeTag
         */
        T_MemoryContext = 600,
        T_AllocSetContext,
+       T_BlockAllocatorContext,
 
        /*
         * TAGS FOR VALUE NODES (value.h)
index 4fadac2333cd93308dcd53877d39e488a1b7ad62..e970349a2037c4fdd9795795c22231c2f28f5909 100644 (file)
@@ -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 */