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

Generated by: LCOV version 1.11