LCOV - differential code coverage report
Current view: top level - src/include/utils - memutils_memorychunk.h (source / functions) Coverage Total Hit UNC UBC GNC CBC DCB
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 100.0 % 22 22 1 21 1
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 5 5 1 4
Baseline: 16@8cea358b128 Branches: 55.6 % 18 10 1 7 1 9
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 100.0 % 1 1 1
(240..) days: 100.0 % 21 21 21
Function coverage date bins:
(240..) days: 100.0 % 5 5 1 4
Branch coverage date bins:
[..60] days: 50.0 % 2 1 1 1
(240..) days: 56.2 % 16 9 7 9

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * memutils_memorychunk.h
                                  4                 :                :  *    Here we define a struct named MemoryChunk which implementations of
                                  5                 :                :  *    MemoryContexts may use as a header for chunks of memory they allocate.
                                  6                 :                :  *
                                  7                 :                :  * MemoryChunk provides a lightweight header that a MemoryContext can use to
                                  8                 :                :  * store a reference back to the block which the given chunk is allocated on
                                  9                 :                :  * and also an additional 30-bits to store another value such as the size of
                                 10                 :                :  * the allocated chunk.
                                 11                 :                :  *
                                 12                 :                :  * Although MemoryChunks are used by each of our MemoryContexts, future
                                 13                 :                :  * implementations may choose to implement their own method for storing chunk
                                 14                 :                :  * headers.  The only requirement is that the header ends with an 8-byte value
                                 15                 :                :  * which the least significant 4-bits of are set to the MemoryContextMethodID
                                 16                 :                :  * of the given context.
                                 17                 :                :  *
                                 18                 :                :  * By default, a MemoryChunk is 8 bytes in size, however, when
                                 19                 :                :  * MEMORY_CONTEXT_CHECKING is defined the header becomes 16 bytes in size due
                                 20                 :                :  * to the additional requested_size field.  The MemoryContext may use this
                                 21                 :                :  * field for whatever they wish, but it is intended to be used for additional
                                 22                 :                :  * checks which are only done in MEMORY_CONTEXT_CHECKING builds.
                                 23                 :                :  *
                                 24                 :                :  * The MemoryChunk contains a uint64 field named 'hdrmask'.  This field is
                                 25                 :                :  * used to encode 4 separate pieces of information.  Starting with the least
                                 26                 :                :  * significant bits of 'hdrmask', the bit space is reserved as follows:
                                 27                 :                :  *
                                 28                 :                :  * 1.   4-bits to indicate the MemoryContextMethodID as defined by
                                 29                 :                :  *      MEMORY_CONTEXT_METHODID_MASK
                                 30                 :                :  * 2.   1-bit to denote an "external" chunk (see below)
                                 31                 :                :  * 3.   30-bits reserved for the MemoryContext to use for anything it
                                 32                 :                :  *      requires.  Most MemoryContexts likely want to store the size of the
                                 33                 :                :  *      chunk here.
                                 34                 :                :  * 4.   30-bits for the number of bytes that must be subtracted from the chunk
                                 35                 :                :  *      to obtain the address of the block that the chunk is stored on.
                                 36                 :                :  *
                                 37                 :                :  * If you're paying close attention, you'll notice this adds up to 65 bits
                                 38                 :                :  * rather than 64 bits.  This is because the highest-order bit of #3 is the
                                 39                 :                :  * same bit as the lowest-order bit of #4.  We can do this as we insist that
                                 40                 :                :  * the chunk and block pointers are both MAXALIGNed, therefore the relative
                                 41                 :                :  * offset between those will always be a MAXALIGNed value which means the
                                 42                 :                :  * lowest order bit is always 0.  When fetching the chunk to block offset we
                                 43                 :                :  * mask out the lowest-order bit to ensure it's still zero.
                                 44                 :                :  *
                                 45                 :                :  * In some cases, for example when memory allocations become large, it's
                                 46                 :                :  * possible fields 3 and 4 above are not large enough to store the values
                                 47                 :                :  * required for the chunk.  In this case, the MemoryContext can choose to mark
                                 48                 :                :  * the chunk as "external" by calling the MemoryChunkSetHdrMaskExternal()
                                 49                 :                :  * function.  When this is done, fields 3 and 4 are unavailable for use by the
                                 50                 :                :  * MemoryContext and it's up to the MemoryContext itself to devise its own
                                 51                 :                :  * method for getting the reference to the block.
                                 52                 :                :  *
                                 53                 :                :  * Interface:
                                 54                 :                :  *
                                 55                 :                :  * MemoryChunkSetHdrMask:
                                 56                 :                :  *      Used to set up a non-external MemoryChunk.
                                 57                 :                :  *
                                 58                 :                :  * MemoryChunkSetHdrMaskExternal:
                                 59                 :                :  *      Used to set up an externally managed MemoryChunk.
                                 60                 :                :  *
                                 61                 :                :  * MemoryChunkIsExternal:
                                 62                 :                :  *      Determine if the given MemoryChunk is externally managed, i.e.
                                 63                 :                :  *      MemoryChunkSetHdrMaskExternal() was called on the chunk.
                                 64                 :                :  *
                                 65                 :                :  * MemoryChunkGetValue:
                                 66                 :                :  *      For non-external chunks, return the stored 30-bit value as it was set
                                 67                 :                :  *      in the call to MemoryChunkSetHdrMask().
                                 68                 :                :  *
                                 69                 :                :  * MemoryChunkGetBlock:
                                 70                 :                :  *      For non-external chunks, return a pointer to the block as it was set
                                 71                 :                :  *      in the call to MemoryChunkSetHdrMask().
                                 72                 :                :  *
                                 73                 :                :  * Also exports:
                                 74                 :                :  *      MEMORYCHUNK_MAX_VALUE
                                 75                 :                :  *      MEMORYCHUNK_MAX_BLOCKOFFSET
                                 76                 :                :  *      PointerGetMemoryChunk
                                 77                 :                :  *      MemoryChunkGetPointer
                                 78                 :                :  *
                                 79                 :                :  * Portions Copyright (c) 2022-2024, PostgreSQL Global Development Group
                                 80                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                 81                 :                :  *
                                 82                 :                :  * src/include/utils/memutils_memorychunk.h
                                 83                 :                :  *
                                 84                 :                :  *-------------------------------------------------------------------------
                                 85                 :                :  */
                                 86                 :                : 
                                 87                 :                : #ifndef MEMUTILS_MEMORYCHUNK_H
                                 88                 :                : #define MEMUTILS_MEMORYCHUNK_H
                                 89                 :                : 
                                 90                 :                : #include "utils/memutils_internal.h"
                                 91                 :                : 
                                 92                 :                :  /*
                                 93                 :                :   * The maximum allowed value that MemoryContexts can store in the value
                                 94                 :                :   * field.  Must be 1 less than a power of 2.
                                 95                 :                :   */
                                 96                 :                : #define MEMORYCHUNK_MAX_VALUE           UINT64CONST(0x3FFFFFFF)
                                 97                 :                : 
                                 98                 :                : /*
                                 99                 :                :  * The maximum distance in bytes that a MemoryChunk can be offset from the
                                100                 :                :  * block that is storing the chunk.  Must be 1 less than a power of 2.
                                101                 :                :  */
                                102                 :                : #define MEMORYCHUNK_MAX_BLOCKOFFSET     UINT64CONST(0x3FFFFFFF)
                                103                 :                : 
                                104                 :                : /*
                                105                 :                :  * As above, but mask out the lowest-order (always zero) bit as this is shared
                                106                 :                :  * with the MemoryChunkGetValue field.
                                107                 :                :  */
                                108                 :                : #define MEMORYCHUNK_BLOCKOFFSET_MASK    UINT64CONST(0x3FFFFFFE)
                                109                 :                : 
                                110                 :                : /* define the least significant base-0 bit of each portion of the hdrmask */
                                111                 :                : #define MEMORYCHUNK_EXTERNAL_BASEBIT    MEMORY_CONTEXT_METHODID_BITS
                                112                 :                : #define MEMORYCHUNK_VALUE_BASEBIT       (MEMORYCHUNK_EXTERNAL_BASEBIT + 1)
                                113                 :                : #define MEMORYCHUNK_BLOCKOFFSET_BASEBIT (MEMORYCHUNK_VALUE_BASEBIT + 29)
                                114                 :                : 
                                115                 :                : /*
                                116                 :                :  * A magic number for storing in the free bits of an external chunk.  This
                                117                 :                :  * must mask out the bits used for storing the MemoryContextMethodID and the
                                118                 :                :  * external bit.
                                119                 :                :  */
                                120                 :                : #define MEMORYCHUNK_MAGIC       (UINT64CONST(0xB1A8DB858EB6EFBA) >> \
                                121                 :                :                                  MEMORYCHUNK_VALUE_BASEBIT << \
                                122                 :                :                                  MEMORYCHUNK_VALUE_BASEBIT)
                                123                 :                : 
                                124                 :                : typedef struct MemoryChunk
                                125                 :                : {
                                126                 :                : #ifdef MEMORY_CONTEXT_CHECKING
                                127                 :                :     Size        requested_size;
                                128                 :                : #endif
                                129                 :                : 
                                130                 :                :     /* bitfield for storing details about the chunk */
                                131                 :                :     uint64      hdrmask;        /* must be last */
                                132                 :                : } MemoryChunk;
                                133                 :                : 
                                134                 :                : /* Get the MemoryChunk from the pointer */
                                135                 :                : #define PointerGetMemoryChunk(p) \
                                136                 :                :     ((MemoryChunk *) ((char *) (p) - sizeof(MemoryChunk)))
                                137                 :                : /* Get the pointer from the MemoryChunk */
                                138                 :                : #define MemoryChunkGetPointer(c) \
                                139                 :                :     ((void *) ((char *) (c) + sizeof(MemoryChunk)))
                                140                 :                : 
                                141                 :                : /* private macros for making the inline functions below more simple */
                                142                 :                : #define HdrMaskIsExternal(hdrmask) \
                                143                 :                :     ((hdrmask) & (((uint64) 1) << MEMORYCHUNK_EXTERNAL_BASEBIT))
                                144                 :                : #define HdrMaskGetValue(hdrmask) \
                                145                 :                :     (((hdrmask) >> MEMORYCHUNK_VALUE_BASEBIT) & MEMORYCHUNK_MAX_VALUE)
                                146                 :                : 
                                147                 :                : /*
                                148                 :                :  * Shift the block offset down to the 0th bit position and mask off the single
                                149                 :                :  * bit that's shared with the MemoryChunkGetValue field.
                                150                 :                :  */
                                151                 :                : #define HdrMaskBlockOffset(hdrmask) \
                                152                 :                :     (((hdrmask) >> MEMORYCHUNK_BLOCKOFFSET_BASEBIT) & MEMORYCHUNK_BLOCKOFFSET_MASK)
                                153                 :                : 
                                154                 :                : /* For external chunks only, check the magic number matches */
                                155                 :                : #define HdrMaskCheckMagic(hdrmask) \
                                156                 :                :     (MEMORYCHUNK_MAGIC == \
                                157                 :                :      ((hdrmask) >> MEMORYCHUNK_VALUE_BASEBIT << MEMORYCHUNK_VALUE_BASEBIT))
                                158                 :                : /*
                                159                 :                :  * MemoryChunkSetHdrMask
                                160                 :                :  *      Store the given 'block', 'chunk_size' and 'methodid' in the given
                                161                 :                :  *      MemoryChunk.
                                162                 :                :  *
                                163                 :                :  * The number of bytes between 'block' and 'chunk' must be <=
                                164                 :                :  * MEMORYCHUNK_MAX_BLOCKOFFSET.
                                165                 :                :  * 'value' must be <= MEMORYCHUNK_MAX_VALUE.
                                166                 :                :  * Both 'chunk' and 'block' must be MAXALIGNed pointers.
                                167                 :                :  */
                                168                 :                : static inline void
  594 drowley@postgresql.o      169                 :CBC   303912068 : MemoryChunkSetHdrMask(MemoryChunk *chunk, void *block,
                                170                 :                :                       Size value, MemoryContextMethodID methodid)
                                171                 :                : {
                                172                 :      303912068 :     Size        blockoffset = (char *) chunk - (char *) block;
                                173                 :                : 
  479                           174         [ -  + ]:      303912068 :     Assert((char *) chunk >= (char *) block);
    7 drowley@postgresql.o      175         [ -  + ]:GNC   303912068 :     Assert((blockoffset & MEMORYCHUNK_BLOCKOFFSET_MASK) == blockoffset);
  594 drowley@postgresql.o      176         [ -  + ]:CBC   303912068 :     Assert(value <= MEMORYCHUNK_MAX_VALUE);
  592                           177         [ -  + ]:      303912068 :     Assert((int) methodid <= MEMORY_CONTEXT_METHODID_MASK);
                                178                 :                : 
  594                           179                 :      303912068 :     chunk->hdrmask = (((uint64) blockoffset) << MEMORYCHUNK_BLOCKOFFSET_BASEBIT) |
                                180                 :      303912068 :         (((uint64) value) << MEMORYCHUNK_VALUE_BASEBIT) |
                                181                 :                :         methodid;
                                182                 :      303912068 : }
                                183                 :                : 
                                184                 :                : /*
                                185                 :                :  * MemoryChunkSetHdrMaskExternal
                                186                 :                :  *      Set 'chunk' as an externally managed chunk.  Here we only record the
                                187                 :                :  *      MemoryContextMethodID and set the external chunk bit.
                                188                 :                :  */
                                189                 :                : static inline void
                                190                 :        7666736 : MemoryChunkSetHdrMaskExternal(MemoryChunk *chunk,
                                191                 :                :                               MemoryContextMethodID methodid)
                                192                 :                : {
  592                           193         [ -  + ]:        7666736 :     Assert((int) methodid <= MEMORY_CONTEXT_METHODID_MASK);
                                194                 :                : 
  594                           195                 :        7666736 :     chunk->hdrmask = MEMORYCHUNK_MAGIC | (((uint64) 1) << MEMORYCHUNK_EXTERNAL_BASEBIT) |
                                196                 :                :         methodid;
                                197                 :        7666736 : }
                                198                 :                : 
                                199                 :                : /*
                                200                 :                :  * MemoryChunkIsExternal
                                201                 :                :  *      Return true if 'chunk' is marked as external.
                                202                 :                :  */
                                203                 :                : static inline bool
                                204                 :     2457456736 : MemoryChunkIsExternal(MemoryChunk *chunk)
                                205                 :                : {
                                206                 :                :     /*
                                207                 :                :      * External chunks should always store MEMORYCHUNK_MAGIC in the upper
                                208                 :                :      * portion of the hdrmask, check that nothing has stomped on that.
                                209                 :                :      */
                                210   [ +  +  -  + ]:     2457456736 :     Assert(!HdrMaskIsExternal(chunk->hdrmask) ||
                                211                 :                :            HdrMaskCheckMagic(chunk->hdrmask));
                                212                 :                : 
                                213                 :     2457456736 :     return HdrMaskIsExternal(chunk->hdrmask);
                                214                 :                : }
                                215                 :                : 
                                216                 :                : /*
                                217                 :                :  * MemoryChunkGetValue
                                218                 :                :  *      For non-external chunks, returns the value field as it was set in
                                219                 :                :  *      MemoryChunkSetHdrMask.
                                220                 :                :  */
                                221                 :                : static inline Size
                                222                 :     2609978109 : MemoryChunkGetValue(MemoryChunk *chunk)
                                223                 :                : {
                                224         [ -  + ]:     2609978109 :     Assert(!HdrMaskIsExternal(chunk->hdrmask));
                                225                 :                : 
                                226                 :     2609978109 :     return HdrMaskGetValue(chunk->hdrmask);
                                227                 :                : }
                                228                 :                : 
                                229                 :                : /*
                                230                 :                :  * MemoryChunkGetBlock
                                231                 :                :  *      For non-external chunks, returns the pointer to the block as was set
                                232                 :                :  *      in MemoryChunkSetHdrMask.
                                233                 :                :  */
                                234                 :                : static inline void *
                                235                 :     2426665103 : MemoryChunkGetBlock(MemoryChunk *chunk)
                                236                 :                : {
                                237         [ -  + ]:     2426665103 :     Assert(!HdrMaskIsExternal(chunk->hdrmask));
                                238                 :                : 
                                239                 :     2426665103 :     return (void *) ((char *) chunk - HdrMaskBlockOffset(chunk->hdrmask));
                                240                 :                : }
                                241                 :                : 
                                242                 :                : /* cleanup all internal definitions */
                                243                 :                : #undef MEMORYCHUNK_BLOCKOFFSET_MASK
                                244                 :                : #undef MEMORYCHUNK_EXTERNAL_BASEBIT
                                245                 :                : #undef MEMORYCHUNK_VALUE_BASEBIT
                                246                 :                : #undef MEMORYCHUNK_BLOCKOFFSET_BASEBIT
                                247                 :                : #undef MEMORYCHUNK_MAGIC
                                248                 :                : #undef HdrMaskIsExternal
                                249                 :                : #undef HdrMaskGetValue
                                250                 :                : #undef HdrMaskBlockOffset
                                251                 :                : #undef HdrMaskCheckMagic
                                252                 :                : 
                                253                 :                : #endif                          /* MEMUTILS_MEMORYCHUNK_H */
        

Generated by: LCOV version 2.1-beta2-3-g6141622