LCOV - differential code coverage report
Current view: top level - src/backend/utils/mmgr - mcxt.c (source / functions) Coverage Total Hit UNC LBC UIC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 79.5 % 396 315 20 14 47 16 177 66 56 61 223 4 22
Current Date: 2023-04-08 15:15:32 Functions: 85.7 % 49 42 5 2 36 6 6 41 1 1
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a