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

Generated by: LCOV version 1.13