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

Generated by: LCOV version 1.16