LCOV - code coverage report
Current view: top level - src/include/utils - memutils.h (source / functions) Coverage Total Hit
Test: Code coverage Lines: 64.4 % 45 29
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 1 1
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 50.0 % 42 21

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * memutils.h
       4                 :             :  *        This file contains declarations for memory allocation utility
       5                 :             :  *        functions.  These are functions that are not quite widely used
       6                 :             :  *        enough to justify going in utils/palloc.h, but are still part
       7                 :             :  *        of the API of the memory management subsystem.
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      11                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      12                 :             :  *
      13                 :             :  * src/include/utils/memutils.h
      14                 :             :  *
      15                 :             :  *-------------------------------------------------------------------------
      16                 :             :  */
      17                 :             : #ifndef MEMUTILS_H
      18                 :             : #define MEMUTILS_H
      19                 :             : 
      20                 :             : #include "nodes/memnodes.h"
      21                 :             : 
      22                 :             : 
      23                 :             : /*
      24                 :             :  * MaxAllocSize, MaxAllocHugeSize
      25                 :             :  *              Quasi-arbitrary limits on size of allocations.
      26                 :             :  *
      27                 :             :  * Note:
      28                 :             :  *              There is no guarantee that smaller allocations will succeed, but
      29                 :             :  *              larger requests will be summarily denied.
      30                 :             :  *
      31                 :             :  * palloc() enforces MaxAllocSize, chosen to correspond to the limiting size
      32                 :             :  * of varlena objects under TOAST.  See VARSIZE_4B() and related macros in
      33                 :             :  * varatt.h.  Many datatypes assume that any allocatable size can be
      34                 :             :  * represented in a varlena header.  This limit also permits a caller to use
      35                 :             :  * an "int" variable for an index into or length of an allocation.  Callers
      36                 :             :  * careful to avoid these hazards can access the higher limit with
      37                 :             :  * MemoryContextAllocHuge().  Both limits permit code to assume that it may
      38                 :             :  * compute twice an allocation's size without overflow.
      39                 :             :  */
      40                 :             : #define MaxAllocSize    ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
      41                 :             : 
      42                 :             : #define AllocSizeIsValid(size)  ((Size) (size) <= MaxAllocSize)
      43                 :             : 
      44                 :             : /* Must be less than SIZE_MAX */
      45                 :             : #define MaxAllocHugeSize        (SIZE_MAX / 2)
      46                 :             : 
      47                 :             : #define InvalidAllocSize        SIZE_MAX
      48                 :             : 
      49                 :             : #define AllocHugeSizeIsValid(size)      ((Size) (size) <= MaxAllocHugeSize)
      50                 :             : 
      51                 :             : 
      52                 :             : /*
      53                 :             :  * Standard top-level memory contexts.
      54                 :             :  *
      55                 :             :  * Only TopMemoryContext and ErrorContext are initialized by
      56                 :             :  * MemoryContextInit() itself.
      57                 :             :  */
      58                 :             : extern PGDLLIMPORT MemoryContext TopMemoryContext;
      59                 :             : extern PGDLLIMPORT MemoryContext ErrorContext;
      60                 :             : extern PGDLLIMPORT MemoryContext PostmasterContext;
      61                 :             : extern PGDLLIMPORT MemoryContext CacheMemoryContext;
      62                 :             : extern PGDLLIMPORT MemoryContext MessageContext;
      63                 :             : extern PGDLLIMPORT MemoryContext TopTransactionContext;
      64                 :             : extern PGDLLIMPORT MemoryContext CurTransactionContext;
      65                 :             : 
      66                 :             : /* This is a transient link to the active portal's memory context: */
      67                 :             : extern PGDLLIMPORT MemoryContext PortalContext;
      68                 :             : 
      69                 :             : 
      70                 :             : /*
      71                 :             :  * Memory-context-type-independent functions in mcxt.c
      72                 :             :  */
      73                 :             : extern void MemoryContextInit(void);
      74                 :             : extern void MemoryContextReset(MemoryContext context);
      75                 :             : extern void MemoryContextDelete(MemoryContext context);
      76                 :             : extern void MemoryContextResetOnly(MemoryContext context);
      77                 :             : extern void MemoryContextResetChildren(MemoryContext context);
      78                 :             : extern void MemoryContextDeleteChildren(MemoryContext context);
      79                 :             : extern void MemoryContextSetIdentifier(MemoryContext context, const char *id);
      80                 :             : extern void MemoryContextSetParent(MemoryContext context,
      81                 :             :                                                                    MemoryContext new_parent);
      82                 :             : extern MemoryContext GetMemoryChunkContext(void *pointer);
      83                 :             : extern Size GetMemoryChunkSpace(void *pointer);
      84                 :             : extern MemoryContext MemoryContextGetParent(MemoryContext context);
      85                 :             : extern bool MemoryContextIsEmpty(MemoryContext context);
      86                 :             : extern Size MemoryContextMemAllocated(MemoryContext context, bool recurse);
      87                 :             : extern void MemoryContextMemConsumed(MemoryContext context,
      88                 :             :                                                                          MemoryContextCounters *consumed);
      89                 :             : extern void MemoryContextStats(MemoryContext context);
      90                 :             : extern void MemoryContextStatsDetail(MemoryContext context,
      91                 :             :                                                                          int max_level, int max_children,
      92                 :             :                                                                          bool print_to_stderr);
      93                 :             : extern void MemoryContextAllowInCriticalSection(MemoryContext context,
      94                 :             :                                                                                                 bool allow);
      95                 :             : 
      96                 :             : #ifdef MEMORY_CONTEXT_CHECKING
      97                 :             : extern void MemoryContextCheck(MemoryContext context);
      98                 :             : #endif
      99                 :             : 
     100                 :             : /* Handy macro for copying and assigning context ID ... but note double eval */
     101                 :             : #define MemoryContextCopyAndSetIdentifier(cxt, id) \
     102                 :             :         MemoryContextSetIdentifier(cxt, MemoryContextStrdup(cxt, id))
     103                 :             : 
     104                 :             : extern void HandleLogMemoryContextInterrupt(void);
     105                 :             : extern void ProcessLogMemoryContextInterrupt(void);
     106                 :             : 
     107                 :             : /*
     108                 :             :  * Memory-context-type-specific functions
     109                 :             :  */
     110                 :             : 
     111                 :             : /* aset.c */
     112                 :             : extern MemoryContext AllocSetContextCreateInternal(MemoryContext parent,
     113                 :             :                                                                                                    const char *name,
     114                 :             :                                                                                                    Size minContextSize,
     115                 :             :                                                                                                    Size initBlockSize,
     116                 :             :                                                                                                    Size maxBlockSize);
     117                 :             : 
     118                 :             : /*
     119                 :             :  * This wrapper macro exists to check for non-constant strings used as context
     120                 :             :  * names; that's no longer supported.  (Use MemoryContextSetIdentifier if you
     121                 :             :  * want to provide a variable identifier.)
     122                 :             :  */
     123                 :             : #ifdef HAVE__BUILTIN_CONSTANT_P
     124                 :             : #define AllocSetContextCreate(parent, name, ...) \
     125                 :             :         (StaticAssertExpr(__builtin_constant_p(name), \
     126                 :             :                                           "memory context names must be constant strings"), \
     127                 :             :          AllocSetContextCreateInternal(parent, name, __VA_ARGS__))
     128                 :             : #else
     129                 :             : #define AllocSetContextCreate \
     130                 :             :         AllocSetContextCreateInternal
     131                 :             : #endif
     132                 :             : 
     133                 :             : /* slab.c */
     134                 :             : extern MemoryContext SlabContextCreate(MemoryContext parent,
     135                 :             :                                                                            const char *name,
     136                 :             :                                                                            Size blockSize,
     137                 :             :                                                                            Size chunkSize);
     138                 :             : 
     139                 :             : /* generation.c */
     140                 :             : extern MemoryContext GenerationContextCreate(MemoryContext parent,
     141                 :             :                                                                                          const char *name,
     142                 :             :                                                                                          Size minContextSize,
     143                 :             :                                                                                          Size initBlockSize,
     144                 :             :                                                                                          Size maxBlockSize);
     145                 :             : 
     146                 :             : /* bump.c */
     147                 :             : extern MemoryContext BumpContextCreate(MemoryContext parent,
     148                 :             :                                                                            const char *name,
     149                 :             :                                                                            Size minContextSize,
     150                 :             :                                                                            Size initBlockSize,
     151                 :             :                                                                            Size maxBlockSize);
     152                 :             : 
     153                 :             : /*
     154                 :             :  * Recommended default alloc parameters, suitable for "ordinary" contexts
     155                 :             :  * that might hold quite a lot of data.
     156                 :             :  */
     157                 :             : #define ALLOCSET_DEFAULT_MINSIZE   0
     158                 :             : #define ALLOCSET_DEFAULT_INITSIZE  (8 * 1024)
     159                 :             : #define ALLOCSET_DEFAULT_MAXSIZE   (8 * 1024 * 1024)
     160                 :             : #define ALLOCSET_DEFAULT_SIZES \
     161                 :             :         ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE
     162                 :             : 
     163                 :             : /*
     164                 :             :  * Recommended alloc parameters for "small" contexts that are never expected
     165                 :             :  * to contain much data (for example, a context to contain a query plan).
     166                 :             :  */
     167                 :             : #define ALLOCSET_SMALL_MINSIZE   0
     168                 :             : #define ALLOCSET_SMALL_INITSIZE  (1 * 1024)
     169                 :             : #define ALLOCSET_SMALL_MAXSIZE   (8 * 1024)
     170                 :             : #define ALLOCSET_SMALL_SIZES \
     171                 :             :         ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MAXSIZE
     172                 :             : 
     173                 :             : /*
     174                 :             :  * Recommended alloc parameters for contexts that should start out small,
     175                 :             :  * but might sometimes grow big.
     176                 :             :  */
     177                 :             : #define ALLOCSET_START_SMALL_SIZES \
     178                 :             :         ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE
     179                 :             : 
     180                 :             : 
     181                 :             : /*
     182                 :             :  * Threshold above which a request in an AllocSet context is certain to be
     183                 :             :  * allocated separately (and thereby have constant allocation overhead).
     184                 :             :  * Few callers should be interested in this, but tuplesort/tuplestore need
     185                 :             :  * to know it.
     186                 :             :  */
     187                 :             : #define ALLOCSET_SEPARATE_THRESHOLD  8192
     188                 :             : 
     189                 :             : #define SLAB_DEFAULT_BLOCK_SIZE         (8 * 1024)
     190                 :             : #define SLAB_LARGE_BLOCK_SIZE           (8 * 1024 * 1024)
     191                 :             : 
     192                 :             : /*
     193                 :             :  * pg_memory_is_all_zeros
     194                 :             :  *
     195                 :             :  * Test if a memory region starting at "ptr" and of size "len" is full of
     196                 :             :  * zeroes.
     197                 :             :  *
     198                 :             :  * The test is divided into multiple cases for safety reason and multiple
     199                 :             :  * phases for efficiency.
     200                 :             :  *
     201                 :             :  * Case 1: len < sizeof(size_t) bytes, then byte-by-byte comparison.
     202                 :             :  * Case 2: len < (sizeof(size_t) * 8 - 1) bytes:
     203                 :             :  *       - Phase 1: byte-by-byte comparison, until the pointer is aligned.
     204                 :             :  *       - Phase 2: size_t comparisons, with aligned pointers, up to the last
     205                 :             :  *                  location possible.
     206                 :             :  *       - Phase 3: byte-by-byte comparison, until the end location.
     207                 :             :  * Case 3: len >= (sizeof(size_t) * 8) bytes, same as case 2 except that an
     208                 :             :  *         additional phase is placed between Phase 1 and Phase 2, with
     209                 :             :  *         (8 * sizeof(size_t)) comparisons using bitwise OR to encourage
     210                 :             :  *         compilers to use SIMD instructions if available, up to the last
     211                 :             :  *         aligned location possible.
     212                 :             :  *
     213                 :             :  * Case 1 and Case 2 are mandatory to ensure that we won't read beyond the
     214                 :             :  * memory area.  This is portable for 32-bit and 64-bit architectures.
     215                 :             :  *
     216                 :             :  * Caller must ensure that "ptr" is not NULL.
     217                 :             :  */
     218                 :             : static inline bool
     219                 :       45115 : pg_memory_is_all_zeros(const void *ptr, size_t len)
     220                 :             : {
     221                 :       45115 :         const unsigned char *p = (const unsigned char *) ptr;
     222                 :       45115 :         const unsigned char *end = &p[len];
     223                 :       90230 :         const unsigned char *aligned_end = (const unsigned char *)
     224                 :       45115 :                 ((uintptr_t) end & (~(sizeof(size_t) - 1)));
     225                 :             : 
     226         [ -  + ]:       45115 :         if (len < sizeof(size_t))
     227                 :             :         {
     228         [ #  # ]:           0 :                 while (p < end)
     229                 :             :                 {
     230         [ #  # ]:           0 :                         if (*p++ != 0)
     231                 :           0 :                                 return false;
     232                 :             :                 }
     233                 :           0 :                 return true;
     234                 :             :         }
     235                 :             : 
     236                 :             :         /* "len" in the [sizeof(size_t), sizeof(size_t) * 8 - 1] range */
     237         [ +  + ]:       45115 :         if (len < sizeof(size_t) * 8)
     238                 :             :         {
     239                 :             :                 /* Compare bytes until the pointer "p" is aligned */
     240         [ -  + ]:          24 :                 while (((uintptr_t) p & (sizeof(size_t) - 1)) != 0)
     241                 :             :                 {
     242         [ #  # ]:           0 :                         if (p == end)
     243                 :           0 :                                 return true;
     244         [ #  # ]:           0 :                         if (*p++ != 0)
     245                 :           0 :                                 return false;
     246                 :             :                 }
     247                 :             : 
     248                 :             :                 /*
     249                 :             :                  * Compare remaining size_t-aligned chunks.
     250                 :             :                  *
     251                 :             :                  * There is no risk to read beyond the memory area, as "aligned_end"
     252                 :             :                  * cannot be higher than "end".
     253                 :             :                  */
     254         [ +  + ]:          94 :                 for (; p < aligned_end; p += sizeof(size_t))
     255                 :             :                 {
     256         [ +  + ]:          83 :                         if (*(size_t *) p != 0)
     257                 :          13 :                                 return false;
     258                 :          70 :                 }
     259                 :             : 
     260                 :             :                 /* Compare remaining bytes until the end */
     261         [ -  + ]:          11 :                 while (p < end)
     262                 :             :                 {
     263         [ #  # ]:           0 :                         if (*p++ != 0)
     264                 :           0 :                                 return false;
     265                 :             :                 }
     266                 :          11 :                 return true;
     267                 :             :         }
     268                 :             : 
     269                 :             :         /* "len" in the [sizeof(size_t) * 8, inf) range */
     270                 :             : 
     271                 :             :         /* Compare bytes until the pointer "p" is aligned */
     272         [ -  + ]:       45091 :         while (((uintptr_t) p & (sizeof(size_t) - 1)) != 0)
     273                 :             :         {
     274         [ #  # ]:           0 :                 if (p == end)
     275                 :           0 :                         return true;
     276                 :             : 
     277         [ #  # ]:           0 :                 if (*p++ != 0)
     278                 :           0 :                         return false;
     279                 :             :         }
     280                 :             : 
     281                 :             :         /*
     282                 :             :          * Compare 8 * sizeof(size_t) chunks at once.
     283                 :             :          *
     284                 :             :          * For performance reasons, we manually unroll this loop and purposefully
     285                 :             :          * use bitwise-ORs to combine each comparison.  This prevents boolean
     286                 :             :          * short-circuiting and lets the compiler know that it's safe to access
     287                 :             :          * all 8 elements regardless of the result of the other comparisons.  This
     288                 :             :          * seems to be enough to coax a few compilers into using SIMD
     289                 :             :          * instructions.
     290                 :             :          */
     291         [ +  + ]:       75336 :         for (; p < aligned_end - (sizeof(size_t) * 7); p += sizeof(size_t) * 8)
     292                 :             :         {
     293                 :      121758 :                 if ((((size_t *) p)[0] != 0) | (((size_t *) p)[1] != 0) |
     294                 :      182637 :                         (((size_t *) p)[2] != 0) | (((size_t *) p)[3] != 0) |
     295                 :      182637 :                         (((size_t *) p)[4] != 0) | (((size_t *) p)[5] != 0) |
     296   [ +  +  +  + ]:      121758 :                         (((size_t *) p)[6] != 0) | (((size_t *) p)[7] != 0))
     297                 :       30634 :                         return false;
     298                 :       30245 :         }
     299                 :             : 
     300                 :             :         /*
     301                 :             :          * Compare remaining size_t-aligned chunks.
     302                 :             :          *
     303                 :             :          * There is no risk to read beyond the memory area, as "aligned_end"
     304                 :             :          * cannot be higher than "end".
     305                 :             :          */
     306         [ +  + ]:       71798 :         for (; p < aligned_end; p += sizeof(size_t))
     307                 :             :         {
     308         [ +  + ]:       71547 :                 if (*(size_t *) p != 0)
     309                 :       14206 :                         return false;
     310                 :       57341 :         }
     311                 :             : 
     312                 :             :         /* Compare remaining bytes until the end */
     313         [ -  + ]:         251 :         while (p < end)
     314                 :             :         {
     315         [ #  # ]:           0 :                 if (*p++ != 0)
     316                 :           0 :                         return false;
     317                 :             :         }
     318                 :             : 
     319                 :         251 :         return true;
     320                 :       45115 : }
     321                 :             : 
     322                 :             : #endif                                                  /* MEMUTILS_H */
        

Generated by: LCOV version 2.3.2-1