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

Generated by: LCOV version 1.13