LCOV - code coverage report
Current view: top level - src/backend/utils/mmgr - mcxt.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 79.8 % 515 411
Test Date: 2026-01-26 10:56:24 Functions: 81.5 % 54 44
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 49.9 % 507 253

             Branch data     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                 :    56160276 : GetMemoryChunkMethodID(const void *pointer)
     212                 :             : {
     213                 :    56160276 :         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         [ +  - ]:    56160276 :         Assert(pointer == (const void *) MAXALIGN(pointer));
     221                 :             : 
     222                 :             :         /* Allow access to the uint64 header */
     223                 :    56160276 :         VALGRIND_MAKE_MEM_DEFINED((char *) pointer - sizeof(uint64), sizeof(uint64));
     224                 :             : 
     225                 :    56160276 :         header = *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
     226                 :             : 
     227                 :             :         /* Disallow access to the uint64 header */
     228                 :    56160276 :         VALGRIND_MAKE_MEM_NOACCESS((char *) pointer - sizeof(uint64), sizeof(uint64));
     229                 :             : 
     230                 :   112320552 :         return (MemoryContextMethodID) (header & MEMORY_CONTEXT_METHODID_MASK);
     231                 :    56160276 : }
     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                 :           0 :         uint64          header;
     243                 :             : 
     244                 :             :         /* Allow access to the uint64 header */
     245                 :           0 :         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                 :           0 :         VALGRIND_MAKE_MEM_NOACCESS((char *) pointer - sizeof(uint64), sizeof(uint64));
     251                 :             : 
     252                 :           0 :         return header;
     253                 :           0 : }
     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                 :    11819614 : MemoryContextTraverseNext(MemoryContext curr, MemoryContext top)
     278                 :             : {
     279                 :             :         /* After processing a node, traverse to its first child if any */
     280         [ +  + ]:    11819614 :         if (curr->firstchild != NULL)
     281                 :     1244709 :                 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         [ +  + ]:    11819614 :         while (curr->nextchild == NULL)
     291                 :             :         {
     292                 :     1370292 :                 curr = curr->parent;
     293         [ +  + ]:     1370292 :                 if (curr == top)
     294                 :      125583 :                         return NULL;
     295                 :             :         }
     296                 :    10449322 :         return curr->nextchild;
     297                 :    11819614 : }
     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                 :           0 : }
     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                 :           0 :         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                 :           0 :         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                 :           0 :         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                 :           8 : MemoryContextInit(void)
     360                 :             : {
     361         [ +  - ]:           8 :         Assert(TopMemoryContext == NULL);
     362                 :             : 
     363                 :             :         /*
     364                 :             :          * First, initialize TopMemoryContext, which is the parent of all others.
     365                 :             :          */
     366                 :           8 :         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                 :           8 :         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                 :           8 :         ErrorContext = AllocSetContextCreate(TopMemoryContext,
     390                 :             :                                                                                  "ErrorContext",
     391                 :             :                                                                                  8 * 1024,
     392                 :             :                                                                                  8 * 1024,
     393                 :             :                                                                                  8 * 1024);
     394                 :           8 :         MemoryContextAllowInCriticalSection(ErrorContext, true);
     395                 :           8 : }
     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                 :    43125499 : MemoryContextReset(MemoryContext context)
     404                 :             : {
     405   [ +  -  +  +  :    43125499 :         Assert(MemoryContextIsValid(context));
             +  -  +  + ]
     406                 :             : 
     407                 :             :         /* save a function call in common case where there are no children */
     408         [ +  + ]:    43125499 :         if (context->firstchild != NULL)
     409                 :       50838 :                 MemoryContextDeleteChildren(context);
     410                 :             : 
     411                 :             :         /* save a function call if no pallocs since startup or last reset */
     412         [ +  + ]:    43125499 :         if (!context->isReset)
     413                 :     4543891 :                 MemoryContextResetOnly(context);
     414                 :    43125499 : }
     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                 :     5843800 : MemoryContextResetOnly(MemoryContext context)
     423                 :             : {
     424   [ +  -  +  +  :     5843800 :         Assert(MemoryContextIsValid(context));
             +  -  +  + ]
     425                 :             : 
     426                 :             :         /* Nothing to do if no pallocs since startup or last reset */
     427         [ +  + ]:     5843800 :         if (!context->isReset)
     428                 :             :         {
     429                 :     5843604 :                 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                 :     5843604 :                 context->methods->reset(context);
     440                 :     5843604 :                 context->isReset = true;
     441                 :     5843604 :         }
     442                 :     5843800 : }
     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   [ #  #  #  #  :           0 :         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                 :           0 :         }
     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                 :     2480584 : MemoryContextDelete(MemoryContext context)
     473                 :             : {
     474                 :     2480584 :         MemoryContext curr;
     475                 :             : 
     476   [ +  -  +  +  :     2480584 :         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                 :     2480584 :         curr = context;
     487                 :     2961933 :         for (;;)
     488                 :             :         {
     489                 :     2961933 :                 MemoryContext parent;
     490                 :             : 
     491                 :             :                 /* Descend down until we find a leaf context with no children */
     492         [ +  + ]:     3443282 :                 while (curr->firstchild != NULL)
     493                 :      481349 :                         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                 :     2961933 :                 parent = curr->parent;
     500                 :     2961933 :                 MemoryContextDeleteOnly(curr);
     501                 :             : 
     502         [ +  + ]:     2961933 :                 if (curr == context)
     503                 :     2480584 :                         break;
     504                 :      481349 :                 curr = parent;
     505      [ -  +  + ]:     2961933 :         }
     506                 :     2480584 : }
     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                 :     2961933 : MemoryContextDeleteOnly(MemoryContext context)
     515                 :             : {
     516   [ +  -  +  +  :     2961933 :         Assert(MemoryContextIsValid(context));
             +  +  +  + ]
     517                 :             :         /* We had better not be deleting TopMemoryContext ... */
     518         [ +  - ]:     2961933 :         Assert(context != TopMemoryContext);
     519                 :             :         /* And not CurrentMemoryContext, either */
     520         [ +  - ]:     2961933 :         Assert(context != CurrentMemoryContext);
     521                 :             :         /* All the children should've been deleted already */
     522         [ +  - ]:     2961933 :         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                 :     2961933 :         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                 :     2961933 :         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                 :     2961933 :         context->ident = NULL;
     545                 :             : 
     546                 :     2961933 :         context->methods->delete_context(context);
     547                 :     2961933 : }
     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                 :       83776 : MemoryContextDeleteChildren(MemoryContext context)
     556                 :             : {
     557   [ +  -  +  +  :       83776 :         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         [ +  + ]:      143496 :         while (context->firstchild != NULL)
     564                 :       59720 :                 MemoryContextDelete(context->firstchild);
     565                 :       83776 : }
     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                 :       10285 : MemoryContextRegisterResetCallback(MemoryContext context,
     583                 :             :                                                                    MemoryContextCallback *cb)
     584                 :             : {
     585   [ +  -  -  +  :       10285 :         Assert(MemoryContextIsValid(context));
             #  #  #  # ]
     586                 :             : 
     587                 :             :         /* Push onto head so this will be called before older registrants. */
     588                 :       10285 :         cb->next = context->reset_cbs;
     589                 :       10285 :         context->reset_cbs = cb;
     590                 :             :         /* Mark the context as non-reset (it probably is already). */
     591                 :       10285 :         context->isReset = false;
     592                 :       10285 : }
     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                 :           0 : MemoryContextUnregisterResetCallback(MemoryContext context,
     608                 :             :                                                                          MemoryContextCallback *cb)
     609                 :             : {
     610                 :           0 :         MemoryContextCallback *prev,
     611                 :             :                            *cur;
     612                 :             : 
     613   [ #  #  #  #  :           0 :         Assert(MemoryContextIsValid(context));
             #  #  #  # ]
     614                 :             : 
     615         [ #  # ]:           0 :         for (prev = NULL, cur = context->reset_cbs; cur != NULL;
     616                 :           0 :                  prev = cur, cur = cur->next)
     617                 :             :         {
     618         [ #  # ]:           0 :                 if (cur != cb)
     619                 :           0 :                         continue;
     620         [ #  # ]:           0 :                 if (prev)
     621                 :           0 :                         prev->next = cur->next;
     622                 :             :                 else
     623                 :           0 :                         context->reset_cbs = cur->next;
     624                 :           0 :                 return;
     625                 :             :         }
     626                 :           0 :         Assert(false);
     627         [ #  # ]:           0 : }
     628                 :             : 
     629                 :             : /*
     630                 :             :  * MemoryContextCallResetCallbacks
     631                 :             :  *              Internal function to call all registered callbacks for context.
     632                 :             :  */
     633                 :             : static void
     634                 :     8805537 : MemoryContextCallResetCallbacks(MemoryContext context)
     635                 :             : {
     636                 :     8805537 :         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         [ +  + ]:     8815822 :         while ((cb = context->reset_cbs) != NULL)
     644                 :             :         {
     645                 :       10285 :                 context->reset_cbs = cb->next;
     646                 :       10285 :                 cb->func(cb->arg);
     647                 :             :         }
     648                 :     8805537 : }
     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                 :      215721 : MemoryContextSetIdentifier(MemoryContext context, const char *id)
     662                 :             : {
     663   [ +  -  -  +  :      215721 :         Assert(MemoryContextIsValid(context));
             #  #  #  # ]
     664                 :      215721 :         context->ident = id;
     665                 :      215721 : }
     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                 :     2990109 : MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
     687                 :             : {
     688   [ +  -  +  +  :     2990109 :         Assert(MemoryContextIsValid(context));
             +  +  +  + ]
     689         [ +  - ]:     2990109 :         Assert(context != new_parent);
     690                 :             : 
     691                 :             :         /* Fast path if it's got correct parent already */
     692         [ +  + ]:     2990109 :         if (new_parent == context->parent)
     693                 :        1570 :                 return;
     694                 :             : 
     695                 :             :         /* Delink from existing parent, if any */
     696         [ -  + ]:     2988539 :         if (context->parent)
     697                 :             :         {
     698                 :     2988539 :                 MemoryContext parent = context->parent;
     699                 :             : 
     700         [ +  + ]:     2988539 :                 if (context->prevchild != NULL)
     701                 :      109384 :                         context->prevchild->nextchild = context->nextchild;
     702                 :             :                 else
     703                 :             :                 {
     704         [ +  - ]:     2879155 :                         Assert(parent->firstchild == context);
     705                 :     2879155 :                         parent->firstchild = context->nextchild;
     706                 :             :                 }
     707                 :             : 
     708         [ +  + ]:     2988539 :                 if (context->nextchild != NULL)
     709                 :     1338537 :                         context->nextchild->prevchild = context->prevchild;
     710                 :     2988539 :         }
     711                 :             : 
     712                 :             :         /* And relink */
     713         [ +  + ]:     2988539 :         if (new_parent)
     714                 :             :         {
     715   [ +  -  -  +  :       26606 :                 Assert(MemoryContextIsValid(new_parent));
             #  #  #  # ]
     716                 :       26606 :                 context->parent = new_parent;
     717                 :       26606 :                 context->prevchild = NULL;
     718                 :       26606 :                 context->nextchild = new_parent->firstchild;
     719         [ +  + ]:       26606 :                 if (new_parent->firstchild != NULL)
     720                 :       24699 :                         new_parent->firstchild->prevchild = context;
     721                 :       26606 :                 new_parent->firstchild = context;
     722                 :       26606 :         }
     723                 :             :         else
     724                 :             :         {
     725                 :     2961933 :                 context->parent = NULL;
     726                 :     2961933 :                 context->prevchild = NULL;
     727                 :     2961933 :                 context->nextchild = NULL;
     728                 :             :         }
     729                 :     2990109 : }
     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                 :          11 : MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
     744                 :             : {
     745   [ +  -  -  +  :          11 :         Assert(MemoryContextIsValid(context));
             #  #  #  # ]
     746                 :             : 
     747                 :          11 :         context->allowInCritSection = allow;
     748                 :          11 : }
     749                 :             : 
     750                 :             : /*
     751                 :             :  * GetMemoryChunkContext
     752                 :             :  *              Given a currently-allocated chunk, determine the MemoryContext that
     753                 :             :  *              the chunk belongs to.
     754                 :             :  */
     755                 :             : MemoryContext
     756                 :      526620 : GetMemoryChunkContext(void *pointer)
     757                 :             : {
     758                 :      526620 :         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                 :     4408291 : GetMemoryChunkSpace(void *pointer)
     771                 :             : {
     772                 :     4408291 :         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                 :        2794 : MemoryContextGetParent(MemoryContext context)
     781                 :             : {
     782   [ +  -  -  +  :        2794 :         Assert(MemoryContextIsValid(context));
             #  #  #  # ]
     783                 :             : 
     784                 :        2794 :         return context->parent;
     785                 :             : }
     786                 :             : 
     787                 :             : /*
     788                 :             :  * MemoryContextIsEmpty
     789                 :             :  *              Is a memory context empty of any allocated space?
     790                 :             :  */
     791                 :             : bool
     792                 :         482 : MemoryContextIsEmpty(MemoryContext context)
     793                 :             : {
     794   [ +  -  -  +  :         482 :         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         [ -  + ]:         482 :         if (context->firstchild != NULL)
     801                 :           0 :                 return false;
     802                 :             :         /* Otherwise use the type-specific inquiry */
     803                 :         482 :         return context->methods->is_empty(context);
     804                 :         482 : }
     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                 :      214392 : MemoryContextMemAllocated(MemoryContext context, bool recurse)
     812                 :             : {
     813                 :      214392 :         Size            total = context->mem_allocated;
     814                 :             : 
     815   [ +  -  +  +  :      214392 :         Assert(MemoryContextIsValid(context));
             +  -  +  - ]
     816                 :             : 
     817         [ +  - ]:      214392 :         if (recurse)
     818                 :             :         {
     819         [ +  + ]:      350566 :                 for (MemoryContext curr = context->firstchild;
     820                 :      350566 :                          curr != NULL;
     821                 :      136174 :                          curr = MemoryContextTraverseNext(curr, context))
     822                 :             :                 {
     823                 :      136174 :                         total += curr->mem_allocated;
     824                 :      136174 :                 }
     825                 :      214392 :         }
     826                 :             : 
     827                 :      428784 :         return total;
     828                 :      214392 : }
     829                 :             : 
     830                 :             : /*
     831                 :             :  * Return the memory consumption statistics about the given context and its
     832                 :             :  * children.
     833                 :             :  */
     834                 :             : void
     835                 :           5 : MemoryContextMemConsumed(MemoryContext context,
     836                 :             :                                                  MemoryContextCounters *consumed)
     837                 :             : {
     838   [ +  -  -  +  :           5 :         Assert(MemoryContextIsValid(context));
             #  #  #  # ]
     839                 :             : 
     840                 :           5 :         memset(consumed, 0, sizeof(*consumed));
     841                 :             : 
     842                 :             :         /* Examine the context itself */
     843                 :           5 :         context->methods->stats(context, NULL, NULL, consumed, false);
     844                 :             : 
     845                 :             :         /* Examine children, using iteration not recursion */
     846         [ +  - ]:           5 :         for (MemoryContext curr = context->firstchild;
     847                 :           5 :                  curr != NULL;
     848                 :           0 :                  curr = MemoryContextTraverseNext(curr, context))
     849                 :             :         {
     850                 :           0 :                 curr->methods->stats(curr, NULL, NULL, consumed, false);
     851                 :           0 :         }
     852                 :           5 : }
     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                 :           2 : MemoryContextStatsDetail(MemoryContext context,
     879                 :             :                                                  int max_level, int max_children,
     880                 :             :                                                  bool print_to_stderr)
     881                 :             : {
     882                 :           2 :         MemoryContextCounters grand_totals;
     883                 :             : 
     884                 :           2 :         memset(&grand_totals, 0, sizeof(grand_totals));
     885                 :             : 
     886                 :           4 :         MemoryContextStatsInternal(context, 1, max_level, max_children,
     887                 :           2 :                                                            &grand_totals, print_to_stderr);
     888                 :             : 
     889         [ -  + ]:           2 :         if (print_to_stderr)
     890                 :           0 :                 fprintf(stderr,
     891                 :             :                                 "Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used\n",
     892                 :           0 :                                 grand_totals.totalspace, grand_totals.nblocks,
     893                 :           0 :                                 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   [ -  +  +  - ]:           2 :                 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                 :           2 : }
     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                 :         258 : MemoryContextStatsInternal(MemoryContext context, int level,
     926                 :             :                                                    int max_level, int max_children,
     927                 :             :                                                    MemoryContextCounters *totals,
     928                 :             :                                                    bool print_to_stderr)
     929                 :             : {
     930                 :         258 :         MemoryContext child;
     931                 :         258 :         int                     ichild;
     932                 :             : 
     933   [ +  -  -  +  :         258 :         Assert(MemoryContextIsValid(context));
             #  #  #  # ]
     934                 :             : 
     935                 :             :         /* Examine the context itself */
     936                 :         516 :         context->methods->stats(context,
     937                 :             :                                                         MemoryContextStatsPrint,
     938                 :             :                                                         &level,
     939                 :         258 :                                                         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                 :         258 :         child = context->firstchild;
     950                 :         258 :         ichild = 0;
     951   [ +  -  -  + ]:         258 :         if (level <= max_level && !stack_is_too_deep())
     952                 :             :         {
     953   [ +  +  +  + ]:         514 :                 for (; child != NULL && ichild < max_children;
     954                 :         256 :                          child = child->nextchild, ichild++)
     955                 :             :                 {
     956                 :         512 :                         MemoryContextStatsInternal(child, level + 1,
     957                 :         256 :                                                                            max_level, max_children,
     958                 :         256 :                                                                            totals,
     959                 :         256 :                                                                            print_to_stderr);
     960                 :         256 :                 }
     961                 :         258 :         }
     962                 :             : 
     963         [ +  - ]:         258 :         if (child != NULL)
     964                 :             :         {
     965                 :             :                 /* Summarize the rest of the children, avoiding recursion. */
     966                 :           0 :                 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                 :           0 :                                         ichild,
     985                 :           0 :                                         local_totals.totalspace,
     986                 :           0 :                                         local_totals.nblocks,
     987                 :           0 :                                         local_totals.freespace,
     988                 :           0 :                                         local_totals.freechunks,
     989                 :           0 :                                         local_totals.totalspace - local_totals.freespace);
     990                 :           0 :                 }
     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                 :           0 :                 }
    1011                 :           0 :         }
    1012                 :         258 : }
    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                 :         258 : MemoryContextStatsPrint(MemoryContext context, void *passthru,
    1023                 :             :                                                 const char *stats_string,
    1024                 :             :                                                 bool print_to_stderr)
    1025                 :             : {
    1026                 :         258 :         int                     level = *(int *) passthru;
    1027                 :         258 :         const char *name = context->name;
    1028                 :         258 :         const char *ident = context->ident;
    1029                 :         258 :         char            truncated_ident[110];
    1030                 :         258 :         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   [ +  +  +  + ]:         258 :         if (ident && strcmp(name, "dynahash") == 0)
    1038                 :             :         {
    1039                 :          30 :                 name = ident;
    1040                 :          30 :                 ident = NULL;
    1041                 :          30 :         }
    1042                 :             : 
    1043                 :         258 :         truncated_ident[0] = '\0';
    1044                 :             : 
    1045         [ +  + ]:         258 :         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                 :         190 :                 int                     idlen = strlen(ident);
    1054                 :         190 :                 bool            truncated = false;
    1055                 :             : 
    1056                 :         190 :                 strcpy(truncated_ident, ": ");
    1057                 :         190 :                 i = strlen(truncated_ident);
    1058                 :             : 
    1059         [ +  - ]:         190 :                 if (idlen > 100)
    1060                 :             :                 {
    1061                 :           0 :                         idlen = pg_mbcliplen(ident, idlen, 100);
    1062                 :           0 :                         truncated = true;
    1063                 :           0 :                 }
    1064                 :             : 
    1065         [ +  + ]:        5311 :                 while (idlen-- > 0)
    1066                 :             :                 {
    1067                 :        5121 :                         unsigned char c = *ident++;
    1068                 :             : 
    1069         [ +  - ]:        5121 :                         if (c < ' ')
    1070                 :           0 :                                 c = ' ';
    1071                 :        5121 :                         truncated_ident[i++] = c;
    1072                 :        5121 :                 }
    1073                 :         190 :                 truncated_ident[i] = '\0';
    1074                 :             : 
    1075         [ +  - ]:         190 :                 if (truncated)
    1076                 :           0 :                         strcat(truncated_ident, "...");
    1077                 :         190 :         }
    1078                 :             : 
    1079         [ -  + ]:         258 :         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                 :           0 :         }
    1085                 :             :         else
    1086   [ -  +  +  - ]:         258 :                 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                 :         258 : }
    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                 :       52263 : MemoryContextCheck(MemoryContext context)
    1102                 :             : {
    1103   [ +  -  -  +  :       52263 :         Assert(MemoryContextIsValid(context));
             #  #  #  # ]
    1104                 :       52263 :         context->methods->check(context);
    1105                 :             : 
    1106         [ +  + ]:    11735703 :         for (MemoryContext curr = context->firstchild;
    1107                 :    11735703 :                  curr != NULL;
    1108                 :    11683440 :                  curr = MemoryContextTraverseNext(curr, context))
    1109                 :             :         {
    1110   [ +  -  +  +  :    11683440 :                 Assert(MemoryContextIsValid(curr));
             +  -  +  + ]
    1111                 :    11683440 :                 curr->methods->check(curr);
    1112                 :    11683440 :         }
    1113                 :       52263 : }
    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                 :     3029796 : 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         [ +  - ]:     3029796 :         Assert(CritSectionCount == 0);
    1157                 :             : 
    1158                 :             :         /* Validate parent, to help prevent crazy context linkages */
    1159   [ +  +  +  -  :     3029796 :         Assert(parent == NULL || MemoryContextIsValid(parent));
          +  +  +  -  +  
                      - ]
    1160         [ +  - ]:     3029796 :         Assert(node != parent);
    1161                 :             : 
    1162                 :             :         /* Initialize all standard fields of memory context header */
    1163                 :     3029796 :         node->type = tag;
    1164                 :     3029796 :         node->isReset = true;
    1165                 :     3029796 :         node->methods = &mcxt_methods[method_id];
    1166                 :     3029796 :         node->parent = parent;
    1167                 :     3029796 :         node->firstchild = NULL;
    1168                 :     3029796 :         node->mem_allocated = 0;
    1169                 :     3029796 :         node->prevchild = NULL;
    1170                 :     3029796 :         node->name = name;
    1171                 :     3029796 :         node->ident = NULL;
    1172                 :     3029796 :         node->reset_cbs = NULL;
    1173                 :             : 
    1174                 :             :         /* OK to link node into context tree */
    1175         [ +  + ]:     3029796 :         if (parent)
    1176                 :             :         {
    1177                 :     3029787 :                 node->nextchild = parent->firstchild;
    1178         [ +  + ]:     3029787 :                 if (parent->firstchild != NULL)
    1179                 :     1390928 :                         parent->firstchild->prevchild = node;
    1180                 :     3029787 :                 parent->firstchild = node;
    1181                 :             :                 /* inherit allowInCritSection flag from parent */
    1182                 :     3029787 :                 node->allowInCritSection = parent->allowInCritSection;
    1183                 :     3029787 :         }
    1184                 :             :         else
    1185                 :             :         {
    1186                 :           9 :                 node->nextchild = NULL;
    1187                 :           9 :                 node->allowInCritSection = false;
    1188                 :             :         }
    1189                 :     3029796 : }
    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                 :           0 :         }
    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                 :           0 : }
    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                 :     9055178 : MemoryContextAlloc(MemoryContext context, Size size)
    1233                 :             : {
    1234                 :     9055178 :         void       *ret;
    1235                 :             : 
    1236   [ +  -  +  +  :     9055178 :         Assert(MemoryContextIsValid(context));
             +  +  +  + ]
    1237   [ +  +  +  - ]:     9055178 :         AssertNotInCriticalSection(context);
    1238                 :             : 
    1239                 :     9055178 :         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                 :     9055178 :         ret = context->methods->alloc(context, size, 0);
    1252                 :             : 
    1253                 :     9055178 :         VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1254                 :             : 
    1255                 :    18110356 :         return ret;
    1256                 :     9055178 : }
    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                 :     3622939 : MemoryContextAllocZero(MemoryContext context, Size size)
    1267                 :             : {
    1268                 :     3622939 :         void       *ret;
    1269                 :             : 
    1270   [ +  -  +  +  :     3622939 :         Assert(MemoryContextIsValid(context));
             +  -  +  - ]
    1271   [ -  +  #  # ]:     3622939 :         AssertNotInCriticalSection(context);
    1272                 :             : 
    1273                 :     3622939 :         context->isReset = false;
    1274                 :             : 
    1275                 :     3622939 :         ret = context->methods->alloc(context, size, 0);
    1276                 :             : 
    1277                 :     3622939 :         VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1278                 :             : 
    1279   [ +  +  +  -  :    32557127 :         MemSetAligned(ret, 0, size);
             +  +  +  + ]
    1280                 :             : 
    1281                 :     7245878 :         return ret;
    1282                 :     3622939 : }
    1283                 :             : 
    1284                 :             : /*
    1285                 :             :  * MemoryContextAllocExtended
    1286                 :             :  *              Allocate space within the specified context using the given flags.
    1287                 :             :  */
    1288                 :             : void *
    1289                 :      512386 : MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
    1290                 :             : {
    1291                 :      512386 :         void       *ret;
    1292                 :             : 
    1293   [ +  -  -  +  :      512386 :         Assert(MemoryContextIsValid(context));
             #  #  #  # ]
    1294   [ +  +  +  - ]:      512386 :         AssertNotInCriticalSection(context);
    1295                 :             : 
    1296   [ +  +  +  - ]:      512386 :         if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) :
    1297                 :      332788 :                   AllocSizeIsValid(size)))
    1298   [ #  #  #  # ]:           0 :                 elog(ERROR, "invalid memory alloc request size %zu", size);
    1299                 :             : 
    1300                 :      512386 :         context->isReset = false;
    1301                 :             : 
    1302                 :      512386 :         ret = context->methods->alloc(context, size, flags);
    1303         [ -  + ]:      512386 :         if (unlikely(ret == NULL))
    1304                 :           0 :                 return NULL;
    1305                 :             : 
    1306                 :      512386 :         VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1307                 :             : 
    1308         [ +  + ]:      512386 :         if ((flags & MCXT_ALLOC_ZERO) != 0)
    1309   [ +  -  +  -  :      251696 :                 MemSetAligned(ret, 0, size);
             +  +  +  + ]
    1310                 :             : 
    1311                 :      512386 :         return ret;
    1312                 :      512386 : }
    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                 :           2 : HandleLogMemoryContextInterrupt(void)
    1324                 :             : {
    1325                 :           2 :         InterruptPending = true;
    1326                 :           2 :         LogMemoryContextPending = true;
    1327                 :             :         /* latch will be set by procsignal_sigusr1_handler */
    1328                 :           2 : }
    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                 :           2 : ProcessLogMemoryContextInterrupt(void)
    1341                 :             : {
    1342                 :           2 :         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         [ -  + ]:           2 :         if (LogMemoryContextInProgress)
    1351                 :           0 :                 return;
    1352                 :           2 :         LogMemoryContextInProgress = true;
    1353                 :             : 
    1354         [ -  + ]:           2 :         PG_TRY();
    1355                 :             :         {
    1356                 :             :                 /*
    1357                 :             :                  * Use LOG_SERVER_ONLY to prevent this message from being sent to the
    1358                 :             :                  * connected client.
    1359                 :             :                  */
    1360   [ -  +  +  - ]:           2 :                 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                 :           2 :                 MemoryContextStatsDetail(TopMemoryContext, 100, 100, false);
    1378                 :             :         }
    1379                 :           2 :         PG_FINALLY();
    1380                 :             :         {
    1381                 :           2 :                 LogMemoryContextInProgress = false;
    1382                 :             :         }
    1383         [ +  - ]:           2 :         PG_END_TRY();
    1384                 :           2 : }
    1385                 :             : 
    1386                 :             : void *
    1387                 :    58211768 : palloc(Size size)
    1388                 :             : {
    1389                 :             :         /* duplicates MemoryContextAlloc to avoid increased overhead */
    1390                 :    58211768 :         void       *ret;
    1391                 :    58211768 :         MemoryContext context = CurrentMemoryContext;
    1392                 :             : 
    1393   [ +  -  +  +  :    58211768 :         Assert(MemoryContextIsValid(context));
             +  -  +  + ]
    1394   [ +  +  +  - ]:    58211768 :         AssertNotInCriticalSection(context);
    1395                 :             : 
    1396                 :    58211768 :         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                 :    58211768 :         ret = context->methods->alloc(context, size, 0);
    1409                 :             :         /* We expect OOM to be handled by the alloc function */
    1410         [ +  - ]:    58211768 :         Assert(ret != NULL);
    1411                 :    58211768 :         VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1412                 :             : 
    1413                 :   116423536 :         return ret;
    1414                 :    58211768 : }
    1415                 :             : 
    1416                 :             : void *
    1417                 :    39163258 : palloc0(Size size)
    1418                 :             : {
    1419                 :             :         /* duplicates MemoryContextAllocZero to avoid increased overhead */
    1420                 :    39163258 :         void       *ret;
    1421                 :    39163258 :         MemoryContext context = CurrentMemoryContext;
    1422                 :             : 
    1423   [ +  -  +  +  :    39163258 :         Assert(MemoryContextIsValid(context));
             +  -  +  + ]
    1424   [ -  +  #  # ]:    39163258 :         AssertNotInCriticalSection(context);
    1425                 :             : 
    1426                 :    39163258 :         context->isReset = false;
    1427                 :             : 
    1428                 :    39163258 :         ret = context->methods->alloc(context, size, 0);
    1429                 :             :         /* We expect OOM to be handled by the alloc function */
    1430         [ +  - ]:    39163258 :         Assert(ret != NULL);
    1431                 :    39163258 :         VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1432                 :             : 
    1433   [ +  +  +  -  :   395342938 :         MemSetAligned(ret, 0, size);
             +  +  +  + ]
    1434                 :             : 
    1435                 :    78326516 :         return ret;
    1436                 :    39163258 : }
    1437                 :             : 
    1438                 :             : void *
    1439                 :     3866529 : palloc_extended(Size size, int flags)
    1440                 :             : {
    1441                 :             :         /* duplicates MemoryContextAllocExtended to avoid increased overhead */
    1442                 :     3866529 :         void       *ret;
    1443                 :     3866529 :         MemoryContext context = CurrentMemoryContext;
    1444                 :             : 
    1445   [ +  -  -  +  :     3866529 :         Assert(MemoryContextIsValid(context));
             #  #  #  # ]
    1446   [ -  +  #  # ]:     3866529 :         AssertNotInCriticalSection(context);
    1447                 :             : 
    1448                 :     3866529 :         context->isReset = false;
    1449                 :             : 
    1450                 :     3866529 :         ret = context->methods->alloc(context, size, flags);
    1451         [ -  + ]:     3866529 :         if (unlikely(ret == NULL))
    1452                 :             :         {
    1453                 :             :                 /* NULL can be returned only when using MCXT_ALLOC_NO_OOM */
    1454         [ #  # ]:           0 :                 Assert(flags & MCXT_ALLOC_NO_OOM);
    1455                 :           0 :                 return NULL;
    1456                 :             :         }
    1457                 :             : 
    1458                 :     3866529 :         VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1459                 :             : 
    1460         [ +  + ]:     3866529 :         if ((flags & MCXT_ALLOC_ZERO) != 0)
    1461   [ +  -  +  -  :           4 :                 MemSetAligned(ret, 0, size);
             +  -  #  # ]
    1462                 :             : 
    1463                 :     3866529 :         return ret;
    1464                 :     3866529 : }
    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                 :       77689 : MemoryContextAllocAligned(MemoryContext context,
    1483                 :             :                                                   Size size, Size alignto, int flags)
    1484                 :             : {
    1485                 :       77689 :         MemoryChunk *alignedchunk;
    1486                 :       77689 :         Size            alloc_size;
    1487                 :       77689 :         void       *unaligned;
    1488                 :       77689 :         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         [ +  - ]:       77689 :         Assert(alignto < (128 * 1024 * 1024));
    1498                 :             : 
    1499                 :             :         /* ensure alignto is a power of 2 */
    1500         [ +  - ]:       77689 :         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         [ -  + ]:       77689 :         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                 :       77689 :         alloc_size = size + PallocAlignedExtraBytes(alignto);
    1527                 :             : 
    1528                 :             : #ifdef MEMORY_CONTEXT_CHECKING
    1529                 :             :         /* ensure there's space for a sentinel byte */
    1530                 :       77689 :         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                 :      155378 :         unaligned = MemoryContextAllocExtended(context, alloc_size,
    1539                 :       77689 :                                                                                    flags & ~MCXT_ALLOC_ZERO);
    1540                 :             : 
    1541                 :             :         /* compute the aligned pointer */
    1542                 :       77689 :         aligned = (void *) TYPEALIGN(alignto, (char *) unaligned +
    1543                 :             :                                                                  sizeof(MemoryChunk));
    1544                 :             : 
    1545                 :       77689 :         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                 :       77689 :         MemoryChunkSetHdrMask(alignedchunk, unaligned, alignto,
    1558                 :             :                                                   MCTX_ALIGNED_REDIRECT_ID);
    1559                 :             : 
    1560                 :             :         /* double check we produced a correctly aligned pointer */
    1561         [ +  - ]:       77689 :         Assert((void *) TYPEALIGN(alignto, aligned) == aligned);
    1562                 :             : 
    1563                 :             : #ifdef MEMORY_CONTEXT_CHECKING
    1564                 :       77689 :         alignedchunk->requested_size = size;
    1565                 :             :         /* set mark to catch clobber of "unused" space */
    1566                 :       77689 :         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                 :       77689 :         VALGRIND_MEMPOOL_FREE(context, unaligned);
    1581                 :       77689 :         VALGRIND_MEMPOOL_ALLOC(context, aligned, size);
    1582                 :             : 
    1583                 :             :         /* Now zero (and make DEFINED) just the aligned chunk, if requested */
    1584         [ +  + ]:       77689 :         if ((flags & MCXT_ALLOC_ZERO) != 0)
    1585   [ +  -  +  -  :     3866310 :                 MemSetAligned(aligned, 0, size);
             -  +  +  + ]
    1586                 :             : 
    1587                 :       77689 :         return aligned;
    1588                 :       77689 : }
    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                 :       67830 : palloc_aligned(Size size, Size alignto, int flags)
    1607                 :             : {
    1608                 :       67830 :         return MemoryContextAllocAligned(CurrentMemoryContext, size, alignto, flags);
    1609                 :             : }
    1610                 :             : 
    1611                 :             : /*
    1612                 :             :  * pfree
    1613                 :             :  *              Release an allocated chunk.
    1614                 :             :  */
    1615                 :             : void
    1616                 :    50990794 : pfree(void *pointer)
    1617                 :             : {
    1618                 :             : #ifdef USE_VALGRIND
    1619                 :             :         MemoryContext context = GetMemoryChunkContext(pointer);
    1620                 :             : #endif
    1621                 :             : 
    1622                 :    50990794 :         MCXT_METHOD(pointer, free_p) (pointer);
    1623                 :             : 
    1624                 :    50990794 :         VALGRIND_MEMPOOL_FREE(context, pointer);
    1625                 :    50990794 : }
    1626                 :             : 
    1627                 :             : /*
    1628                 :             :  * repalloc
    1629                 :             :  *              Adjust the size of a previously allocated chunk.
    1630                 :             :  */
    1631                 :             : void *
    1632                 :      221829 : repalloc(void *pointer, Size size)
    1633                 :             : {
    1634                 :             : #if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
    1635                 :      221829 :         MemoryContext context = GetMemoryChunkContext(pointer);
    1636                 :             : #endif
    1637                 :      221829 :         void       *ret;
    1638                 :             : 
    1639   [ -  +  #  # ]:      221829 :         AssertNotInCriticalSection(context);
    1640                 :             : 
    1641                 :             :         /* isReset must be false already */
    1642         [ +  - ]:      221829 :         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                 :      221829 :         ret = MCXT_METHOD(pointer, realloc) (pointer, size, 0);
    1655                 :             : 
    1656                 :      221829 :         VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
    1657                 :             : 
    1658                 :      443658 :         return ret;
    1659                 :      221829 : }
    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                 :       12742 : repalloc_extended(void *pointer, Size size, int flags)
    1668                 :             : {
    1669                 :             : #if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
    1670                 :       12742 :         MemoryContext context = GetMemoryChunkContext(pointer);
    1671                 :             : #endif
    1672                 :       12742 :         void       *ret;
    1673                 :             : 
    1674   [ -  +  #  # ]:       12742 :         AssertNotInCriticalSection(context);
    1675                 :             : 
    1676                 :             :         /* isReset must be false already */
    1677         [ +  - ]:       12742 :         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                 :       12742 :         ret = MCXT_METHOD(pointer, realloc) (pointer, size, flags);
    1690         [ -  + ]:       12742 :         if (unlikely(ret == NULL))
    1691                 :           0 :                 return NULL;
    1692                 :             : 
    1693                 :       12742 :         VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
    1694                 :             : 
    1695                 :       12742 :         return ret;
    1696                 :       12742 : }
    1697                 :             : 
    1698                 :             : /*
    1699                 :             :  * repalloc0
    1700                 :             :  *              Adjust the size of a previously allocated chunk and zero out the added
    1701                 :             :  *              space.
    1702                 :             :  */
    1703                 :             : void *
    1704                 :        6729 : repalloc0(void *pointer, Size oldsize, Size size)
    1705                 :             : {
    1706                 :        6729 :         void       *ret;
    1707                 :             : 
    1708                 :             :         /* catch wrong argument order */
    1709         [ +  - ]:        6729 :         if (unlikely(oldsize > size))
    1710   [ #  #  #  # ]:           0 :                 elog(ERROR, "invalid repalloc0 call: oldsize %zu, new size %zu",
    1711                 :             :                          oldsize, size);
    1712                 :             : 
    1713                 :        6729 :         ret = repalloc(pointer, size);
    1714                 :        6729 :         memset((char *) ret + oldsize, 0, (size - oldsize));
    1715                 :       13458 :         return ret;
    1716                 :        6729 : }
    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                 :         164 : MemoryContextAllocHuge(MemoryContext context, Size size)
    1726                 :             : {
    1727                 :         164 :         void       *ret;
    1728                 :             : 
    1729   [ +  -  -  +  :         164 :         Assert(MemoryContextIsValid(context));
             #  #  #  # ]
    1730   [ -  +  #  # ]:         164 :         AssertNotInCriticalSection(context);
    1731                 :             : 
    1732                 :         164 :         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                 :         164 :         ret = context->methods->alloc(context, size, MCXT_ALLOC_HUGE);
    1745                 :             : 
    1746                 :         164 :         VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1747                 :             : 
    1748                 :         328 :         return ret;
    1749                 :         164 : }
    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                 :       12659 : repalloc_huge(void *pointer, Size size)
    1758                 :             : {
    1759                 :             :         /* this one seems not worth its own implementation */
    1760                 :       12659 :         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                 :     2680607 : MemoryContextStrdup(MemoryContext context, const char *string)
    1769                 :             : {
    1770                 :     2680607 :         char       *nstr;
    1771                 :     2680607 :         Size            len = strlen(string) + 1;
    1772                 :             : 
    1773                 :     2680607 :         nstr = (char *) MemoryContextAlloc(context, len);
    1774                 :             : 
    1775                 :     2680607 :         memcpy(nstr, string, len);
    1776                 :             : 
    1777                 :     5361214 :         return nstr;
    1778                 :     2680607 : }
    1779                 :             : 
    1780                 :             : char *
    1781                 :     2545134 : pstrdup(const char *in)
    1782                 :             : {
    1783                 :     2545134 :         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                 :      169408 : pnstrdup(const char *in, Size len)
    1793                 :             : {
    1794                 :      169408 :         char       *out;
    1795                 :             : 
    1796                 :      169408 :         len = strnlen(in, len);
    1797                 :             : 
    1798                 :      169408 :         out = palloc(len + 1);
    1799                 :      169408 :         memcpy(out, in, len);
    1800                 :      169408 :         out[len] = '\0';
    1801                 :             : 
    1802                 :      338816 :         return out;
    1803                 :      169408 : }
    1804                 :             : 
    1805                 :             : /*
    1806                 :             :  * Make copy of string with all trailing newline characters removed.
    1807                 :             :  */
    1808                 :             : char *
    1809                 :           1 : pchomp(const char *in)
    1810                 :             : {
    1811                 :           1 :         size_t          n;
    1812                 :             : 
    1813                 :           1 :         n = strlen(in);
    1814   [ -  +  +  + ]:           2 :         while (n > 0 && in[n - 1] == '\n')
    1815                 :           1 :                 n--;
    1816                 :           2 :         return pnstrdup(in, n);
    1817                 :           1 : }
        

Generated by: LCOV version 2.3.2-1