LCOV - differential code coverage report
Current view: top level - src/backend/utils/mmgr - mcxt.c (source / functions) Coverage Total Hit UNC LBC UIC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 79.5 % 396 315 20 14 47 16 177 66 56 61 223 4 22
Current Date: 2023-04-08 17:13:01 Functions: 85.7 % 49 42 5 2 36 6 6 41 1 1
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 94.1 % 17 16 1 16
Legend: Lines: hit not hit (120,180] days: 83.3 % 48 40 8 39 1 2
(180,240] days: 47.6 % 21 10 11 10
(240..) days: 80.3 % 310 249 14 47 16 177 1 55 46 156
Function coverage date bins:
(60,120] days: 100.0 % 2 2 2
(120,180] days: 66.7 % 3 2 2 1
(180,240] days: 28.6 % 7 2 5 2
(240..) days: 49.3 % 73 36 2 36 6 29

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

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