LCOV - code coverage report
Current view: top level - src/backend/utils/mmgr - mcxt.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 260 322 80.7 %
Date: 2024-12-02 21:15:08 Functions: 43 52 82.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * mcxt.c
       4             :  *    POSTGRES memory context management code.
       5             :  *
       6             :  * This module handles context management operations that are independent
       7             :  * of the particular kind of context being operated on.  It calls
       8             :  * context-type-specific operations via the function pointers in a
       9             :  * context's MemoryContextMethods struct.
      10             :  *
      11             :  *
      12             :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
      13             :  * Portions Copyright (c) 1994, Regents of the University of California
      14             :  *
      15             :  *
      16             :  * IDENTIFICATION
      17             :  *    src/backend/utils/mmgr/mcxt.c
      18             :  *
      19             :  *-------------------------------------------------------------------------
      20             :  */
      21             : 
      22             : #include "postgres.h"
      23             : 
      24             : #include "mb/pg_wchar.h"
      25             : #include "miscadmin.h"
      26             : #include "utils/memdebug.h"
      27             : #include "utils/memutils.h"
      28             : #include "utils/memutils_internal.h"
      29             : #include "utils/memutils_memorychunk.h"
      30             : 
      31             : 
      32             : static void BogusFree(void *pointer);
      33             : static void *BogusRealloc(void *pointer, Size size, int flags);
      34             : static MemoryContext BogusGetChunkContext(void *pointer);
      35             : static Size BogusGetChunkSpace(void *pointer);
      36             : 
      37             : /*****************************************************************************
      38             :  *    GLOBAL MEMORY                                                          *
      39             :  *****************************************************************************/
      40             : #define BOGUS_MCTX(id) \
      41             :     [id].free_p = BogusFree, \
      42             :     [id].realloc = BogusRealloc, \
      43             :     [id].get_chunk_context = BogusGetChunkContext, \
      44             :     [id].get_chunk_space = BogusGetChunkSpace
      45             : 
      46             : static const MemoryContextMethods mcxt_methods[] = {
      47             :     /* aset.c */
      48             :     [MCTX_ASET_ID].alloc = AllocSetAlloc,
      49             :     [MCTX_ASET_ID].free_p = AllocSetFree,
      50             :     [MCTX_ASET_ID].realloc = AllocSetRealloc,
      51             :     [MCTX_ASET_ID].reset = AllocSetReset,
      52             :     [MCTX_ASET_ID].delete_context = AllocSetDelete,
      53             :     [MCTX_ASET_ID].get_chunk_context = AllocSetGetChunkContext,
      54             :     [MCTX_ASET_ID].get_chunk_space = AllocSetGetChunkSpace,
      55             :     [MCTX_ASET_ID].is_empty = AllocSetIsEmpty,
      56             :     [MCTX_ASET_ID].stats = AllocSetStats,
      57             : #ifdef MEMORY_CONTEXT_CHECKING
      58             :     [MCTX_ASET_ID].check = AllocSetCheck,
      59             : #endif
      60             : 
      61             :     /* generation.c */
      62             :     [MCTX_GENERATION_ID].alloc = GenerationAlloc,
      63             :     [MCTX_GENERATION_ID].free_p = GenerationFree,
      64             :     [MCTX_GENERATION_ID].realloc = GenerationRealloc,
      65             :     [MCTX_GENERATION_ID].reset = GenerationReset,
      66             :     [MCTX_GENERATION_ID].delete_context = GenerationDelete,
      67             :     [MCTX_GENERATION_ID].get_chunk_context = GenerationGetChunkContext,
      68             :     [MCTX_GENERATION_ID].get_chunk_space = GenerationGetChunkSpace,
      69             :     [MCTX_GENERATION_ID].is_empty = GenerationIsEmpty,
      70             :     [MCTX_GENERATION_ID].stats = GenerationStats,
      71             : #ifdef MEMORY_CONTEXT_CHECKING
      72             :     [MCTX_GENERATION_ID].check = GenerationCheck,
      73             : #endif
      74             : 
      75             :     /* slab.c */
      76             :     [MCTX_SLAB_ID].alloc = SlabAlloc,
      77             :     [MCTX_SLAB_ID].free_p = SlabFree,
      78             :     [MCTX_SLAB_ID].realloc = SlabRealloc,
      79             :     [MCTX_SLAB_ID].reset = SlabReset,
      80             :     [MCTX_SLAB_ID].delete_context = SlabDelete,
      81             :     [MCTX_SLAB_ID].get_chunk_context = SlabGetChunkContext,
      82             :     [MCTX_SLAB_ID].get_chunk_space = SlabGetChunkSpace,
      83             :     [MCTX_SLAB_ID].is_empty = SlabIsEmpty,
      84             :     [MCTX_SLAB_ID].stats = SlabStats,
      85             : #ifdef MEMORY_CONTEXT_CHECKING
      86             :     [MCTX_SLAB_ID].check = SlabCheck,
      87             : #endif
      88             : 
      89             :     /* alignedalloc.c */
      90             :     [MCTX_ALIGNED_REDIRECT_ID].alloc = NULL,    /* not required */
      91             :     [MCTX_ALIGNED_REDIRECT_ID].free_p = AlignedAllocFree,
      92             :     [MCTX_ALIGNED_REDIRECT_ID].realloc = AlignedAllocRealloc,
      93             :     [MCTX_ALIGNED_REDIRECT_ID].reset = NULL,    /* not required */
      94             :     [MCTX_ALIGNED_REDIRECT_ID].delete_context = NULL,   /* not required */
      95             :     [MCTX_ALIGNED_REDIRECT_ID].get_chunk_context = AlignedAllocGetChunkContext,
      96             :     [MCTX_ALIGNED_REDIRECT_ID].get_chunk_space = AlignedAllocGetChunkSpace,
      97             :     [MCTX_ALIGNED_REDIRECT_ID].is_empty = NULL, /* not required */
      98             :     [MCTX_ALIGNED_REDIRECT_ID].stats = NULL,    /* not required */
      99             : #ifdef MEMORY_CONTEXT_CHECKING
     100             :     [MCTX_ALIGNED_REDIRECT_ID].check = NULL,    /* not required */
     101             : #endif
     102             : 
     103             :     /* bump.c */
     104             :     [MCTX_BUMP_ID].alloc = BumpAlloc,
     105             :     [MCTX_BUMP_ID].free_p = BumpFree,
     106             :     [MCTX_BUMP_ID].realloc = BumpRealloc,
     107             :     [MCTX_BUMP_ID].reset = BumpReset,
     108             :     [MCTX_BUMP_ID].delete_context = BumpDelete,
     109             :     [MCTX_BUMP_ID].get_chunk_context = BumpGetChunkContext,
     110             :     [MCTX_BUMP_ID].get_chunk_space = BumpGetChunkSpace,
     111             :     [MCTX_BUMP_ID].is_empty = BumpIsEmpty,
     112             :     [MCTX_BUMP_ID].stats = BumpStats,
     113             : #ifdef MEMORY_CONTEXT_CHECKING
     114             :     [MCTX_BUMP_ID].check = BumpCheck,
     115             : #endif
     116             : 
     117             : 
     118             :     /*
     119             :      * Reserved and unused IDs should have dummy entries here.  This allows us
     120             :      * to fail cleanly if a bogus pointer is passed to pfree or the like.  It
     121             :      * seems sufficient to provide routines for the methods that might get
     122             :      * invoked from inspection of a chunk (see MCXT_METHOD calls below).
     123             :      */
     124             :     BOGUS_MCTX(MCTX_1_RESERVED_GLIBC_ID),
     125             :     BOGUS_MCTX(MCTX_2_RESERVED_GLIBC_ID),
     126             :     BOGUS_MCTX(MCTX_8_UNUSED_ID),
     127             :     BOGUS_MCTX(MCTX_9_UNUSED_ID),
     128             :     BOGUS_MCTX(MCTX_10_UNUSED_ID),
     129             :     BOGUS_MCTX(MCTX_11_UNUSED_ID),
     130             :     BOGUS_MCTX(MCTX_12_UNUSED_ID),
     131             :     BOGUS_MCTX(MCTX_13_UNUSED_ID),
     132             :     BOGUS_MCTX(MCTX_14_UNUSED_ID),
     133             :     BOGUS_MCTX(MCTX_0_RESERVED_UNUSEDMEM_ID),
     134             :     BOGUS_MCTX(MCTX_15_RESERVED_WIPEDMEM_ID)
     135             : };
     136             : 
     137             : #undef BOGUS_MCTX
     138             : 
     139             : /*
     140             :  * CurrentMemoryContext
     141             :  *      Default memory context for allocations.
     142             :  */
     143             : MemoryContext CurrentMemoryContext = NULL;
     144             : 
     145             : /*
     146             :  * Standard top-level contexts. For a description of the purpose of each
     147             :  * of these contexts, refer to src/backend/utils/mmgr/README
     148             :  */
     149             : MemoryContext TopMemoryContext = NULL;
     150             : MemoryContext ErrorContext = NULL;
     151             : MemoryContext PostmasterContext = NULL;
     152             : MemoryContext CacheMemoryContext = NULL;
     153             : MemoryContext MessageContext = NULL;
     154             : MemoryContext TopTransactionContext = NULL;
     155             : MemoryContext CurTransactionContext = NULL;
     156             : 
     157             : /* This is a transient link to the active portal's memory context: */
     158             : MemoryContext PortalContext = NULL;
     159             : 
     160             : static void MemoryContextDeleteOnly(MemoryContext context);
     161             : static void MemoryContextCallResetCallbacks(MemoryContext context);
     162             : static void MemoryContextStatsInternal(MemoryContext context, int level,
     163             :                                        int max_level, int max_children,
     164             :                                        MemoryContextCounters *totals,
     165             :                                        bool print_to_stderr);
     166             : static void MemoryContextStatsPrint(MemoryContext context, void *passthru,
     167             :                                     const char *stats_string,
     168             :                                     bool print_to_stderr);
     169             : 
     170             : /*
     171             :  * You should not do memory allocations within a critical section, because
     172             :  * an out-of-memory error will be escalated to a PANIC. To enforce that
     173             :  * rule, the allocation functions Assert that.
     174             :  */
     175             : #define AssertNotInCriticalSection(context) \
     176             :     Assert(CritSectionCount == 0 || (context)->allowInCritSection)
     177             : 
     178             : /*
     179             :  * Call the given function in the MemoryContextMethods for the memory context
     180             :  * type that 'pointer' belongs to.
     181             :  */
     182             : #define MCXT_METHOD(pointer, method) \
     183             :     mcxt_methods[GetMemoryChunkMethodID(pointer)].method
     184             : 
     185             : /*
     186             :  * GetMemoryChunkMethodID
     187             :  *      Return the MemoryContextMethodID from the uint64 chunk header which
     188             :  *      directly precedes 'pointer'.
     189             :  */
     190             : static inline MemoryContextMethodID
     191   467828898 : GetMemoryChunkMethodID(const void *pointer)
     192             : {
     193             :     uint64      header;
     194             : 
     195             :     /*
     196             :      * Try to detect bogus pointers handed to us, poorly though we can.
     197             :      * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
     198             :      * allocated chunk.
     199             :      */
     200             :     Assert(pointer == (const void *) MAXALIGN(pointer));
     201             : 
     202             :     /* Allow access to the uint64 header */
     203             :     VALGRIND_MAKE_MEM_DEFINED((char *) pointer - sizeof(uint64), sizeof(uint64));
     204             : 
     205   467828898 :     header = *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
     206             : 
     207             :     /* Disallow access to the uint64 header */
     208             :     VALGRIND_MAKE_MEM_NOACCESS((char *) pointer - sizeof(uint64), sizeof(uint64));
     209             : 
     210   467828898 :     return (MemoryContextMethodID) (header & MEMORY_CONTEXT_METHODID_MASK);
     211             : }
     212             : 
     213             : /*
     214             :  * GetMemoryChunkHeader
     215             :  *      Return the uint64 chunk header which directly precedes 'pointer'.
     216             :  *
     217             :  * This is only used after GetMemoryChunkMethodID, so no need for error checks.
     218             :  */
     219             : static inline uint64
     220           0 : GetMemoryChunkHeader(const void *pointer)
     221             : {
     222             :     uint64      header;
     223             : 
     224             :     /* Allow access to the uint64 header */
     225             :     VALGRIND_MAKE_MEM_DEFINED((char *) pointer - sizeof(uint64), sizeof(uint64));
     226             : 
     227           0 :     header = *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
     228             : 
     229             :     /* Disallow access to the uint64 header */
     230             :     VALGRIND_MAKE_MEM_NOACCESS((char *) pointer - sizeof(uint64), sizeof(uint64));
     231             : 
     232           0 :     return header;
     233             : }
     234             : 
     235             : /*
     236             :  * MemoryContextTraverseNext
     237             :  *      Helper function to traverse all descendants of a memory context
     238             :  *      without recursion.
     239             :  *
     240             :  * Recursion could lead to out-of-stack errors with deep context hierarchies,
     241             :  * which would be unpleasant in error cleanup code paths.
     242             :  *
     243             :  * To process 'context' and all its descendants, use a loop like this:
     244             :  *
     245             :  *     <process 'context'>
     246             :  *     for (MemoryContext curr = context->firstchild;
     247             :  *          curr != NULL;
     248             :  *          curr = MemoryContextTraverseNext(curr, context))
     249             :  *     {
     250             :  *         <process 'curr'>
     251             :  *     }
     252             :  *
     253             :  * This visits all the contexts in pre-order, that is a node is visited
     254             :  * before its children.
     255             :  */
     256             : static MemoryContext
     257     3418710 : MemoryContextTraverseNext(MemoryContext curr, MemoryContext top)
     258             : {
     259             :     /* After processing a node, traverse to its first child if any */
     260     3418710 :     if (curr->firstchild != NULL)
     261           0 :         return curr->firstchild;
     262             : 
     263             :     /*
     264             :      * After processing a childless node, traverse to its next sibling if
     265             :      * there is one.  If there isn't, traverse back up to the parent (which
     266             :      * has already been visited, and now so have all its descendants).  We're
     267             :      * done if that is "top", otherwise traverse to its next sibling if any,
     268             :      * otherwise repeat moving up.
     269             :      */
     270     3418710 :     while (curr->nextchild == NULL)
     271             :     {
     272      915584 :         curr = curr->parent;
     273      915584 :         if (curr == top)
     274      915584 :             return NULL;
     275             :     }
     276     2503126 :     return curr->nextchild;
     277             : }
     278             : 
     279             : /*
     280             :  * Support routines to trap use of invalid memory context method IDs
     281             :  * (from calling pfree or the like on a bogus pointer).  As a possible
     282             :  * aid in debugging, we report the header word along with the pointer
     283             :  * address (if we got here, there must be an accessible header word).
     284             :  */
     285             : static void
     286           0 : BogusFree(void *pointer)
     287             : {
     288           0 :     elog(ERROR, "pfree called with invalid pointer %p (header 0x%016llx)",
     289             :          pointer, (unsigned long long) GetMemoryChunkHeader(pointer));
     290             : }
     291             : 
     292             : static void *
     293           0 : BogusRealloc(void *pointer, Size size, int flags)
     294             : {
     295           0 :     elog(ERROR, "repalloc called with invalid pointer %p (header 0x%016llx)",
     296             :          pointer, (unsigned long long) GetMemoryChunkHeader(pointer));
     297             :     return NULL;                /* keep compiler quiet */
     298             : }
     299             : 
     300             : static MemoryContext
     301           0 : BogusGetChunkContext(void *pointer)
     302             : {
     303           0 :     elog(ERROR, "GetMemoryChunkContext called with invalid pointer %p (header 0x%016llx)",
     304             :          pointer, (unsigned long long) GetMemoryChunkHeader(pointer));
     305             :     return NULL;                /* keep compiler quiet */
     306             : }
     307             : 
     308             : static Size
     309           0 : BogusGetChunkSpace(void *pointer)
     310             : {
     311           0 :     elog(ERROR, "GetMemoryChunkSpace called with invalid pointer %p (header 0x%016llx)",
     312             :          pointer, (unsigned long long) GetMemoryChunkHeader(pointer));
     313             :     return 0;                   /* keep compiler quiet */
     314             : }
     315             : 
     316             : 
     317             : /*****************************************************************************
     318             :  *    EXPORTED ROUTINES                                                      *
     319             :  *****************************************************************************/
     320             : 
     321             : 
     322             : /*
     323             :  * MemoryContextInit
     324             :  *      Start up the memory-context subsystem.
     325             :  *
     326             :  * This must be called before creating contexts or allocating memory in
     327             :  * contexts.  TopMemoryContext and ErrorContext are initialized here;
     328             :  * other contexts must be created afterwards.
     329             :  *
     330             :  * In normal multi-backend operation, this is called once during
     331             :  * postmaster startup, and not at all by individual backend startup
     332             :  * (since the backends inherit an already-initialized context subsystem
     333             :  * by virtue of being forked off the postmaster).  But in an EXEC_BACKEND
     334             :  * build, each process must do this for itself.
     335             :  *
     336             :  * In a standalone backend this must be called during backend startup.
     337             :  */
     338             : void
     339        3280 : MemoryContextInit(void)
     340             : {
     341             :     Assert(TopMemoryContext == NULL);
     342             : 
     343             :     /*
     344             :      * First, initialize TopMemoryContext, which is the parent of all others.
     345             :      */
     346        3280 :     TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
     347             :                                              "TopMemoryContext",
     348             :                                              ALLOCSET_DEFAULT_SIZES);
     349             : 
     350             :     /*
     351             :      * Not having any other place to point CurrentMemoryContext, make it point
     352             :      * to TopMemoryContext.  Caller should change this soon!
     353             :      */
     354        3280 :     CurrentMemoryContext = TopMemoryContext;
     355             : 
     356             :     /*
     357             :      * Initialize ErrorContext as an AllocSetContext with slow growth rate ---
     358             :      * we don't really expect much to be allocated in it. More to the point,
     359             :      * require it to contain at least 8K at all times. This is the only case
     360             :      * where retained memory in a context is *essential* --- we want to be
     361             :      * sure ErrorContext still has some memory even if we've run out
     362             :      * elsewhere! Also, allow allocations in ErrorContext within a critical
     363             :      * section. Otherwise a PANIC will cause an assertion failure in the error
     364             :      * reporting code, before printing out the real cause of the failure.
     365             :      *
     366             :      * This should be the last step in this function, as elog.c assumes memory
     367             :      * management works once ErrorContext is non-null.
     368             :      */
     369        3280 :     ErrorContext = AllocSetContextCreate(TopMemoryContext,
     370             :                                          "ErrorContext",
     371             :                                          8 * 1024,
     372             :                                          8 * 1024,
     373             :                                          8 * 1024);
     374        3280 :     MemoryContextAllowInCriticalSection(ErrorContext, true);
     375        3280 : }
     376             : 
     377             : /*
     378             :  * MemoryContextReset
     379             :  *      Release all space allocated within a context and delete all its
     380             :  *      descendant contexts (but not the named context itself).
     381             :  */
     382             : void
     383   294691872 : MemoryContextReset(MemoryContext context)
     384             : {
     385             :     Assert(MemoryContextIsValid(context));
     386             : 
     387             :     /* save a function call in common case where there are no children */
     388   294691872 :     if (context->firstchild != NULL)
     389      440412 :         MemoryContextDeleteChildren(context);
     390             : 
     391             :     /* save a function call if no pallocs since startup or last reset */
     392   294691872 :     if (!context->isReset)
     393    43097874 :         MemoryContextResetOnly(context);
     394   294691872 : }
     395             : 
     396             : /*
     397             :  * MemoryContextResetOnly
     398             :  *      Release all space allocated within a context.
     399             :  *      Nothing is done to the context's descendant contexts.
     400             :  */
     401             : void
     402    48485152 : MemoryContextResetOnly(MemoryContext context)
     403             : {
     404             :     Assert(MemoryContextIsValid(context));
     405             : 
     406             :     /* Nothing to do if no pallocs since startup or last reset */
     407    48485152 :     if (!context->isReset)
     408             :     {
     409    48483972 :         MemoryContextCallResetCallbacks(context);
     410             : 
     411             :         /*
     412             :          * If context->ident points into the context's memory, it will become
     413             :          * a dangling pointer.  We could prevent that by setting it to NULL
     414             :          * here, but that would break valid coding patterns that keep the
     415             :          * ident elsewhere, e.g. in a parent context.  So for now we assume
     416             :          * the programmer got it right.
     417             :          */
     418             : 
     419    48483972 :         context->methods->reset(context);
     420    48483972 :         context->isReset = true;
     421             :         VALGRIND_DESTROY_MEMPOOL(context);
     422             :         VALGRIND_CREATE_MEMPOOL(context, 0, false);
     423             :     }
     424    48485152 : }
     425             : 
     426             : /*
     427             :  * MemoryContextResetChildren
     428             :  *      Release all space allocated within a context's descendants,
     429             :  *      but don't delete the contexts themselves.  The named context
     430             :  *      itself is not touched.
     431             :  */
     432             : void
     433           0 : MemoryContextResetChildren(MemoryContext context)
     434             : {
     435             :     Assert(MemoryContextIsValid(context));
     436             : 
     437           0 :     for (MemoryContext curr = context->firstchild;
     438             :          curr != NULL;
     439           0 :          curr = MemoryContextTraverseNext(curr, context))
     440             :     {
     441           0 :         MemoryContextResetOnly(curr);
     442             :     }
     443           0 : }
     444             : 
     445             : /*
     446             :  * MemoryContextDelete
     447             :  *      Delete a context and its descendants, and release all space
     448             :  *      allocated therein.
     449             :  *
     450             :  * The type-specific delete routine removes all storage for the context,
     451             :  * but we have to deal with descendant nodes here.
     452             :  */
     453             : void
     454     8595172 : MemoryContextDelete(MemoryContext context)
     455             : {
     456             :     MemoryContext curr;
     457             : 
     458             :     Assert(MemoryContextIsValid(context));
     459             : 
     460             :     /*
     461             :      * Delete subcontexts from the bottom up.
     462             :      *
     463             :      * Note: Do not use recursion here.  A "stack depth limit exceeded" error
     464             :      * would be unpleasant if we're already in the process of cleaning up from
     465             :      * transaction abort.  We also cannot use MemoryContextTraverseNext() here
     466             :      * because we modify the tree as we go.
     467             :      */
     468     8595172 :     curr = context;
     469             :     for (;;)
     470     1338534 :     {
     471             :         MemoryContext parent;
     472             : 
     473             :         /* Descend down until we find a leaf context with no children */
     474    11272240 :         while (curr->firstchild != NULL)
     475     1338534 :             curr = curr->firstchild;
     476             : 
     477             :         /*
     478             :          * We're now at a leaf with no children. Free it and continue from the
     479             :          * parent.  Or if this was the original node, we're all done.
     480             :          */
     481     9933706 :         parent = curr->parent;
     482     9933706 :         MemoryContextDeleteOnly(curr);
     483             : 
     484     9933706 :         if (curr == context)
     485     8595172 :             break;
     486     1338534 :         curr = parent;
     487             :     }
     488     8595172 : }
     489             : 
     490             : /*
     491             :  * Subroutine of MemoryContextDelete,
     492             :  * to delete a context that has no children.
     493             :  * We must also delink the context from its parent, if it has one.
     494             :  */
     495             : static void
     496     9933706 : MemoryContextDeleteOnly(MemoryContext context)
     497             : {
     498             :     Assert(MemoryContextIsValid(context));
     499             :     /* We had better not be deleting TopMemoryContext ... */
     500             :     Assert(context != TopMemoryContext);
     501             :     /* And not CurrentMemoryContext, either */
     502             :     Assert(context != CurrentMemoryContext);
     503             :     /* All the children should've been deleted already */
     504             :     Assert(context->firstchild == NULL);
     505             : 
     506             :     /*
     507             :      * It's not entirely clear whether 'tis better to do this before or after
     508             :      * delinking the context; but an error in a callback will likely result in
     509             :      * leaking the whole context (if it's not a root context) if we do it
     510             :      * after, so let's do it before.
     511             :      */
     512     9933706 :     MemoryContextCallResetCallbacks(context);
     513             : 
     514             :     /*
     515             :      * We delink the context from its parent before deleting it, so that if
     516             :      * there's an error we won't have deleted/busted contexts still attached
     517             :      * to the context tree.  Better a leak than a crash.
     518             :      */
     519     9933706 :     MemoryContextSetParent(context, NULL);
     520             : 
     521             :     /*
     522             :      * Also reset the context's ident pointer, in case it points into the
     523             :      * context.  This would only matter if someone tries to get stats on the
     524             :      * (already unlinked) context, which is unlikely, but let's be safe.
     525             :      */
     526     9933706 :     context->ident = NULL;
     527             : 
     528     9933706 :     context->methods->delete_context(context);
     529             : 
     530             :     VALGRIND_DESTROY_MEMPOOL(context);
     531     9933706 : }
     532             : 
     533             : /*
     534             :  * MemoryContextDeleteChildren
     535             :  *      Delete all the descendants of the named context and release all
     536             :  *      space allocated therein.  The named context itself is not touched.
     537             :  */
     538             : void
     539      836002 : MemoryContextDeleteChildren(MemoryContext context)
     540             : {
     541             :     Assert(MemoryContextIsValid(context));
     542             : 
     543             :     /*
     544             :      * MemoryContextDelete will delink the child from me, so just iterate as
     545             :      * long as there is a child.
     546             :      */
     547     1343916 :     while (context->firstchild != NULL)
     548      507914 :         MemoryContextDelete(context->firstchild);
     549      836002 : }
     550             : 
     551             : /*
     552             :  * MemoryContextRegisterResetCallback
     553             :  *      Register a function to be called before next context reset/delete.
     554             :  *      Such callbacks will be called in reverse order of registration.
     555             :  *
     556             :  * The caller is responsible for allocating a MemoryContextCallback struct
     557             :  * to hold the info about this callback request, and for filling in the
     558             :  * "func" and "arg" fields in the struct to show what function to call with
     559             :  * what argument.  Typically the callback struct should be allocated within
     560             :  * the specified context, since that means it will automatically be freed
     561             :  * when no longer needed.
     562             :  *
     563             :  * There is no API for deregistering a callback once registered.  If you
     564             :  * want it to not do anything anymore, adjust the state pointed to by its
     565             :  * "arg" to indicate that.
     566             :  */
     567             : void
     568       43356 : MemoryContextRegisterResetCallback(MemoryContext context,
     569             :                                    MemoryContextCallback *cb)
     570             : {
     571             :     Assert(MemoryContextIsValid(context));
     572             : 
     573             :     /* Push onto head so this will be called before older registrants. */
     574       43356 :     cb->next = context->reset_cbs;
     575       43356 :     context->reset_cbs = cb;
     576             :     /* Mark the context as non-reset (it probably is already). */
     577       43356 :     context->isReset = false;
     578       43356 : }
     579             : 
     580             : /*
     581             :  * MemoryContextCallResetCallbacks
     582             :  *      Internal function to call all registered callbacks for context.
     583             :  */
     584             : static void
     585    58417678 : MemoryContextCallResetCallbacks(MemoryContext context)
     586             : {
     587             :     MemoryContextCallback *cb;
     588             : 
     589             :     /*
     590             :      * We pop each callback from the list before calling.  That way, if an
     591             :      * error occurs inside the callback, we won't try to call it a second time
     592             :      * in the likely event that we reset or delete the context later.
     593             :      */
     594    58461006 :     while ((cb = context->reset_cbs) != NULL)
     595             :     {
     596       43328 :         context->reset_cbs = cb->next;
     597       43328 :         cb->func(cb->arg);
     598             :     }
     599    58417678 : }
     600             : 
     601             : /*
     602             :  * MemoryContextSetIdentifier
     603             :  *      Set the identifier string for a memory context.
     604             :  *
     605             :  * An identifier can be provided to help distinguish among different contexts
     606             :  * of the same kind in memory context stats dumps.  The identifier string
     607             :  * must live at least as long as the context it is for; typically it is
     608             :  * allocated inside that context, so that it automatically goes away on
     609             :  * context deletion.  Pass id = NULL to forget any old identifier.
     610             :  */
     611             : void
     612     4222648 : MemoryContextSetIdentifier(MemoryContext context, const char *id)
     613             : {
     614             :     Assert(MemoryContextIsValid(context));
     615     4222648 :     context->ident = id;
     616     4222648 : }
     617             : 
     618             : /*
     619             :  * MemoryContextSetParent
     620             :  *      Change a context to belong to a new parent (or no parent).
     621             :  *
     622             :  * We provide this as an API function because it is sometimes useful to
     623             :  * change a context's lifespan after creation.  For example, a context
     624             :  * might be created underneath a transient context, filled with data,
     625             :  * and then reparented underneath CacheMemoryContext to make it long-lived.
     626             :  * In this way no special effort is needed to get rid of the context in case
     627             :  * a failure occurs before its contents are completely set up.
     628             :  *
     629             :  * Callers often assume that this function cannot fail, so don't put any
     630             :  * elog(ERROR) calls in it.
     631             :  *
     632             :  * A possible caller error is to reparent a context under itself, creating
     633             :  * a loop in the context graph.  We assert here that context != new_parent,
     634             :  * but checking for multi-level loops seems more trouble than it's worth.
     635             :  */
     636             : void
     637    10191808 : MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
     638             : {
     639             :     Assert(MemoryContextIsValid(context));
     640             :     Assert(context != new_parent);
     641             : 
     642             :     /* Fast path if it's got correct parent already */
     643    10191808 :     if (new_parent == context->parent)
     644        9526 :         return;
     645             : 
     646             :     /* Delink from existing parent, if any */
     647    10182282 :     if (context->parent)
     648             :     {
     649    10182282 :         MemoryContext parent = context->parent;
     650             : 
     651    10182282 :         if (context->prevchild != NULL)
     652      997896 :             context->prevchild->nextchild = context->nextchild;
     653             :         else
     654             :         {
     655             :             Assert(parent->firstchild == context);
     656     9184386 :             parent->firstchild = context->nextchild;
     657             :         }
     658             : 
     659    10182282 :         if (context->nextchild != NULL)
     660     4275832 :             context->nextchild->prevchild = context->prevchild;
     661             :     }
     662             : 
     663             :     /* And relink */
     664    10182282 :     if (new_parent)
     665             :     {
     666             :         Assert(MemoryContextIsValid(new_parent));
     667      248576 :         context->parent = new_parent;
     668      248576 :         context->prevchild = NULL;
     669      248576 :         context->nextchild = new_parent->firstchild;
     670      248576 :         if (new_parent->firstchild != NULL)
     671      226578 :             new_parent->firstchild->prevchild = context;
     672      248576 :         new_parent->firstchild = context;
     673             :     }
     674             :     else
     675             :     {
     676     9933706 :         context->parent = NULL;
     677     9933706 :         context->prevchild = NULL;
     678     9933706 :         context->nextchild = NULL;
     679             :     }
     680             : }
     681             : 
     682             : /*
     683             :  * MemoryContextAllowInCriticalSection
     684             :  *      Allow/disallow allocations in this memory context within a critical
     685             :  *      section.
     686             :  *
     687             :  * Normally, memory allocations are not allowed within a critical section,
     688             :  * because a failure would lead to PANIC.  There are a few exceptions to
     689             :  * that, like allocations related to debugging code that is not supposed to
     690             :  * be enabled in production.  This function can be used to exempt specific
     691             :  * memory contexts from the assertion in palloc().
     692             :  */
     693             : void
     694        4372 : MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
     695             : {
     696             :     Assert(MemoryContextIsValid(context));
     697             : 
     698        4372 :     context->allowInCritSection = allow;
     699        4372 : }
     700             : 
     701             : /*
     702             :  * GetMemoryChunkContext
     703             :  *      Given a currently-allocated chunk, determine the MemoryContext that
     704             :  *      the chunk belongs to.
     705             :  */
     706             : MemoryContext
     707     3168498 : GetMemoryChunkContext(void *pointer)
     708             : {
     709     3168498 :     return MCXT_METHOD(pointer, get_chunk_context) (pointer);
     710             : }
     711             : 
     712             : /*
     713             :  * GetMemoryChunkSpace
     714             :  *      Given a currently-allocated chunk, determine the total space
     715             :  *      it occupies (including all memory-allocation overhead).
     716             :  *
     717             :  * This is useful for measuring the total space occupied by a set of
     718             :  * allocated chunks.
     719             :  */
     720             : Size
     721    36039492 : GetMemoryChunkSpace(void *pointer)
     722             : {
     723    36039492 :     return MCXT_METHOD(pointer, get_chunk_space) (pointer);
     724             : }
     725             : 
     726             : /*
     727             :  * MemoryContextGetParent
     728             :  *      Get the parent context (if any) of the specified context
     729             :  */
     730             : MemoryContext
     731       17254 : MemoryContextGetParent(MemoryContext context)
     732             : {
     733             :     Assert(MemoryContextIsValid(context));
     734             : 
     735       17254 :     return context->parent;
     736             : }
     737             : 
     738             : /*
     739             :  * MemoryContextIsEmpty
     740             :  *      Is a memory context empty of any allocated space?
     741             :  */
     742             : bool
     743       10714 : MemoryContextIsEmpty(MemoryContext context)
     744             : {
     745             :     Assert(MemoryContextIsValid(context));
     746             : 
     747             :     /*
     748             :      * For now, we consider a memory context nonempty if it has any children;
     749             :      * perhaps this should be changed later.
     750             :      */
     751       10714 :     if (context->firstchild != NULL)
     752           2 :         return false;
     753             :     /* Otherwise use the type-specific inquiry */
     754       10712 :     return context->methods->is_empty(context);
     755             : }
     756             : 
     757             : /*
     758             :  * Find the memory allocated to blocks for this memory context. If recurse is
     759             :  * true, also include children.
     760             :  */
     761             : Size
     762     1392556 : MemoryContextMemAllocated(MemoryContext context, bool recurse)
     763             : {
     764     1392556 :     Size        total = context->mem_allocated;
     765             : 
     766             :     Assert(MemoryContextIsValid(context));
     767             : 
     768     1392556 :     if (recurse)
     769             :     {
     770     4811266 :         for (MemoryContext curr = context->firstchild;
     771             :              curr != NULL;
     772     3418710 :              curr = MemoryContextTraverseNext(curr, context))
     773             :         {
     774     3418710 :             total += curr->mem_allocated;
     775             :         }
     776             :     }
     777             : 
     778     1392556 :     return total;
     779             : }
     780             : 
     781             : /*
     782             :  * Return the memory consumption statistics about the given context and its
     783             :  * children.
     784             :  */
     785             : void
     786          30 : MemoryContextMemConsumed(MemoryContext context,
     787             :                          MemoryContextCounters *consumed)
     788             : {
     789             :     Assert(MemoryContextIsValid(context));
     790             : 
     791          30 :     memset(consumed, 0, sizeof(*consumed));
     792             : 
     793             :     /* Examine the context itself */
     794          30 :     context->methods->stats(context, NULL, NULL, consumed, false);
     795             : 
     796             :     /* Examine children, using iteration not recursion */
     797          30 :     for (MemoryContext curr = context->firstchild;
     798             :          curr != NULL;
     799           0 :          curr = MemoryContextTraverseNext(curr, context))
     800             :     {
     801           0 :         curr->methods->stats(curr, NULL, NULL, consumed, false);
     802             :     }
     803          30 : }
     804             : 
     805             : /*
     806             :  * MemoryContextStats
     807             :  *      Print statistics about the named context and all its descendants.
     808             :  *
     809             :  * This is just a debugging utility, so it's not very fancy.  However, we do
     810             :  * make some effort to summarize when the output would otherwise be very long.
     811             :  * The statistics are sent to stderr.
     812             :  */
     813             : void
     814           0 : MemoryContextStats(MemoryContext context)
     815             : {
     816             :     /* Hard-wired limits are usually good enough */
     817           0 :     MemoryContextStatsDetail(context, 100, 100, true);
     818           0 : }
     819             : 
     820             : /*
     821             :  * MemoryContextStatsDetail
     822             :  *
     823             :  * Entry point for use if you want to vary the number of child contexts shown.
     824             :  *
     825             :  * If print_to_stderr is true, print statistics about the memory contexts
     826             :  * with fprintf(stderr), otherwise use ereport().
     827             :  */
     828             : void
     829          18 : MemoryContextStatsDetail(MemoryContext context,
     830             :                          int max_level, int max_children,
     831             :                          bool print_to_stderr)
     832             : {
     833             :     MemoryContextCounters grand_totals;
     834             : 
     835          18 :     memset(&grand_totals, 0, sizeof(grand_totals));
     836             : 
     837          18 :     MemoryContextStatsInternal(context, 0, max_level, max_children,
     838             :                                &grand_totals, print_to_stderr);
     839             : 
     840          18 :     if (print_to_stderr)
     841           0 :         fprintf(stderr,
     842             :                 "Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used\n",
     843             :                 grand_totals.totalspace, grand_totals.nblocks,
     844             :                 grand_totals.freespace, grand_totals.freechunks,
     845           0 :                 grand_totals.totalspace - grand_totals.freespace);
     846             :     else
     847             :     {
     848             :         /*
     849             :          * Use LOG_SERVER_ONLY to prevent the memory contexts from being sent
     850             :          * to the connected client.
     851             :          *
     852             :          * We don't buffer the information about all memory contexts in a
     853             :          * backend into StringInfo and log it as one message.  That would
     854             :          * require the buffer to be enlarged, risking an OOM as there could be
     855             :          * a large number of memory contexts in a backend.  Instead, we log
     856             :          * one message per memory context.
     857             :          */
     858          18 :         ereport(LOG_SERVER_ONLY,
     859             :                 (errhidestmt(true),
     860             :                  errhidecontext(true),
     861             :                  errmsg_internal("Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used",
     862             :                                  grand_totals.totalspace, grand_totals.nblocks,
     863             :                                  grand_totals.freespace, grand_totals.freechunks,
     864             :                                  grand_totals.totalspace - grand_totals.freespace)));
     865             :     }
     866          18 : }
     867             : 
     868             : /*
     869             :  * MemoryContextStatsInternal
     870             :  *      One recursion level for MemoryContextStats
     871             :  *
     872             :  * Print stats for this context if possible, but in any case accumulate counts
     873             :  * into *totals (if not NULL).
     874             :  */
     875             : static void
     876        1614 : MemoryContextStatsInternal(MemoryContext context, int level,
     877             :                            int max_level, int max_children,
     878             :                            MemoryContextCounters *totals,
     879             :                            bool print_to_stderr)
     880             : {
     881             :     MemoryContext child;
     882             :     int         ichild;
     883             : 
     884             :     Assert(MemoryContextIsValid(context));
     885             : 
     886             :     /* Examine the context itself */
     887        1614 :     context->methods->stats(context,
     888             :                             MemoryContextStatsPrint,
     889             :                             &level,
     890             :                             totals, print_to_stderr);
     891             : 
     892             :     /*
     893             :      * Examine children.
     894             :      *
     895             :      * If we are past the recursion depth limit or already running low on
     896             :      * stack, do not print them explicitly but just summarize them. Similarly,
     897             :      * if there are more than max_children of them, we do not print the rest
     898             :      * explicitly, but just summarize them.
     899             :      */
     900        1614 :     child = context->firstchild;
     901        1614 :     ichild = 0;
     902        1614 :     if (level < max_level && !stack_is_too_deep())
     903             :     {
     904        3210 :         for (; child != NULL && ichild < max_children;
     905        1596 :              child = child->nextchild, ichild++)
     906             :         {
     907        1596 :             MemoryContextStatsInternal(child, level + 1,
     908             :                                        max_level, max_children,
     909             :                                        totals,
     910             :                                        print_to_stderr);
     911             :         }
     912             :     }
     913             : 
     914        1614 :     if (child != NULL)
     915             :     {
     916             :         /* Summarize the rest of the children, avoiding recursion. */
     917             :         MemoryContextCounters local_totals;
     918             : 
     919           0 :         memset(&local_totals, 0, sizeof(local_totals));
     920             : 
     921           0 :         ichild = 0;
     922           0 :         while (child != NULL)
     923             :         {
     924           0 :             child->methods->stats(child, NULL, NULL, &local_totals, false);
     925           0 :             ichild++;
     926           0 :             child = MemoryContextTraverseNext(child, context);
     927             :         }
     928             : 
     929           0 :         if (print_to_stderr)
     930             :         {
     931           0 :             for (int i = 0; i <= level; i++)
     932           0 :                 fprintf(stderr, "  ");
     933           0 :             fprintf(stderr,
     934             :                     "%d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used\n",
     935             :                     ichild,
     936             :                     local_totals.totalspace,
     937             :                     local_totals.nblocks,
     938             :                     local_totals.freespace,
     939             :                     local_totals.freechunks,
     940           0 :                     local_totals.totalspace - local_totals.freespace);
     941             :         }
     942             :         else
     943           0 :             ereport(LOG_SERVER_ONLY,
     944             :                     (errhidestmt(true),
     945             :                      errhidecontext(true),
     946             :                      errmsg_internal("level: %d; %d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used",
     947             :                                      level,
     948             :                                      ichild,
     949             :                                      local_totals.totalspace,
     950             :                                      local_totals.nblocks,
     951             :                                      local_totals.freespace,
     952             :                                      local_totals.freechunks,
     953             :                                      local_totals.totalspace - local_totals.freespace)));
     954             : 
     955           0 :         if (totals)
     956             :         {
     957           0 :             totals->nblocks += local_totals.nblocks;
     958           0 :             totals->freechunks += local_totals.freechunks;
     959           0 :             totals->totalspace += local_totals.totalspace;
     960           0 :             totals->freespace += local_totals.freespace;
     961             :         }
     962             :     }
     963        1614 : }
     964             : 
     965             : /*
     966             :  * MemoryContextStatsPrint
     967             :  *      Print callback used by MemoryContextStatsInternal
     968             :  *
     969             :  * For now, the passthru pointer just points to "int level"; later we might
     970             :  * make that more complicated.
     971             :  */
     972             : static void
     973        1614 : MemoryContextStatsPrint(MemoryContext context, void *passthru,
     974             :                         const char *stats_string,
     975             :                         bool print_to_stderr)
     976             : {
     977        1614 :     int         level = *(int *) passthru;
     978        1614 :     const char *name = context->name;
     979        1614 :     const char *ident = context->ident;
     980             :     char        truncated_ident[110];
     981             :     int         i;
     982             : 
     983             :     /*
     984             :      * It seems preferable to label dynahash contexts with just the hash table
     985             :      * name.  Those are already unique enough, so the "dynahash" part isn't
     986             :      * very helpful, and this way is more consistent with pre-v11 practice.
     987             :      */
     988        1614 :     if (ident && strcmp(name, "dynahash") == 0)
     989             :     {
     990         210 :         name = ident;
     991         210 :         ident = NULL;
     992             :     }
     993             : 
     994        1614 :     truncated_ident[0] = '\0';
     995             : 
     996        1614 :     if (ident)
     997             :     {
     998             :         /*
     999             :          * Some contexts may have very long identifiers (e.g., SQL queries).
    1000             :          * Arbitrarily truncate at 100 bytes, but be careful not to break
    1001             :          * multibyte characters.  Also, replace ASCII control characters, such
    1002             :          * as newlines, with spaces.
    1003             :          */
    1004        1134 :         int         idlen = strlen(ident);
    1005        1134 :         bool        truncated = false;
    1006             : 
    1007        1134 :         strcpy(truncated_ident, ": ");
    1008        1134 :         i = strlen(truncated_ident);
    1009             : 
    1010        1134 :         if (idlen > 100)
    1011             :         {
    1012           0 :             idlen = pg_mbcliplen(ident, idlen, 100);
    1013           0 :             truncated = true;
    1014             :         }
    1015             : 
    1016       31590 :         while (idlen-- > 0)
    1017             :         {
    1018       30456 :             unsigned char c = *ident++;
    1019             : 
    1020       30456 :             if (c < ' ')
    1021           0 :                 c = ' ';
    1022       30456 :             truncated_ident[i++] = c;
    1023             :         }
    1024        1134 :         truncated_ident[i] = '\0';
    1025             : 
    1026        1134 :         if (truncated)
    1027           0 :             strcat(truncated_ident, "...");
    1028             :     }
    1029             : 
    1030        1614 :     if (print_to_stderr)
    1031             :     {
    1032           0 :         for (i = 0; i < level; i++)
    1033           0 :             fprintf(stderr, "  ");
    1034           0 :         fprintf(stderr, "%s: %s%s\n", name, stats_string, truncated_ident);
    1035             :     }
    1036             :     else
    1037        1614 :         ereport(LOG_SERVER_ONLY,
    1038             :                 (errhidestmt(true),
    1039             :                  errhidecontext(true),
    1040             :                  errmsg_internal("level: %d; %s: %s%s",
    1041             :                                  level, name, stats_string, truncated_ident)));
    1042        1614 : }
    1043             : 
    1044             : /*
    1045             :  * MemoryContextCheck
    1046             :  *      Check all chunks in the named context and its children.
    1047             :  *
    1048             :  * This is just a debugging utility, so it's not fancy.
    1049             :  */
    1050             : #ifdef MEMORY_CONTEXT_CHECKING
    1051             : void
    1052             : MemoryContextCheck(MemoryContext context)
    1053             : {
    1054             :     Assert(MemoryContextIsValid(context));
    1055             :     context->methods->check(context);
    1056             : 
    1057             :     for (MemoryContext curr = context->firstchild;
    1058             :          curr != NULL;
    1059             :          curr = MemoryContextTraverseNext(curr, context))
    1060             :     {
    1061             :         Assert(MemoryContextIsValid(curr));
    1062             :         curr->methods->check(curr);
    1063             :     }
    1064             : }
    1065             : #endif
    1066             : 
    1067             : /*
    1068             :  * MemoryContextCreate
    1069             :  *      Context-type-independent part of context creation.
    1070             :  *
    1071             :  * This is only intended to be called by context-type-specific
    1072             :  * context creation routines, not by the unwashed masses.
    1073             :  *
    1074             :  * The memory context creation procedure goes like this:
    1075             :  *  1.  Context-type-specific routine makes some initial space allocation,
    1076             :  *      including enough space for the context header.  If it fails,
    1077             :  *      it can ereport() with no damage done.
    1078             :  *  2.  Context-type-specific routine sets up all type-specific fields of
    1079             :  *      the header (those beyond MemoryContextData proper), as well as any
    1080             :  *      other management fields it needs to have a fully valid context.
    1081             :  *      Usually, failure in this step is impossible, but if it's possible
    1082             :  *      the initial space allocation should be freed before ereport'ing.
    1083             :  *  3.  Context-type-specific routine calls MemoryContextCreate() to fill in
    1084             :  *      the generic header fields and link the context into the context tree.
    1085             :  *  4.  We return to the context-type-specific routine, which finishes
    1086             :  *      up type-specific initialization.  This routine can now do things
    1087             :  *      that might fail (like allocate more memory), so long as it's
    1088             :  *      sure the node is left in a state that delete will handle.
    1089             :  *
    1090             :  * node: the as-yet-uninitialized common part of the context header node.
    1091             :  * tag: NodeTag code identifying the memory context type.
    1092             :  * method_id: MemoryContextMethodID of the context-type being created.
    1093             :  * parent: parent context, or NULL if this will be a top-level context.
    1094             :  * name: name of context (must be statically allocated).
    1095             :  *
    1096             :  * Context routines generally assume that MemoryContextCreate can't fail,
    1097             :  * so this can contain Assert but not elog/ereport.
    1098             :  */
    1099             : void
    1100    13115654 : MemoryContextCreate(MemoryContext node,
    1101             :                     NodeTag tag,
    1102             :                     MemoryContextMethodID method_id,
    1103             :                     MemoryContext parent,
    1104             :                     const char *name)
    1105             : {
    1106             :     /* Creating new memory contexts is not allowed in a critical section */
    1107             :     Assert(CritSectionCount == 0);
    1108             : 
    1109             :     /* Initialize all standard fields of memory context header */
    1110    13115654 :     node->type = tag;
    1111    13115654 :     node->isReset = true;
    1112    13115654 :     node->methods = &mcxt_methods[method_id];
    1113    13115654 :     node->parent = parent;
    1114    13115654 :     node->firstchild = NULL;
    1115    13115654 :     node->mem_allocated = 0;
    1116    13115654 :     node->prevchild = NULL;
    1117    13115654 :     node->name = name;
    1118    13115654 :     node->ident = NULL;
    1119    13115654 :     node->reset_cbs = NULL;
    1120             : 
    1121             :     /* OK to link node into context tree */
    1122    13115654 :     if (parent)
    1123             :     {
    1124    13112284 :         node->nextchild = parent->firstchild;
    1125    13112284 :         if (parent->firstchild != NULL)
    1126     7316650 :             parent->firstchild->prevchild = node;
    1127    13112284 :         parent->firstchild = node;
    1128             :         /* inherit allowInCritSection flag from parent */
    1129    13112284 :         node->allowInCritSection = parent->allowInCritSection;
    1130             :     }
    1131             :     else
    1132             :     {
    1133        3370 :         node->nextchild = NULL;
    1134        3370 :         node->allowInCritSection = false;
    1135             :     }
    1136             : 
    1137             :     VALGRIND_CREATE_MEMPOOL(node, 0, false);
    1138    13115654 : }
    1139             : 
    1140             : /*
    1141             :  * MemoryContextAllocationFailure
    1142             :  *      For use by MemoryContextMethods implementations to handle when malloc
    1143             :  *      returns NULL.  The behavior is specific to whether MCXT_ALLOC_NO_OOM
    1144             :  *      is in 'flags'.
    1145             :  */
    1146             : void *
    1147           0 : MemoryContextAllocationFailure(MemoryContext context, Size size, int flags)
    1148             : {
    1149           0 :     if ((flags & MCXT_ALLOC_NO_OOM) == 0)
    1150             :     {
    1151           0 :         if (TopMemoryContext)
    1152           0 :             MemoryContextStats(TopMemoryContext);
    1153           0 :         ereport(ERROR,
    1154             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
    1155             :                  errmsg("out of memory"),
    1156             :                  errdetail("Failed on request of size %zu in memory context \"%s\".",
    1157             :                            size, context->name)));
    1158             :     }
    1159           0 :     return NULL;
    1160             : }
    1161             : 
    1162             : /*
    1163             :  * MemoryContextSizeFailure
    1164             :  *      For use by MemoryContextMethods implementations to handle invalid
    1165             :  *      memory allocation request sizes.
    1166             :  */
    1167             : void
    1168           0 : MemoryContextSizeFailure(MemoryContext context, Size size, int flags)
    1169             : {
    1170           0 :     elog(ERROR, "invalid memory alloc request size %zu", size);
    1171             : }
    1172             : 
    1173             : /*
    1174             :  * MemoryContextAlloc
    1175             :  *      Allocate space within the specified context.
    1176             :  *
    1177             :  * This could be turned into a macro, but we'd have to import
    1178             :  * nodes/memnodes.h into postgres.h which seems a bad idea.
    1179             :  */
    1180             : void *
    1181   161898940 : MemoryContextAlloc(MemoryContext context, Size size)
    1182             : {
    1183             :     void       *ret;
    1184             : 
    1185             :     Assert(MemoryContextIsValid(context));
    1186             :     AssertNotInCriticalSection(context);
    1187             : 
    1188   161898940 :     context->isReset = false;
    1189             : 
    1190             :     /*
    1191             :      * For efficiency reasons, we purposefully offload the handling of
    1192             :      * allocation failures to the MemoryContextMethods implementation as this
    1193             :      * allows these checks to be performed only when an actual malloc needs to
    1194             :      * be done to request more memory from the OS.  Additionally, not having
    1195             :      * to execute any instructions after this call allows the compiler to use
    1196             :      * the sibling call optimization.  If you're considering adding code after
    1197             :      * this call, consider making it the responsibility of the 'alloc'
    1198             :      * function instead.
    1199             :      */
    1200   161898940 :     ret = context->methods->alloc(context, size, 0);
    1201             : 
    1202             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1203             : 
    1204   161898940 :     return ret;
    1205             : }
    1206             : 
    1207             : /*
    1208             :  * MemoryContextAllocZero
    1209             :  *      Like MemoryContextAlloc, but clears allocated memory
    1210             :  *
    1211             :  *  We could just call MemoryContextAlloc then clear the memory, but this
    1212             :  *  is a very common combination, so we provide the combined operation.
    1213             :  */
    1214             : void *
    1215    40493780 : MemoryContextAllocZero(MemoryContext context, Size size)
    1216             : {
    1217             :     void       *ret;
    1218             : 
    1219             :     Assert(MemoryContextIsValid(context));
    1220             :     AssertNotInCriticalSection(context);
    1221             : 
    1222    40493780 :     context->isReset = false;
    1223             : 
    1224    40493780 :     ret = context->methods->alloc(context, size, 0);
    1225             : 
    1226             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1227             : 
    1228   467736830 :     MemSetAligned(ret, 0, size);
    1229             : 
    1230    40493780 :     return ret;
    1231             : }
    1232             : 
    1233             : /*
    1234             :  * MemoryContextAllocExtended
    1235             :  *      Allocate space within the specified context using the given flags.
    1236             :  */
    1237             : void *
    1238     7170752 : MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
    1239             : {
    1240             :     void       *ret;
    1241             : 
    1242             :     Assert(MemoryContextIsValid(context));
    1243             :     AssertNotInCriticalSection(context);
    1244             : 
    1245     7170752 :     if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) :
    1246             :           AllocSizeIsValid(size)))
    1247           0 :         elog(ERROR, "invalid memory alloc request size %zu", size);
    1248             : 
    1249     7170752 :     context->isReset = false;
    1250             : 
    1251     7170752 :     ret = context->methods->alloc(context, size, flags);
    1252     7170752 :     if (unlikely(ret == NULL))
    1253           0 :         return NULL;
    1254             : 
    1255             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1256             : 
    1257     7170752 :     if ((flags & MCXT_ALLOC_ZERO) != 0)
    1258   194606144 :         MemSetAligned(ret, 0, size);
    1259             : 
    1260     7170752 :     return ret;
    1261             : }
    1262             : 
    1263             : /*
    1264             :  * HandleLogMemoryContextInterrupt
    1265             :  *      Handle receipt of an interrupt indicating logging of memory
    1266             :  *      contexts.
    1267             :  *
    1268             :  * All the actual work is deferred to ProcessLogMemoryContextInterrupt(),
    1269             :  * because we cannot safely emit a log message inside the signal handler.
    1270             :  */
    1271             : void
    1272          18 : HandleLogMemoryContextInterrupt(void)
    1273             : {
    1274          18 :     InterruptPending = true;
    1275          18 :     LogMemoryContextPending = true;
    1276             :     /* latch will be set by procsignal_sigusr1_handler */
    1277          18 : }
    1278             : 
    1279             : /*
    1280             :  * ProcessLogMemoryContextInterrupt
    1281             :  *      Perform logging of memory contexts of this backend process.
    1282             :  *
    1283             :  * Any backend that participates in ProcSignal signaling must arrange
    1284             :  * to call this function if we see LogMemoryContextPending set.
    1285             :  * It is called from CHECK_FOR_INTERRUPTS(), which is enough because
    1286             :  * the target process for logging of memory contexts is a backend.
    1287             :  */
    1288             : void
    1289          18 : ProcessLogMemoryContextInterrupt(void)
    1290             : {
    1291          18 :     LogMemoryContextPending = false;
    1292             : 
    1293             :     /*
    1294             :      * Use LOG_SERVER_ONLY to prevent this message from being sent to the
    1295             :      * connected client.
    1296             :      */
    1297          18 :     ereport(LOG_SERVER_ONLY,
    1298             :             (errhidestmt(true),
    1299             :              errhidecontext(true),
    1300             :              errmsg("logging memory contexts of PID %d", MyProcPid)));
    1301             : 
    1302             :     /*
    1303             :      * When a backend process is consuming huge memory, logging all its memory
    1304             :      * contexts might overrun available disk space. To prevent this, we limit
    1305             :      * the depth of the hierarchy, as well as the number of child contexts to
    1306             :      * log per parent to 100.
    1307             :      *
    1308             :      * As with MemoryContextStats(), we suppose that practical cases where the
    1309             :      * dump gets long will typically be huge numbers of siblings under the
    1310             :      * same parent context; while the additional debugging value from seeing
    1311             :      * details about individual siblings beyond 100 will not be large.
    1312             :      */
    1313          18 :     MemoryContextStatsDetail(TopMemoryContext, 100, 100, false);
    1314          18 : }
    1315             : 
    1316             : void *
    1317   567906348 : palloc(Size size)
    1318             : {
    1319             :     /* duplicates MemoryContextAlloc to avoid increased overhead */
    1320             :     void       *ret;
    1321   567906348 :     MemoryContext context = CurrentMemoryContext;
    1322             : 
    1323             :     Assert(MemoryContextIsValid(context));
    1324             :     AssertNotInCriticalSection(context);
    1325             : 
    1326   567906348 :     context->isReset = false;
    1327             : 
    1328             :     /*
    1329             :      * For efficiency reasons, we purposefully offload the handling of
    1330             :      * allocation failures to the MemoryContextMethods implementation as this
    1331             :      * allows these checks to be performed only when an actual malloc needs to
    1332             :      * be done to request more memory from the OS.  Additionally, not having
    1333             :      * to execute any instructions after this call allows the compiler to use
    1334             :      * the sibling call optimization.  If you're considering adding code after
    1335             :      * this call, consider making it the responsibility of the 'alloc'
    1336             :      * function instead.
    1337             :      */
    1338   567906348 :     ret = context->methods->alloc(context, size, 0);
    1339             :     /* We expect OOM to be handled by the alloc function */
    1340             :     Assert(ret != NULL);
    1341             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1342             : 
    1343   567906348 :     return ret;
    1344             : }
    1345             : 
    1346             : void *
    1347   428605544 : palloc0(Size size)
    1348             : {
    1349             :     /* duplicates MemoryContextAllocZero to avoid increased overhead */
    1350             :     void       *ret;
    1351   428605544 :     MemoryContext context = CurrentMemoryContext;
    1352             : 
    1353             :     Assert(MemoryContextIsValid(context));
    1354             :     AssertNotInCriticalSection(context);
    1355             : 
    1356   428605544 :     context->isReset = false;
    1357             : 
    1358   428605544 :     ret = context->methods->alloc(context, size, 0);
    1359             : 
    1360             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1361             : 
    1362  3841686666 :     MemSetAligned(ret, 0, size);
    1363             : 
    1364   428605544 :     return ret;
    1365             : }
    1366             : 
    1367             : void *
    1368    21039788 : palloc_extended(Size size, int flags)
    1369             : {
    1370             :     /* duplicates MemoryContextAllocExtended to avoid increased overhead */
    1371             :     void       *ret;
    1372    21039788 :     MemoryContext context = CurrentMemoryContext;
    1373             : 
    1374             :     Assert(MemoryContextIsValid(context));
    1375             :     AssertNotInCriticalSection(context);
    1376             : 
    1377    21039788 :     context->isReset = false;
    1378             : 
    1379    21039788 :     ret = context->methods->alloc(context, size, flags);
    1380    21039788 :     if (unlikely(ret == NULL))
    1381             :     {
    1382           0 :         return NULL;
    1383             :     }
    1384             : 
    1385             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1386             : 
    1387    21039788 :     if ((flags & MCXT_ALLOC_ZERO) != 0)
    1388        5072 :         MemSetAligned(ret, 0, size);
    1389             : 
    1390    21039788 :     return ret;
    1391             : }
    1392             : 
    1393             : /*
    1394             :  * MemoryContextAllocAligned
    1395             :  *      Allocate 'size' bytes of memory in 'context' aligned to 'alignto'
    1396             :  *      bytes.
    1397             :  *
    1398             :  * Currently, we align addresses by requesting additional bytes from the
    1399             :  * MemoryContext's standard allocator function and then aligning the returned
    1400             :  * address by the required alignment.  This means that the given MemoryContext
    1401             :  * must support providing us with a chunk of memory that's larger than 'size'.
    1402             :  * For allocators such as Slab, that's not going to work, as slab only allows
    1403             :  * chunks of the size that's specified when the context is created.
    1404             :  *
    1405             :  * 'alignto' must be a power of 2.
    1406             :  * 'flags' may be 0 or set the same as MemoryContextAllocExtended().
    1407             :  */
    1408             : void *
    1409     2987728 : MemoryContextAllocAligned(MemoryContext context,
    1410             :                           Size size, Size alignto, int flags)
    1411             : {
    1412             :     MemoryChunk *alignedchunk;
    1413             :     Size        alloc_size;
    1414             :     void       *unaligned;
    1415             :     void       *aligned;
    1416             : 
    1417             :     /* wouldn't make much sense to waste that much space */
    1418             :     Assert(alignto < (128 * 1024 * 1024));
    1419             : 
    1420             :     /* ensure alignto is a power of 2 */
    1421             :     Assert((alignto & (alignto - 1)) == 0);
    1422             : 
    1423             :     /*
    1424             :      * If the alignment requirements are less than what we already guarantee
    1425             :      * then just use the standard allocation function.
    1426             :      */
    1427     2987728 :     if (unlikely(alignto <= MAXIMUM_ALIGNOF))
    1428           0 :         return MemoryContextAllocExtended(context, size, flags);
    1429             : 
    1430             :     /*
    1431             :      * We implement aligned pointers by simply allocating enough memory for
    1432             :      * the requested size plus the alignment and an additional "redirection"
    1433             :      * MemoryChunk.  This additional MemoryChunk is required for operations
    1434             :      * such as pfree when used on the pointer returned by this function.  We
    1435             :      * use this redirection MemoryChunk in order to find the pointer to the
    1436             :      * memory that was returned by the MemoryContextAllocExtended call below.
    1437             :      * We do that by "borrowing" the block offset field and instead of using
    1438             :      * that to find the offset into the owning block, we use it to find the
    1439             :      * original allocated address.
    1440             :      *
    1441             :      * Here we must allocate enough extra memory so that we can still align
    1442             :      * the pointer returned by MemoryContextAllocExtended and also have enough
    1443             :      * space for the redirection MemoryChunk.  Since allocations will already
    1444             :      * be at least aligned by MAXIMUM_ALIGNOF, we can subtract that amount
    1445             :      * from the allocation size to save a little memory.
    1446             :      */
    1447     2987728 :     alloc_size = size + PallocAlignedExtraBytes(alignto);
    1448             : 
    1449             : #ifdef MEMORY_CONTEXT_CHECKING
    1450             :     /* ensure there's space for a sentinel byte */
    1451             :     alloc_size += 1;
    1452             : #endif
    1453             : 
    1454             :     /* perform the actual allocation */
    1455     2987728 :     unaligned = MemoryContextAllocExtended(context, alloc_size, flags);
    1456             : 
    1457             :     /* set the aligned pointer */
    1458     2987728 :     aligned = (void *) TYPEALIGN(alignto, (char *) unaligned +
    1459             :                                  sizeof(MemoryChunk));
    1460             : 
    1461     2987728 :     alignedchunk = PointerGetMemoryChunk(aligned);
    1462             : 
    1463             :     /*
    1464             :      * We set the redirect MemoryChunk so that the block offset calculation is
    1465             :      * used to point back to the 'unaligned' allocated chunk.  This allows us
    1466             :      * to use MemoryChunkGetBlock() to find the unaligned chunk when we need
    1467             :      * to perform operations such as pfree() and repalloc().
    1468             :      *
    1469             :      * We store 'alignto' in the MemoryChunk's 'value' so that we know what
    1470             :      * the alignment was set to should we ever be asked to realloc this
    1471             :      * pointer.
    1472             :      */
    1473     2987728 :     MemoryChunkSetHdrMask(alignedchunk, unaligned, alignto,
    1474             :                           MCTX_ALIGNED_REDIRECT_ID);
    1475             : 
    1476             :     /* double check we produced a correctly aligned pointer */
    1477             :     Assert((void *) TYPEALIGN(alignto, aligned) == aligned);
    1478             : 
    1479             : #ifdef MEMORY_CONTEXT_CHECKING
    1480             :     alignedchunk->requested_size = size;
    1481             :     /* set mark to catch clobber of "unused" space */
    1482             :     set_sentinel(aligned, size);
    1483             : #endif
    1484             : 
    1485             :     /* Mark the bytes before the redirection header as noaccess */
    1486             :     VALGRIND_MAKE_MEM_NOACCESS(unaligned,
    1487             :                                (char *) alignedchunk - (char *) unaligned);
    1488             : 
    1489             :     /* Disallow access to the redirection chunk header. */
    1490             :     VALGRIND_MAKE_MEM_NOACCESS(alignedchunk, sizeof(MemoryChunk));
    1491             : 
    1492     2987728 :     return aligned;
    1493             : }
    1494             : 
    1495             : /*
    1496             :  * palloc_aligned
    1497             :  *      Allocate 'size' bytes returning a pointer that's aligned to the
    1498             :  *      'alignto' boundary.
    1499             :  *
    1500             :  * Currently, we align addresses by requesting additional bytes from the
    1501             :  * MemoryContext's standard allocator function and then aligning the returned
    1502             :  * address by the required alignment.  This means that the given MemoryContext
    1503             :  * must support providing us with a chunk of memory that's larger than 'size'.
    1504             :  * For allocators such as Slab, that's not going to work, as slab only allows
    1505             :  * chunks of the size that's specified when the context is created.
    1506             :  *
    1507             :  * 'alignto' must be a power of 2.
    1508             :  * 'flags' may be 0 or set the same as MemoryContextAllocExtended().
    1509             :  */
    1510             : void *
    1511     2869584 : palloc_aligned(Size size, Size alignto, int flags)
    1512             : {
    1513     2869584 :     return MemoryContextAllocAligned(CurrentMemoryContext, size, alignto, flags);
    1514             : }
    1515             : 
    1516             : /*
    1517             :  * pfree
    1518             :  *      Release an allocated chunk.
    1519             :  */
    1520             : void
    1521   420357728 : pfree(void *pointer)
    1522             : {
    1523             : #ifdef USE_VALGRIND
    1524             :     MemoryContextMethodID method = GetMemoryChunkMethodID(pointer);
    1525             :     MemoryContext context = GetMemoryChunkContext(pointer);
    1526             : #endif
    1527             : 
    1528   420357728 :     MCXT_METHOD(pointer, free_p) (pointer);
    1529             : 
    1530             : #ifdef USE_VALGRIND
    1531             :     if (method != MCTX_ALIGNED_REDIRECT_ID)
    1532             :         VALGRIND_MEMPOOL_FREE(context, pointer);
    1533             : #endif
    1534   420357728 : }
    1535             : 
    1536             : /*
    1537             :  * repalloc
    1538             :  *      Adjust the size of a previously allocated chunk.
    1539             :  */
    1540             : void *
    1541     8176300 : repalloc(void *pointer, Size size)
    1542             : {
    1543             : #ifdef USE_VALGRIND
    1544             :     MemoryContextMethodID method = GetMemoryChunkMethodID(pointer);
    1545             : #endif
    1546             : #if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
    1547             :     MemoryContext context = GetMemoryChunkContext(pointer);
    1548             : #endif
    1549             :     void       *ret;
    1550             : 
    1551             :     AssertNotInCriticalSection(context);
    1552             : 
    1553             :     /* isReset must be false already */
    1554             :     Assert(!context->isReset);
    1555             : 
    1556             :     /*
    1557             :      * For efficiency reasons, we purposefully offload the handling of
    1558             :      * allocation failures to the MemoryContextMethods implementation as this
    1559             :      * allows these checks to be performed only when an actual malloc needs to
    1560             :      * be done to request more memory from the OS.  Additionally, not having
    1561             :      * to execute any instructions after this call allows the compiler to use
    1562             :      * the sibling call optimization.  If you're considering adding code after
    1563             :      * this call, consider making it the responsibility of the 'realloc'
    1564             :      * function instead.
    1565             :      */
    1566     8176300 :     ret = MCXT_METHOD(pointer, realloc) (pointer, size, 0);
    1567             : 
    1568             : #ifdef USE_VALGRIND
    1569             :     if (method != MCTX_ALIGNED_REDIRECT_ID)
    1570             :         VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
    1571             : #endif
    1572             : 
    1573     8176300 :     return ret;
    1574             : }
    1575             : 
    1576             : /*
    1577             :  * repalloc_extended
    1578             :  *      Adjust the size of a previously allocated chunk,
    1579             :  *      with HUGE and NO_OOM options.
    1580             :  */
    1581             : void *
    1582       86880 : repalloc_extended(void *pointer, Size size, int flags)
    1583             : {
    1584             : #if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
    1585             :     MemoryContext context = GetMemoryChunkContext(pointer);
    1586             : #endif
    1587             :     void       *ret;
    1588             : 
    1589             :     AssertNotInCriticalSection(context);
    1590             : 
    1591             :     /* isReset must be false already */
    1592             :     Assert(!context->isReset);
    1593             : 
    1594             :     /*
    1595             :      * For efficiency reasons, we purposefully offload the handling of
    1596             :      * allocation failures to the MemoryContextMethods implementation as this
    1597             :      * allows these checks to be performed only when an actual malloc needs to
    1598             :      * be done to request more memory from the OS.  Additionally, not having
    1599             :      * to execute any instructions after this call allows the compiler to use
    1600             :      * the sibling call optimization.  If you're considering adding code after
    1601             :      * this call, consider making it the responsibility of the 'realloc'
    1602             :      * function instead.
    1603             :      */
    1604       86880 :     ret = MCXT_METHOD(pointer, realloc) (pointer, size, flags);
    1605       86880 :     if (unlikely(ret == NULL))
    1606           0 :         return NULL;
    1607             : 
    1608             :     VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
    1609             : 
    1610       86880 :     return ret;
    1611             : }
    1612             : 
    1613             : /*
    1614             :  * repalloc0
    1615             :  *      Adjust the size of a previously allocated chunk and zero out the added
    1616             :  *      space.
    1617             :  */
    1618             : void *
    1619       47900 : repalloc0(void *pointer, Size oldsize, Size size)
    1620             : {
    1621             :     void       *ret;
    1622             : 
    1623             :     /* catch wrong argument order */
    1624       47900 :     if (unlikely(oldsize > size))
    1625           0 :         elog(ERROR, "invalid repalloc0 call: oldsize %zu, new size %zu",
    1626             :              oldsize, size);
    1627             : 
    1628       47900 :     ret = repalloc(pointer, size);
    1629       47900 :     memset((char *) ret + oldsize, 0, (size - oldsize));
    1630       47900 :     return ret;
    1631             : }
    1632             : 
    1633             : /*
    1634             :  * MemoryContextAllocHuge
    1635             :  *      Allocate (possibly-expansive) space within the specified context.
    1636             :  *
    1637             :  * See considerations in comment at MaxAllocHugeSize.
    1638             :  */
    1639             : void *
    1640        2574 : MemoryContextAllocHuge(MemoryContext context, Size size)
    1641             : {
    1642             :     void       *ret;
    1643             : 
    1644             :     Assert(MemoryContextIsValid(context));
    1645             :     AssertNotInCriticalSection(context);
    1646             : 
    1647        2574 :     context->isReset = false;
    1648             : 
    1649             :     /*
    1650             :      * For efficiency reasons, we purposefully offload the handling of
    1651             :      * allocation failures to the MemoryContextMethods implementation as this
    1652             :      * allows these checks to be performed only when an actual malloc needs to
    1653             :      * be done to request more memory from the OS.  Additionally, not having
    1654             :      * to execute any instructions after this call allows the compiler to use
    1655             :      * the sibling call optimization.  If you're considering adding code after
    1656             :      * this call, consider making it the responsibility of the 'alloc'
    1657             :      * function instead.
    1658             :      */
    1659        2574 :     ret = context->methods->alloc(context, size, MCXT_ALLOC_HUGE);
    1660             : 
    1661             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1662             : 
    1663        2574 :     return ret;
    1664             : }
    1665             : 
    1666             : /*
    1667             :  * repalloc_huge
    1668             :  *      Adjust the size of a previously allocated chunk, permitting a large
    1669             :  *      value.  The previous allocation need not have been "huge".
    1670             :  */
    1671             : void *
    1672       86104 : repalloc_huge(void *pointer, Size size)
    1673             : {
    1674             :     /* this one seems not worth its own implementation */
    1675       86104 :     return repalloc_extended(pointer, size, MCXT_ALLOC_HUGE);
    1676             : }
    1677             : 
    1678             : /*
    1679             :  * MemoryContextStrdup
    1680             :  *      Like strdup(), but allocate from the specified context
    1681             :  */
    1682             : char *
    1683    78340840 : MemoryContextStrdup(MemoryContext context, const char *string)
    1684             : {
    1685             :     char       *nstr;
    1686    78340840 :     Size        len = strlen(string) + 1;
    1687             : 
    1688    78340840 :     nstr = (char *) MemoryContextAlloc(context, len);
    1689             : 
    1690    78340840 :     memcpy(nstr, string, len);
    1691             : 
    1692    78340840 :     return nstr;
    1693             : }
    1694             : 
    1695             : char *
    1696    75089508 : pstrdup(const char *in)
    1697             : {
    1698    75089508 :     return MemoryContextStrdup(CurrentMemoryContext, in);
    1699             : }
    1700             : 
    1701             : /*
    1702             :  * pnstrdup
    1703             :  *      Like pstrdup(), but append null byte to a
    1704             :  *      not-necessarily-null-terminated input string.
    1705             :  */
    1706             : char *
    1707     1229936 : pnstrdup(const char *in, Size len)
    1708             : {
    1709             :     char       *out;
    1710             : 
    1711     1229936 :     len = strnlen(in, len);
    1712             : 
    1713     1229936 :     out = palloc(len + 1);
    1714     1229936 :     memcpy(out, in, len);
    1715     1229936 :     out[len] = '\0';
    1716             : 
    1717     1229936 :     return out;
    1718             : }
    1719             : 
    1720             : /*
    1721             :  * Make copy of string with all trailing newline characters removed.
    1722             :  */
    1723             : char *
    1724         370 : pchomp(const char *in)
    1725             : {
    1726             :     size_t      n;
    1727             : 
    1728         370 :     n = strlen(in);
    1729         740 :     while (n > 0 && in[n - 1] == '\n')
    1730         370 :         n--;
    1731         370 :     return pnstrdup(in, n);
    1732             : }

Generated by: LCOV version 1.14