LCOV - code coverage report
Current view: top level - src/backend/utils/mmgr - mcxt.c (source / functions) Hit Total Coverage
Test: PostgreSQL 15devel Lines: 247 312 79.2 %
Date: 2021-12-05 02:08:31 Functions: 36 38 94.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * mcxt.c
       4             :  *    POSTGRES memory context management code.
       5             :  *
       6             :  * This module handles context management operations that are independent
       7             :  * of the particular kind of context being operated on.  It calls
       8             :  * context-type-specific operations via the function pointers in a
       9             :  * context's MemoryContextMethods struct.
      10             :  *
      11             :  *
      12             :  * Portions Copyright (c) 1996-2021, 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             : 
      33             : 
      34             : /*****************************************************************************
      35             :  *    GLOBAL MEMORY                                                          *
      36             :  *****************************************************************************/
      37             : 
      38             : /*
      39             :  * CurrentMemoryContext
      40             :  *      Default memory context for allocations.
      41             :  */
      42             : MemoryContext CurrentMemoryContext = NULL;
      43             : 
      44             : /*
      45             :  * Standard top-level contexts. For a description of the purpose of each
      46             :  * of these contexts, refer to src/backend/utils/mmgr/README
      47             :  */
      48             : MemoryContext TopMemoryContext = NULL;
      49             : MemoryContext ErrorContext = NULL;
      50             : MemoryContext PostmasterContext = NULL;
      51             : MemoryContext CacheMemoryContext = NULL;
      52             : MemoryContext MessageContext = NULL;
      53             : MemoryContext TopTransactionContext = NULL;
      54             : MemoryContext CurTransactionContext = NULL;
      55             : 
      56             : /* This is a transient link to the active portal's memory context: */
      57             : MemoryContext PortalContext = NULL;
      58             : 
      59             : static void MemoryContextCallResetCallbacks(MemoryContext context);
      60             : static void MemoryContextStatsInternal(MemoryContext context, int level,
      61             :                                        bool print, int max_children,
      62             :                                        MemoryContextCounters *totals,
      63             :                                        bool print_to_stderr);
      64             : static void MemoryContextStatsPrint(MemoryContext context, void *passthru,
      65             :                                     const char *stats_string,
      66             :                                     bool print_to_stderr);
      67             : 
      68             : /*
      69             :  * You should not do memory allocations within a critical section, because
      70             :  * an out-of-memory error will be escalated to a PANIC. To enforce that
      71             :  * rule, the allocation functions Assert that.
      72             :  */
      73             : #define AssertNotInCriticalSection(context) \
      74             :     Assert(CritSectionCount == 0 || (context)->allowInCritSection)
      75             : 
      76             : 
      77             : /*****************************************************************************
      78             :  *    EXPORTED ROUTINES                                                      *
      79             :  *****************************************************************************/
      80             : 
      81             : 
      82             : /*
      83             :  * MemoryContextInit
      84             :  *      Start up the memory-context subsystem.
      85             :  *
      86             :  * This must be called before creating contexts or allocating memory in
      87             :  * contexts.  TopMemoryContext and ErrorContext are initialized here;
      88             :  * other contexts must be created afterwards.
      89             :  *
      90             :  * In normal multi-backend operation, this is called once during
      91             :  * postmaster startup, and not at all by individual backend startup
      92             :  * (since the backends inherit an already-initialized context subsystem
      93             :  * by virtue of being forked off the postmaster).  But in an EXEC_BACKEND
      94             :  * build, each process must do this for itself.
      95             :  *
      96             :  * In a standalone backend this must be called during backend startup.
      97             :  */
      98             : void
      99        4126 : MemoryContextInit(void)
     100             : {
     101             :     AssertState(TopMemoryContext == NULL);
     102             : 
     103             :     /*
     104             :      * First, initialize TopMemoryContext, which is the parent of all others.
     105             :      */
     106        4126 :     TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
     107             :                                              "TopMemoryContext",
     108             :                                              ALLOCSET_DEFAULT_SIZES);
     109             : 
     110             :     /*
     111             :      * Not having any other place to point CurrentMemoryContext, make it point
     112             :      * to TopMemoryContext.  Caller should change this soon!
     113             :      */
     114        4126 :     CurrentMemoryContext = TopMemoryContext;
     115             : 
     116             :     /*
     117             :      * Initialize ErrorContext as an AllocSetContext with slow growth rate ---
     118             :      * we don't really expect much to be allocated in it. More to the point,
     119             :      * require it to contain at least 8K at all times. This is the only case
     120             :      * where retained memory in a context is *essential* --- we want to be
     121             :      * sure ErrorContext still has some memory even if we've run out
     122             :      * elsewhere! Also, allow allocations in ErrorContext within a critical
     123             :      * section. Otherwise a PANIC will cause an assertion failure in the error
     124             :      * reporting code, before printing out the real cause of the failure.
     125             :      *
     126             :      * This should be the last step in this function, as elog.c assumes memory
     127             :      * management works once ErrorContext is non-null.
     128             :      */
     129        4126 :     ErrorContext = AllocSetContextCreate(TopMemoryContext,
     130             :                                          "ErrorContext",
     131             :                                          8 * 1024,
     132             :                                          8 * 1024,
     133             :                                          8 * 1024);
     134        4126 :     MemoryContextAllowInCriticalSection(ErrorContext, true);
     135        4126 : }
     136             : 
     137             : /*
     138             :  * MemoryContextReset
     139             :  *      Release all space allocated within a context and delete all its
     140             :  *      descendant contexts (but not the named context itself).
     141             :  */
     142             : void
     143   290366220 : MemoryContextReset(MemoryContext context)
     144             : {
     145             :     AssertArg(MemoryContextIsValid(context));
     146             : 
     147             :     /* save a function call in common case where there are no children */
     148   290366220 :     if (context->firstchild != NULL)
     149     1962926 :         MemoryContextDeleteChildren(context);
     150             : 
     151             :     /* save a function call if no pallocs since startup or last reset */
     152   290366220 :     if (!context->isReset)
     153    34303138 :         MemoryContextResetOnly(context);
     154   290366220 : }
     155             : 
     156             : /*
     157             :  * MemoryContextResetOnly
     158             :  *      Release all space allocated within a context.
     159             :  *      Nothing is done to the context's descendant contexts.
     160             :  */
     161             : void
     162    44162114 : MemoryContextResetOnly(MemoryContext context)
     163             : {
     164             :     AssertArg(MemoryContextIsValid(context));
     165             : 
     166             :     /* Nothing to do if no pallocs since startup or last reset */
     167    44162114 :     if (!context->isReset)
     168             :     {
     169    44161938 :         MemoryContextCallResetCallbacks(context);
     170             : 
     171             :         /*
     172             :          * If context->ident points into the context's memory, it will become
     173             :          * a dangling pointer.  We could prevent that by setting it to NULL
     174             :          * here, but that would break valid coding patterns that keep the
     175             :          * ident elsewhere, e.g. in a parent context.  Another idea is to use
     176             :          * MemoryContextContains(), but we don't require ident strings to be
     177             :          * in separately-palloc'd chunks, so that risks false positives.  So
     178             :          * for now we assume the programmer got it right.
     179             :          */
     180             : 
     181    44161938 :         context->methods->reset(context);
     182    44161938 :         context->isReset = true;
     183             :         VALGRIND_DESTROY_MEMPOOL(context);
     184             :         VALGRIND_CREATE_MEMPOOL(context, 0, false);
     185             :     }
     186    44162114 : }
     187             : 
     188             : /*
     189             :  * MemoryContextResetChildren
     190             :  *      Release all space allocated within a context's descendants,
     191             :  *      but don't delete the contexts themselves.  The named context
     192             :  *      itself is not touched.
     193             :  */
     194             : void
     195           0 : MemoryContextResetChildren(MemoryContext context)
     196             : {
     197             :     MemoryContext child;
     198             : 
     199             :     AssertArg(MemoryContextIsValid(context));
     200             : 
     201           0 :     for (child = context->firstchild; child != NULL; child = child->nextchild)
     202             :     {
     203           0 :         MemoryContextResetChildren(child);
     204           0 :         MemoryContextResetOnly(child);
     205             :     }
     206           0 : }
     207             : 
     208             : /*
     209             :  * MemoryContextDelete
     210             :  *      Delete a context and its descendants, and release all space
     211             :  *      allocated therein.
     212             :  *
     213             :  * The type-specific delete routine removes all storage for the context,
     214             :  * but we have to recurse to handle the children.
     215             :  * We must also delink the context from its parent, if it has one.
     216             :  */
     217             : void
     218    16066838 : MemoryContextDelete(MemoryContext context)
     219             : {
     220             :     AssertArg(MemoryContextIsValid(context));
     221             :     /* We had better not be deleting TopMemoryContext ... */
     222             :     Assert(context != TopMemoryContext);
     223             :     /* And not CurrentMemoryContext, either */
     224             :     Assert(context != CurrentMemoryContext);
     225             : 
     226             :     /* save a function call in common case where there are no children */
     227    16066838 :     if (context->firstchild != NULL)
     228     2610984 :         MemoryContextDeleteChildren(context);
     229             : 
     230             :     /*
     231             :      * It's not entirely clear whether 'tis better to do this before or after
     232             :      * delinking the context; but an error in a callback will likely result in
     233             :      * leaking the whole context (if it's not a root context) if we do it
     234             :      * after, so let's do it before.
     235             :      */
     236    16066838 :     MemoryContextCallResetCallbacks(context);
     237             : 
     238             :     /*
     239             :      * We delink the context from its parent before deleting it, so that if
     240             :      * there's an error we won't have deleted/busted contexts still attached
     241             :      * to the context tree.  Better a leak than a crash.
     242             :      */
     243    16066838 :     MemoryContextSetParent(context, NULL);
     244             : 
     245             :     /*
     246             :      * Also reset the context's ident pointer, in case it points into the
     247             :      * context.  This would only matter if someone tries to get stats on the
     248             :      * (already unlinked) context, which is unlikely, but let's be safe.
     249             :      */
     250    16066838 :     context->ident = NULL;
     251             : 
     252    16066838 :     context->methods->delete_context(context);
     253             : 
     254             :     VALGRIND_DESTROY_MEMPOOL(context);
     255    16066838 : }
     256             : 
     257             : /*
     258             :  * MemoryContextDeleteChildren
     259             :  *      Delete all the descendants of the named context and release all
     260             :  *      space allocated therein.  The named context itself is not touched.
     261             :  */
     262             : void
     263     5150542 : MemoryContextDeleteChildren(MemoryContext context)
     264             : {
     265             :     AssertArg(MemoryContextIsValid(context));
     266             : 
     267             :     /*
     268             :      * MemoryContextDelete will delink the child from me, so just iterate as
     269             :      * long as there is a child.
     270             :      */
     271     9856732 :     while (context->firstchild != NULL)
     272     4706190 :         MemoryContextDelete(context->firstchild);
     273     5150542 : }
     274             : 
     275             : /*
     276             :  * MemoryContextRegisterResetCallback
     277             :  *      Register a function to be called before next context reset/delete.
     278             :  *      Such callbacks will be called in reverse order of registration.
     279             :  *
     280             :  * The caller is responsible for allocating a MemoryContextCallback struct
     281             :  * to hold the info about this callback request, and for filling in the
     282             :  * "func" and "arg" fields in the struct to show what function to call with
     283             :  * what argument.  Typically the callback struct should be allocated within
     284             :  * the specified context, since that means it will automatically be freed
     285             :  * when no longer needed.
     286             :  *
     287             :  * There is no API for deregistering a callback once registered.  If you
     288             :  * want it to not do anything anymore, adjust the state pointed to by its
     289             :  * "arg" to indicate that.
     290             :  */
     291             : void
     292       60242 : MemoryContextRegisterResetCallback(MemoryContext context,
     293             :                                    MemoryContextCallback *cb)
     294             : {
     295             :     AssertArg(MemoryContextIsValid(context));
     296             : 
     297             :     /* Push onto head so this will be called before older registrants. */
     298       60242 :     cb->next = context->reset_cbs;
     299       60242 :     context->reset_cbs = cb;
     300             :     /* Mark the context as non-reset (it probably is already). */
     301       60242 :     context->isReset = false;
     302       60242 : }
     303             : 
     304             : /*
     305             :  * MemoryContextCallResetCallbacks
     306             :  *      Internal function to call all registered callbacks for context.
     307             :  */
     308             : static void
     309    60228776 : MemoryContextCallResetCallbacks(MemoryContext context)
     310             : {
     311             :     MemoryContextCallback *cb;
     312             : 
     313             :     /*
     314             :      * We pop each callback from the list before calling.  That way, if an
     315             :      * error occurs inside the callback, we won't try to call it a second time
     316             :      * in the likely event that we reset or delete the context later.
     317             :      */
     318    60288974 :     while ((cb = context->reset_cbs) != NULL)
     319             :     {
     320       60198 :         context->reset_cbs = cb->next;
     321       60198 :         cb->func(cb->arg);
     322             :     }
     323    60228776 : }
     324             : 
     325             : /*
     326             :  * MemoryContextSetIdentifier
     327             :  *      Set the identifier string for a memory context.
     328             :  *
     329             :  * An identifier can be provided to help distinguish among different contexts
     330             :  * of the same kind in memory context stats dumps.  The identifier string
     331             :  * must live at least as long as the context it is for; typically it is
     332             :  * allocated inside that context, so that it automatically goes away on
     333             :  * context deletion.  Pass id = NULL to forget any old identifier.
     334             :  */
     335             : void
     336     2820304 : MemoryContextSetIdentifier(MemoryContext context, const char *id)
     337             : {
     338             :     AssertArg(MemoryContextIsValid(context));
     339     2820304 :     context->ident = id;
     340     2820304 : }
     341             : 
     342             : /*
     343             :  * MemoryContextSetParent
     344             :  *      Change a context to belong to a new parent (or no parent).
     345             :  *
     346             :  * We provide this as an API function because it is sometimes useful to
     347             :  * change a context's lifespan after creation.  For example, a context
     348             :  * might be created underneath a transient context, filled with data,
     349             :  * and then reparented underneath CacheMemoryContext to make it long-lived.
     350             :  * In this way no special effort is needed to get rid of the context in case
     351             :  * a failure occurs before its contents are completely set up.
     352             :  *
     353             :  * Callers often assume that this function cannot fail, so don't put any
     354             :  * elog(ERROR) calls in it.
     355             :  *
     356             :  * A possible caller error is to reparent a context under itself, creating
     357             :  * a loop in the context graph.  We assert here that context != new_parent,
     358             :  * but checking for multi-level loops seems more trouble than it's worth.
     359             :  */
     360             : void
     361    16227890 : MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
     362             : {
     363             :     AssertArg(MemoryContextIsValid(context));
     364             :     AssertArg(context != new_parent);
     365             : 
     366             :     /* Fast path if it's got correct parent already */
     367    16227890 :     if (new_parent == context->parent)
     368        6160 :         return;
     369             : 
     370             :     /* Delink from existing parent, if any */
     371    16221730 :     if (context->parent)
     372             :     {
     373    16221730 :         MemoryContext parent = context->parent;
     374             : 
     375    16221730 :         if (context->prevchild != NULL)
     376     1098218 :             context->prevchild->nextchild = context->nextchild;
     377             :         else
     378             :         {
     379             :             Assert(parent->firstchild == context);
     380    15123512 :             parent->firstchild = context->nextchild;
     381             :         }
     382             : 
     383    16221730 :         if (context->nextchild != NULL)
     384     7386452 :             context->nextchild->prevchild = context->prevchild;
     385             :     }
     386             : 
     387             :     /* And relink */
     388    16221730 :     if (new_parent)
     389             :     {
     390             :         AssertArg(MemoryContextIsValid(new_parent));
     391      154892 :         context->parent = new_parent;
     392      154892 :         context->prevchild = NULL;
     393      154892 :         context->nextchild = new_parent->firstchild;
     394      154892 :         if (new_parent->firstchild != NULL)
     395      141008 :             new_parent->firstchild->prevchild = context;
     396      154892 :         new_parent->firstchild = context;
     397             :     }
     398             :     else
     399             :     {
     400    16066838 :         context->parent = NULL;
     401    16066838 :         context->prevchild = NULL;
     402    16066838 :         context->nextchild = NULL;
     403             :     }
     404             : }
     405             : 
     406             : /*
     407             :  * MemoryContextAllowInCriticalSection
     408             :  *      Allow/disallow allocations in this memory context within a critical
     409             :  *      section.
     410             :  *
     411             :  * Normally, memory allocations are not allowed within a critical section,
     412             :  * because a failure would lead to PANIC.  There are a few exceptions to
     413             :  * that, like allocations related to debugging code that is not supposed to
     414             :  * be enabled in production.  This function can be used to exempt specific
     415             :  * memory contexts from the assertion in palloc().
     416             :  */
     417             : void
     418        5658 : MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
     419             : {
     420             :     AssertArg(MemoryContextIsValid(context));
     421             : 
     422        5658 :     context->allowInCritSection = allow;
     423        5658 : }
     424             : 
     425             : /*
     426             :  * GetMemoryChunkSpace
     427             :  *      Given a currently-allocated chunk, determine the total space
     428             :  *      it occupies (including all memory-allocation overhead).
     429             :  *
     430             :  * This is useful for measuring the total space occupied by a set of
     431             :  * allocated chunks.
     432             :  */
     433             : Size
     434    74151328 : GetMemoryChunkSpace(void *pointer)
     435             : {
     436    74151328 :     MemoryContext context = GetMemoryChunkContext(pointer);
     437             : 
     438    74151328 :     return context->methods->get_chunk_space(context, pointer);
     439             : }
     440             : 
     441             : /*
     442             :  * MemoryContextGetParent
     443             :  *      Get the parent context (if any) of the specified context
     444             :  */
     445             : MemoryContext
     446       10516 : MemoryContextGetParent(MemoryContext context)
     447             : {
     448             :     AssertArg(MemoryContextIsValid(context));
     449             : 
     450       10516 :     return context->parent;
     451             : }
     452             : 
     453             : /*
     454             :  * MemoryContextIsEmpty
     455             :  *      Is a memory context empty of any allocated space?
     456             :  */
     457             : bool
     458        6442 : MemoryContextIsEmpty(MemoryContext context)
     459             : {
     460             :     AssertArg(MemoryContextIsValid(context));
     461             : 
     462             :     /*
     463             :      * For now, we consider a memory context nonempty if it has any children;
     464             :      * perhaps this should be changed later.
     465             :      */
     466        6442 :     if (context->firstchild != NULL)
     467           2 :         return false;
     468             :     /* Otherwise use the type-specific inquiry */
     469        6440 :     return context->methods->is_empty(context);
     470             : }
     471             : 
     472             : /*
     473             :  * Find the memory allocated to blocks for this memory context. If recurse is
     474             :  * true, also include children.
     475             :  */
     476             : Size
     477     1508168 : MemoryContextMemAllocated(MemoryContext context, bool recurse)
     478             : {
     479     1508168 :     Size        total = context->mem_allocated;
     480             : 
     481             :     AssertArg(MemoryContextIsValid(context));
     482             : 
     483     1508168 :     if (recurse)
     484             :     {
     485             :         MemoryContext child;
     486             : 
     487     2148612 :         for (child = context->firstchild;
     488             :              child != NULL;
     489      640444 :              child = child->nextchild)
     490      640444 :             total += MemoryContextMemAllocated(child, true);
     491             :     }
     492             : 
     493     1508168 :     return total;
     494             : }
     495             : 
     496             : /*
     497             :  * MemoryContextStats
     498             :  *      Print statistics about the named context and all its descendants.
     499             :  *
     500             :  * This is just a debugging utility, so it's not very fancy.  However, we do
     501             :  * make some effort to summarize when the output would otherwise be very long.
     502             :  * The statistics are sent to stderr.
     503             :  */
     504             : void
     505           0 : MemoryContextStats(MemoryContext context)
     506             : {
     507             :     /* A hard-wired limit on the number of children is usually good enough */
     508           0 :     MemoryContextStatsDetail(context, 100, true);
     509           0 : }
     510             : 
     511             : /*
     512             :  * MemoryContextStatsDetail
     513             :  *
     514             :  * Entry point for use if you want to vary the number of child contexts shown.
     515             :  *
     516             :  * If print_to_stderr is true, print statistics about the memory contexts
     517             :  * with fprintf(stderr), otherwise use ereport().
     518             :  */
     519             : void
     520           8 : MemoryContextStatsDetail(MemoryContext context, int max_children,
     521             :                          bool print_to_stderr)
     522             : {
     523             :     MemoryContextCounters grand_totals;
     524             : 
     525           8 :     memset(&grand_totals, 0, sizeof(grand_totals));
     526             : 
     527           8 :     MemoryContextStatsInternal(context, 0, true, max_children, &grand_totals, print_to_stderr);
     528             : 
     529           8 :     if (print_to_stderr)
     530           0 :         fprintf(stderr,
     531             :                 "Grand total: %zu bytes in %zd blocks; %zu free (%zd chunks); %zu used\n",
     532             :                 grand_totals.totalspace, grand_totals.nblocks,
     533             :                 grand_totals.freespace, grand_totals.freechunks,
     534           0 :                 grand_totals.totalspace - grand_totals.freespace);
     535             :     else
     536             : 
     537             :         /*
     538             :          * Use LOG_SERVER_ONLY to prevent the memory contexts from being sent
     539             :          * to the connected client.
     540             :          *
     541             :          * We don't buffer the information about all memory contexts in a
     542             :          * backend into StringInfo and log it as one message. Otherwise which
     543             :          * may require the buffer to be enlarged very much and lead to OOM
     544             :          * error since there can be a large number of memory contexts in a
     545             :          * backend. Instead, we log one message per memory context.
     546             :          */
     547           8 :         ereport(LOG_SERVER_ONLY,
     548             :                 (errhidestmt(true),
     549             :                  errhidecontext(true),
     550             :                  errmsg_internal("Grand total: %zu bytes in %zd blocks; %zu free (%zd chunks); %zu used",
     551             :                                  grand_totals.totalspace, grand_totals.nblocks,
     552             :                                  grand_totals.freespace, grand_totals.freechunks,
     553             :                                  grand_totals.totalspace - grand_totals.freespace)));
     554           8 : }
     555             : 
     556             : /*
     557             :  * MemoryContextStatsInternal
     558             :  *      One recursion level for MemoryContextStats
     559             :  *
     560             :  * Print this context if print is true, but in any case accumulate counts into
     561             :  * *totals (if given).
     562             :  */
     563             : static void
     564         868 : MemoryContextStatsInternal(MemoryContext context, int level,
     565             :                            bool print, int max_children,
     566             :                            MemoryContextCounters *totals,
     567             :                            bool print_to_stderr)
     568             : {
     569             :     MemoryContextCounters local_totals;
     570             :     MemoryContext child;
     571             :     int         ichild;
     572             : 
     573             :     AssertArg(MemoryContextIsValid(context));
     574             : 
     575             :     /* Examine the context itself */
     576         868 :     context->methods->stats(context,
     577             :                             print ? MemoryContextStatsPrint : NULL,
     578             :                             (void *) &level,
     579             :                             totals, print_to_stderr);
     580             : 
     581             :     /*
     582             :      * Examine children.  If there are more than max_children of them, we do
     583             :      * not print the rest explicitly, but just summarize them.
     584             :      */
     585         868 :     memset(&local_totals, 0, sizeof(local_totals));
     586             : 
     587        1728 :     for (child = context->firstchild, ichild = 0;
     588             :          child != NULL;
     589         860 :          child = child->nextchild, ichild++)
     590             :     {
     591         860 :         if (ichild < max_children)
     592         860 :             MemoryContextStatsInternal(child, level + 1,
     593             :                                        print, max_children,
     594             :                                        totals,
     595             :                                        print_to_stderr);
     596             :         else
     597           0 :             MemoryContextStatsInternal(child, level + 1,
     598             :                                        false, max_children,
     599             :                                        &local_totals,
     600             :                                        print_to_stderr);
     601             :     }
     602             : 
     603             :     /* Deal with excess children */
     604         868 :     if (ichild > max_children)
     605             :     {
     606           0 :         if (print)
     607             :         {
     608           0 :             if (print_to_stderr)
     609             :             {
     610             :                 int         i;
     611             : 
     612           0 :                 for (i = 0; i <= level; i++)
     613           0 :                     fprintf(stderr, "  ");
     614           0 :                 fprintf(stderr,
     615             :                         "%d more child contexts containing %zu total in %zd blocks; %zu free (%zd chunks); %zu used\n",
     616             :                         ichild - max_children,
     617             :                         local_totals.totalspace,
     618             :                         local_totals.nblocks,
     619             :                         local_totals.freespace,
     620             :                         local_totals.freechunks,
     621           0 :                         local_totals.totalspace - local_totals.freespace);
     622             :             }
     623             :             else
     624           0 :                 ereport(LOG_SERVER_ONLY,
     625             :                         (errhidestmt(true),
     626             :                          errhidecontext(true),
     627             :                          errmsg_internal("level: %d; %d more child contexts containing %zu total in %zd blocks; %zu free (%zd chunks); %zu used",
     628             :                                          level,
     629             :                                          ichild - max_children,
     630             :                                          local_totals.totalspace,
     631             :                                          local_totals.nblocks,
     632             :                                          local_totals.freespace,
     633             :                                          local_totals.freechunks,
     634             :                                          local_totals.totalspace - local_totals.freespace)));
     635             :         }
     636             : 
     637           0 :         if (totals)
     638             :         {
     639           0 :             totals->nblocks += local_totals.nblocks;
     640           0 :             totals->freechunks += local_totals.freechunks;
     641           0 :             totals->totalspace += local_totals.totalspace;
     642           0 :             totals->freespace += local_totals.freespace;
     643             :         }
     644             :     }
     645         868 : }
     646             : 
     647             : /*
     648             :  * MemoryContextStatsPrint
     649             :  *      Print callback used by MemoryContextStatsInternal
     650             :  *
     651             :  * For now, the passthru pointer just points to "int level"; later we might
     652             :  * make that more complicated.
     653             :  */
     654             : static void
     655         868 : MemoryContextStatsPrint(MemoryContext context, void *passthru,
     656             :                         const char *stats_string,
     657             :                         bool print_to_stderr)
     658             : {
     659         868 :     int         level = *(int *) passthru;
     660         868 :     const char *name = context->name;
     661         868 :     const char *ident = context->ident;
     662             :     char        truncated_ident[110];
     663             :     int         i;
     664             : 
     665             :     /*
     666             :      * It seems preferable to label dynahash contexts with just the hash table
     667             :      * name.  Those are already unique enough, so the "dynahash" part isn't
     668             :      * very helpful, and this way is more consistent with pre-v11 practice.
     669             :      */
     670         868 :     if (ident && strcmp(name, "dynahash") == 0)
     671             :     {
     672          76 :         name = ident;
     673          76 :         ident = NULL;
     674             :     }
     675             : 
     676         868 :     truncated_ident[0] = '\0';
     677             : 
     678         868 :     if (ident)
     679             :     {
     680             :         /*
     681             :          * Some contexts may have very long identifiers (e.g., SQL queries).
     682             :          * Arbitrarily truncate at 100 bytes, but be careful not to break
     683             :          * multibyte characters.  Also, replace ASCII control characters, such
     684             :          * as newlines, with spaces.
     685             :          */
     686         684 :         int         idlen = strlen(ident);
     687         684 :         bool        truncated = false;
     688             : 
     689         684 :         strcpy(truncated_ident, ": ");
     690         684 :         i = strlen(truncated_ident);
     691             : 
     692         684 :         if (idlen > 100)
     693             :         {
     694           0 :             idlen = pg_mbcliplen(ident, idlen, 100);
     695           0 :             truncated = true;
     696             :         }
     697             : 
     698       18964 :         while (idlen-- > 0)
     699             :         {
     700       18280 :             unsigned char c = *ident++;
     701             : 
     702       18280 :             if (c < ' ')
     703           0 :                 c = ' ';
     704       18280 :             truncated_ident[i++] = c;
     705             :         }
     706         684 :         truncated_ident[i] = '\0';
     707             : 
     708         684 :         if (truncated)
     709           0 :             strcat(truncated_ident, "...");
     710             :     }
     711             : 
     712         868 :     if (print_to_stderr)
     713             :     {
     714           0 :         for (i = 0; i < level; i++)
     715           0 :             fprintf(stderr, "  ");
     716           0 :         fprintf(stderr, "%s: %s%s\n", name, stats_string, truncated_ident);
     717             :     }
     718             :     else
     719         868 :         ereport(LOG_SERVER_ONLY,
     720             :                 (errhidestmt(true),
     721             :                  errhidecontext(true),
     722             :                  errmsg_internal("level: %d; %s: %s%s",
     723             :                                  level, name, stats_string, truncated_ident)));
     724         868 : }
     725             : 
     726             : /*
     727             :  * MemoryContextCheck
     728             :  *      Check all chunks in the named context.
     729             :  *
     730             :  * This is just a debugging utility, so it's not fancy.
     731             :  */
     732             : #ifdef MEMORY_CONTEXT_CHECKING
     733             : void
     734             : MemoryContextCheck(MemoryContext context)
     735             : {
     736             :     MemoryContext child;
     737             : 
     738             :     AssertArg(MemoryContextIsValid(context));
     739             : 
     740             :     context->methods->check(context);
     741             :     for (child = context->firstchild; child != NULL; child = child->nextchild)
     742             :         MemoryContextCheck(child);
     743             : }
     744             : #endif
     745             : 
     746             : /*
     747             :  * MemoryContextContains
     748             :  *      Detect whether an allocated chunk of memory belongs to a given
     749             :  *      context or not.
     750             :  *
     751             :  * Caution: this test is reliable as long as 'pointer' does point to
     752             :  * a chunk of memory allocated from *some* context.  If 'pointer' points
     753             :  * at memory obtained in some other way, there is a small chance of a
     754             :  * false-positive result, since the bits right before it might look like
     755             :  * a valid chunk header by chance.
     756             :  */
     757             : bool
     758      253328 : MemoryContextContains(MemoryContext context, void *pointer)
     759             : {
     760             :     MemoryContext ptr_context;
     761             : 
     762             :     /*
     763             :      * NB: Can't use GetMemoryChunkContext() here - that performs assertions
     764             :      * that aren't acceptable here since we might be passed memory not
     765             :      * allocated by any memory context.
     766             :      *
     767             :      * Try to detect bogus pointers handed to us, poorly though we can.
     768             :      * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
     769             :      * allocated chunk.
     770             :      */
     771      253328 :     if (pointer == NULL || pointer != (void *) MAXALIGN(pointer))
     772           0 :         return false;
     773             : 
     774             :     /*
     775             :      * OK, it's probably safe to look at the context.
     776             :      */
     777      253328 :     ptr_context = *(MemoryContext *) (((char *) pointer) - sizeof(void *));
     778             : 
     779      253328 :     return ptr_context == context;
     780             : }
     781             : 
     782             : /*
     783             :  * MemoryContextCreate
     784             :  *      Context-type-independent part of context creation.
     785             :  *
     786             :  * This is only intended to be called by context-type-specific
     787             :  * context creation routines, not by the unwashed masses.
     788             :  *
     789             :  * The memory context creation procedure goes like this:
     790             :  *  1.  Context-type-specific routine makes some initial space allocation,
     791             :  *      including enough space for the context header.  If it fails,
     792             :  *      it can ereport() with no damage done.
     793             :  *  2.  Context-type-specific routine sets up all type-specific fields of
     794             :  *      the header (those beyond MemoryContextData proper), as well as any
     795             :  *      other management fields it needs to have a fully valid context.
     796             :  *      Usually, failure in this step is impossible, but if it's possible
     797             :  *      the initial space allocation should be freed before ereport'ing.
     798             :  *  3.  Context-type-specific routine calls MemoryContextCreate() to fill in
     799             :  *      the generic header fields and link the context into the context tree.
     800             :  *  4.  We return to the context-type-specific routine, which finishes
     801             :  *      up type-specific initialization.  This routine can now do things
     802             :  *      that might fail (like allocate more memory), so long as it's
     803             :  *      sure the node is left in a state that delete will handle.
     804             :  *
     805             :  * node: the as-yet-uninitialized common part of the context header node.
     806             :  * tag: NodeTag code identifying the memory context type.
     807             :  * methods: context-type-specific methods (usually statically allocated).
     808             :  * parent: parent context, or NULL if this will be a top-level context.
     809             :  * name: name of context (must be statically allocated).
     810             :  *
     811             :  * Context routines generally assume that MemoryContextCreate can't fail,
     812             :  * so this can contain Assert but not elog/ereport.
     813             :  */
     814             : void
     815    17571566 : MemoryContextCreate(MemoryContext node,
     816             :                     NodeTag tag,
     817             :                     const MemoryContextMethods *methods,
     818             :                     MemoryContext parent,
     819             :                     const char *name)
     820             : {
     821             :     /* Creating new memory contexts is not allowed in a critical section */
     822             :     Assert(CritSectionCount == 0);
     823             : 
     824             :     /* Initialize all standard fields of memory context header */
     825    17571566 :     node->type = tag;
     826    17571566 :     node->isReset = true;
     827    17571566 :     node->methods = methods;
     828    17571566 :     node->parent = parent;
     829    17571566 :     node->firstchild = NULL;
     830    17571566 :     node->mem_allocated = 0;
     831    17571566 :     node->prevchild = NULL;
     832    17571566 :     node->name = name;
     833    17571566 :     node->ident = NULL;
     834    17571566 :     node->reset_cbs = NULL;
     835             : 
     836             :     /* OK to link node into context tree */
     837    17571566 :     if (parent)
     838             :     {
     839    17566958 :         node->nextchild = parent->firstchild;
     840    17566958 :         if (parent->firstchild != NULL)
     841     8819252 :             parent->firstchild->prevchild = node;
     842    17566958 :         parent->firstchild = node;
     843             :         /* inherit allowInCritSection flag from parent */
     844    17566958 :         node->allowInCritSection = parent->allowInCritSection;
     845             :     }
     846             :     else
     847             :     {
     848        4608 :         node->nextchild = NULL;
     849        4608 :         node->allowInCritSection = false;
     850             :     }
     851             : 
     852             :     VALGRIND_CREATE_MEMPOOL(node, 0, false);
     853    17571566 : }
     854             : 
     855             : /*
     856             :  * MemoryContextAlloc
     857             :  *      Allocate space within the specified context.
     858             :  *
     859             :  * This could be turned into a macro, but we'd have to import
     860             :  * nodes/memnodes.h into postgres.h which seems a bad idea.
     861             :  */
     862             : void *
     863   249774514 : MemoryContextAlloc(MemoryContext context, Size size)
     864             : {
     865             :     void       *ret;
     866             : 
     867             :     AssertArg(MemoryContextIsValid(context));
     868             :     AssertNotInCriticalSection(context);
     869             : 
     870   249774514 :     if (!AllocSizeIsValid(size))
     871           0 :         elog(ERROR, "invalid memory alloc request size %zu", size);
     872             : 
     873   249774514 :     context->isReset = false;
     874             : 
     875   249774514 :     ret = context->methods->alloc(context, size);
     876   249774514 :     if (unlikely(ret == NULL))
     877             :     {
     878           0 :         MemoryContextStats(TopMemoryContext);
     879             : 
     880             :         /*
     881             :          * Here, and elsewhere in this module, we show the target context's
     882             :          * "name" but not its "ident" (if any) in user-visible error messages.
     883             :          * The "ident" string might contain security-sensitive data, such as
     884             :          * values in SQL commands.
     885             :          */
     886           0 :         ereport(ERROR,
     887             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
     888             :                  errmsg("out of memory"),
     889             :                  errdetail("Failed on request of size %zu in memory context \"%s\".",
     890             :                            size, context->name)));
     891             :     }
     892             : 
     893             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
     894             : 
     895   249774514 :     return ret;
     896             : }
     897             : 
     898             : /*
     899             :  * MemoryContextAllocZero
     900             :  *      Like MemoryContextAlloc, but clears allocated memory
     901             :  *
     902             :  *  We could just call MemoryContextAlloc then clear the memory, but this
     903             :  *  is a very common combination, so we provide the combined operation.
     904             :  */
     905             : void *
     906    15987494 : MemoryContextAllocZero(MemoryContext context, Size size)
     907             : {
     908             :     void       *ret;
     909             : 
     910             :     AssertArg(MemoryContextIsValid(context));
     911             :     AssertNotInCriticalSection(context);
     912             : 
     913    15987494 :     if (!AllocSizeIsValid(size))
     914           0 :         elog(ERROR, "invalid memory alloc request size %zu", size);
     915             : 
     916    15987494 :     context->isReset = false;
     917             : 
     918    15987494 :     ret = context->methods->alloc(context, size);
     919    15987494 :     if (unlikely(ret == NULL))
     920             :     {
     921           0 :         MemoryContextStats(TopMemoryContext);
     922           0 :         ereport(ERROR,
     923             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
     924             :                  errmsg("out of memory"),
     925             :                  errdetail("Failed on request of size %zu in memory context \"%s\".",
     926             :                            size, context->name)));
     927             :     }
     928             : 
     929             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
     930             : 
     931   246692700 :     MemSetAligned(ret, 0, size);
     932             : 
     933    15987494 :     return ret;
     934             : }
     935             : 
     936             : /*
     937             :  * MemoryContextAllocZeroAligned
     938             :  *      MemoryContextAllocZero where length is suitable for MemSetLoop
     939             :  *
     940             :  *  This might seem overly specialized, but it's not because newNode()
     941             :  *  is so often called with compile-time-constant sizes.
     942             :  */
     943             : void *
     944   376613308 : MemoryContextAllocZeroAligned(MemoryContext context, Size size)
     945             : {
     946             :     void       *ret;
     947             : 
     948             :     AssertArg(MemoryContextIsValid(context));
     949             :     AssertNotInCriticalSection(context);
     950             : 
     951   376613308 :     if (!AllocSizeIsValid(size))
     952           0 :         elog(ERROR, "invalid memory alloc request size %zu", size);
     953             : 
     954   376613308 :     context->isReset = false;
     955             : 
     956   376613308 :     ret = context->methods->alloc(context, size);
     957   376613308 :     if (unlikely(ret == NULL))
     958             :     {
     959           0 :         MemoryContextStats(TopMemoryContext);
     960           0 :         ereport(ERROR,
     961             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
     962             :                  errmsg("out of memory"),
     963             :                  errdetail("Failed on request of size %zu in memory context \"%s\".",
     964             :                            size, context->name)));
     965             :     }
     966             : 
     967             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
     968             : 
     969  2812763558 :     MemSetLoop(ret, 0, size);
     970             : 
     971   376613308 :     return ret;
     972             : }
     973             : 
     974             : /*
     975             :  * MemoryContextAllocExtended
     976             :  *      Allocate space within the specified context using the given flags.
     977             :  */
     978             : void *
     979       15706 : MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
     980             : {
     981             :     void       *ret;
     982             : 
     983             :     AssertArg(MemoryContextIsValid(context));
     984             :     AssertNotInCriticalSection(context);
     985             : 
     986       15706 :     if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
     987       15706 :         ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
     988           0 :         elog(ERROR, "invalid memory alloc request size %zu", size);
     989             : 
     990       15706 :     context->isReset = false;
     991             : 
     992       15706 :     ret = context->methods->alloc(context, size);
     993       15706 :     if (unlikely(ret == NULL))
     994             :     {
     995           0 :         if ((flags & MCXT_ALLOC_NO_OOM) == 0)
     996             :         {
     997           0 :             MemoryContextStats(TopMemoryContext);
     998           0 :             ereport(ERROR,
     999             :                     (errcode(ERRCODE_OUT_OF_MEMORY),
    1000             :                      errmsg("out of memory"),
    1001             :                      errdetail("Failed on request of size %zu in memory context \"%s\".",
    1002             :                                size, context->name)));
    1003             :         }
    1004           0 :         return NULL;
    1005             :     }
    1006             : 
    1007             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1008             : 
    1009       15706 :     if ((flags & MCXT_ALLOC_ZERO) != 0)
    1010      142810 :         MemSetAligned(ret, 0, size);
    1011             : 
    1012       15706 :     return ret;
    1013             : }
    1014             : 
    1015             : /*
    1016             :  * HandleLogMemoryContextInterrupt
    1017             :  *      Handle receipt of an interrupt indicating logging of memory
    1018             :  *      contexts.
    1019             :  *
    1020             :  * All the actual work is deferred to ProcessLogMemoryContextInterrupt(),
    1021             :  * because we cannot safely emit a log message inside the signal handler.
    1022             :  */
    1023             : void
    1024           8 : HandleLogMemoryContextInterrupt(void)
    1025             : {
    1026           8 :     InterruptPending = true;
    1027           8 :     LogMemoryContextPending = true;
    1028             :     /* latch will be set by procsignal_sigusr1_handler */
    1029           8 : }
    1030             : 
    1031             : /*
    1032             :  * ProcessLogMemoryContextInterrupt
    1033             :  *      Perform logging of memory contexts of this backend process.
    1034             :  *
    1035             :  * Any backend that participates in ProcSignal signaling must arrange
    1036             :  * to call this function if we see LogMemoryContextPending set.
    1037             :  * It is called from CHECK_FOR_INTERRUPTS(), which is enough because
    1038             :  * the target process for logging of memory contexts is a backend.
    1039             :  */
    1040             : void
    1041           8 : ProcessLogMemoryContextInterrupt(void)
    1042             : {
    1043           8 :     LogMemoryContextPending = false;
    1044             : 
    1045           8 :     ereport(LOG,
    1046             :             (errmsg("logging memory contexts of PID %d", MyProcPid)));
    1047             : 
    1048             :     /*
    1049             :      * When a backend process is consuming huge memory, logging all its memory
    1050             :      * contexts might overrun available disk space. To prevent this, we limit
    1051             :      * the number of child contexts to log per parent to 100.
    1052             :      *
    1053             :      * As with MemoryContextStats(), we suppose that practical cases where the
    1054             :      * dump gets long will typically be huge numbers of siblings under the
    1055             :      * same parent context; while the additional debugging value from seeing
    1056             :      * details about individual siblings beyond 100 will not be large.
    1057             :      */
    1058           8 :     MemoryContextStatsDetail(TopMemoryContext, 100, false);
    1059           8 : }
    1060             : 
    1061             : void *
    1062   585979422 : palloc(Size size)
    1063             : {
    1064             :     /* duplicates MemoryContextAlloc to avoid increased overhead */
    1065             :     void       *ret;
    1066   585979422 :     MemoryContext context = CurrentMemoryContext;
    1067             : 
    1068             :     AssertArg(MemoryContextIsValid(context));
    1069             :     AssertNotInCriticalSection(context);
    1070             : 
    1071   585979422 :     if (!AllocSizeIsValid(size))
    1072           0 :         elog(ERROR, "invalid memory alloc request size %zu", size);
    1073             : 
    1074   585979422 :     context->isReset = false;
    1075             : 
    1076   585979422 :     ret = context->methods->alloc(context, size);
    1077   585979422 :     if (unlikely(ret == NULL))
    1078             :     {
    1079           0 :         MemoryContextStats(TopMemoryContext);
    1080           0 :         ereport(ERROR,
    1081             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
    1082             :                  errmsg("out of memory"),
    1083             :                  errdetail("Failed on request of size %zu in memory context \"%s\".",
    1084             :                            size, context->name)));
    1085             :     }
    1086             : 
    1087             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1088             : 
    1089   585979422 :     return ret;
    1090             : }
    1091             : 
    1092             : void *
    1093   219256688 : palloc0(Size size)
    1094             : {
    1095             :     /* duplicates MemoryContextAllocZero to avoid increased overhead */
    1096             :     void       *ret;
    1097   219256688 :     MemoryContext context = CurrentMemoryContext;
    1098             : 
    1099             :     AssertArg(MemoryContextIsValid(context));
    1100             :     AssertNotInCriticalSection(context);
    1101             : 
    1102   219256688 :     if (!AllocSizeIsValid(size))
    1103           0 :         elog(ERROR, "invalid memory alloc request size %zu", size);
    1104             : 
    1105   219256688 :     context->isReset = false;
    1106             : 
    1107   219256688 :     ret = context->methods->alloc(context, size);
    1108   219256688 :     if (unlikely(ret == NULL))
    1109             :     {
    1110           0 :         MemoryContextStats(TopMemoryContext);
    1111           0 :         ereport(ERROR,
    1112             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
    1113             :                  errmsg("out of memory"),
    1114             :                  errdetail("Failed on request of size %zu in memory context \"%s\".",
    1115             :                            size, context->name)));
    1116             :     }
    1117             : 
    1118             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1119             : 
    1120  2145087116 :     MemSetAligned(ret, 0, size);
    1121             : 
    1122   219256688 :     return ret;
    1123             : }
    1124             : 
    1125             : void *
    1126       16054 : palloc_extended(Size size, int flags)
    1127             : {
    1128             :     /* duplicates MemoryContextAllocExtended to avoid increased overhead */
    1129             :     void       *ret;
    1130       16054 :     MemoryContext context = CurrentMemoryContext;
    1131             : 
    1132             :     AssertArg(MemoryContextIsValid(context));
    1133             :     AssertNotInCriticalSection(context);
    1134             : 
    1135       16054 :     if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
    1136       16054 :         ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
    1137           0 :         elog(ERROR, "invalid memory alloc request size %zu", size);
    1138             : 
    1139       16054 :     context->isReset = false;
    1140             : 
    1141       16054 :     ret = context->methods->alloc(context, size);
    1142       16054 :     if (unlikely(ret == NULL))
    1143             :     {
    1144           0 :         if ((flags & MCXT_ALLOC_NO_OOM) == 0)
    1145             :         {
    1146           0 :             MemoryContextStats(TopMemoryContext);
    1147           0 :             ereport(ERROR,
    1148             :                     (errcode(ERRCODE_OUT_OF_MEMORY),
    1149             :                      errmsg("out of memory"),
    1150             :                      errdetail("Failed on request of size %zu in memory context \"%s\".",
    1151             :                                size, context->name)));
    1152             :         }
    1153           0 :         return NULL;
    1154             :     }
    1155             : 
    1156             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1157             : 
    1158       16054 :     if ((flags & MCXT_ALLOC_ZERO) != 0)
    1159        4008 :         MemSetAligned(ret, 0, size);
    1160             : 
    1161       16054 :     return ret;
    1162             : }
    1163             : 
    1164             : /*
    1165             :  * pfree
    1166             :  *      Release an allocated chunk.
    1167             :  */
    1168             : void
    1169   406132886 : pfree(void *pointer)
    1170             : {
    1171   406132886 :     MemoryContext context = GetMemoryChunkContext(pointer);
    1172             : 
    1173   406132886 :     context->methods->free_p(context, pointer);
    1174             :     VALGRIND_MEMPOOL_FREE(context, pointer);
    1175   406132886 : }
    1176             : 
    1177             : /*
    1178             :  * repalloc
    1179             :  *      Adjust the size of a previously allocated chunk.
    1180             :  */
    1181             : void *
    1182     9765882 : repalloc(void *pointer, Size size)
    1183             : {
    1184     9765882 :     MemoryContext context = GetMemoryChunkContext(pointer);
    1185             :     void       *ret;
    1186             : 
    1187     9765882 :     if (!AllocSizeIsValid(size))
    1188           0 :         elog(ERROR, "invalid memory alloc request size %zu", size);
    1189             : 
    1190             :     AssertNotInCriticalSection(context);
    1191             : 
    1192             :     /* isReset must be false already */
    1193             :     Assert(!context->isReset);
    1194             : 
    1195     9765882 :     ret = context->methods->realloc(context, pointer, size);
    1196     9765882 :     if (unlikely(ret == NULL))
    1197             :     {
    1198           0 :         MemoryContextStats(TopMemoryContext);
    1199           0 :         ereport(ERROR,
    1200             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
    1201             :                  errmsg("out of memory"),
    1202             :                  errdetail("Failed on request of size %zu in memory context \"%s\".",
    1203             :                            size, context->name)));
    1204             :     }
    1205             : 
    1206             :     VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
    1207             : 
    1208     9765882 :     return ret;
    1209             : }
    1210             : 
    1211             : /*
    1212             :  * MemoryContextAllocHuge
    1213             :  *      Allocate (possibly-expansive) space within the specified context.
    1214             :  *
    1215             :  * See considerations in comment at MaxAllocHugeSize.
    1216             :  */
    1217             : void *
    1218        1848 : MemoryContextAllocHuge(MemoryContext context, Size size)
    1219             : {
    1220             :     void       *ret;
    1221             : 
    1222             :     AssertArg(MemoryContextIsValid(context));
    1223             :     AssertNotInCriticalSection(context);
    1224             : 
    1225        1848 :     if (!AllocHugeSizeIsValid(size))
    1226           0 :         elog(ERROR, "invalid memory alloc request size %zu", size);
    1227             : 
    1228        1848 :     context->isReset = false;
    1229             : 
    1230        1848 :     ret = context->methods->alloc(context, size);
    1231        1848 :     if (unlikely(ret == NULL))
    1232             :     {
    1233           0 :         MemoryContextStats(TopMemoryContext);
    1234           0 :         ereport(ERROR,
    1235             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
    1236             :                  errmsg("out of memory"),
    1237             :                  errdetail("Failed on request of size %zu in memory context \"%s\".",
    1238             :                            size, context->name)));
    1239             :     }
    1240             : 
    1241             :     VALGRIND_MEMPOOL_ALLOC(context, ret, size);
    1242             : 
    1243        1848 :     return ret;
    1244             : }
    1245             : 
    1246             : /*
    1247             :  * repalloc_huge
    1248             :  *      Adjust the size of a previously allocated chunk, permitting a large
    1249             :  *      value.  The previous allocation need not have been "huge".
    1250             :  */
    1251             : void *
    1252       63164 : repalloc_huge(void *pointer, Size size)
    1253             : {
    1254       63164 :     MemoryContext context = GetMemoryChunkContext(pointer);
    1255             :     void       *ret;
    1256             : 
    1257       63164 :     if (!AllocHugeSizeIsValid(size))
    1258           0 :         elog(ERROR, "invalid memory alloc request size %zu", size);
    1259             : 
    1260             :     AssertNotInCriticalSection(context);
    1261             : 
    1262             :     /* isReset must be false already */
    1263             :     Assert(!context->isReset);
    1264             : 
    1265       63164 :     ret = context->methods->realloc(context, pointer, size);
    1266       63164 :     if (unlikely(ret == NULL))
    1267             :     {
    1268           0 :         MemoryContextStats(TopMemoryContext);
    1269           0 :         ereport(ERROR,
    1270             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
    1271             :                  errmsg("out of memory"),
    1272             :                  errdetail("Failed on request of size %zu in memory context \"%s\".",
    1273             :                            size, context->name)));
    1274             :     }
    1275             : 
    1276             :     VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
    1277             : 
    1278       63164 :     return ret;
    1279             : }
    1280             : 
    1281             : /*
    1282             :  * MemoryContextStrdup
    1283             :  *      Like strdup(), but allocate from the specified context
    1284             :  */
    1285             : char *
    1286   165135338 : MemoryContextStrdup(MemoryContext context, const char *string)
    1287             : {
    1288             :     char       *nstr;
    1289   165135338 :     Size        len = strlen(string) + 1;
    1290             : 
    1291   165135338 :     nstr = (char *) MemoryContextAlloc(context, len);
    1292             : 
    1293   165135338 :     memcpy(nstr, string, len);
    1294             : 
    1295   165135338 :     return nstr;
    1296             : }
    1297             : 
    1298             : char *
    1299   163439196 : pstrdup(const char *in)
    1300             : {
    1301   163439196 :     return MemoryContextStrdup(CurrentMemoryContext, in);
    1302             : }
    1303             : 
    1304             : /*
    1305             :  * pnstrdup
    1306             :  *      Like pstrdup(), but append null byte to a
    1307             :  *      not-necessarily-null-terminated input string.
    1308             :  */
    1309             : char *
    1310     1087798 : pnstrdup(const char *in, Size len)
    1311             : {
    1312             :     char       *out;
    1313             : 
    1314     1087798 :     len = strnlen(in, len);
    1315             : 
    1316     1087798 :     out = palloc(len + 1);
    1317     1087798 :     memcpy(out, in, len);
    1318     1087798 :     out[len] = '\0';
    1319             : 
    1320     1087798 :     return out;
    1321             : }
    1322             : 
    1323             : /*
    1324             :  * Make copy of string with all trailing newline characters removed.
    1325             :  */
    1326             : char *
    1327         248 : pchomp(const char *in)
    1328             : {
    1329             :     size_t      n;
    1330             : 
    1331         248 :     n = strlen(in);
    1332         496 :     while (n > 0 && in[n - 1] == '\n')
    1333         248 :         n--;
    1334         248 :     return pnstrdup(in, n);
    1335             : }

Generated by: LCOV version 1.14