LCOV - differential code coverage report
Current view: top level - src/include/utils - memutils_memorychunk.h (source / functions) Coverage Total Hit GNC
Current: Differential Code Coverage HEAD vs 15 Lines: 100.0 % 22 22 22
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 5 5 5
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           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 3-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.   3-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 MemoryContext 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                 :  * In some cases, for example when memory allocations become large, it's
      38                 :  * possible fields 3 and 4 above are not large enough to store the values
      39                 :  * required for the chunk.  In this case, the MemoryContext can choose to mark
      40                 :  * the chunk as "external" by calling the MemoryChunkSetExternal() function.
      41                 :  * When this is done, fields 3 and 4 are unavailable for use by the
      42                 :  * MemoryContext and it's up to the MemoryContext itself to devise its own
      43                 :  * method for getting the reference to the block.
      44                 :  *
      45                 :  * Interface:
      46                 :  *
      47                 :  * MemoryChunkSetHdrMask:
      48                 :  *      Used to set up a non-external MemoryChunk.
      49                 :  *
      50                 :  * MemoryChunkSetHdrMaskExternal:
      51                 :  *      Used to set up an externally managed MemoryChunk.
      52                 :  *
      53                 :  * MemoryChunkIsExternal:
      54                 :  *      Determine if the given MemoryChunk is externally managed, i.e.
      55                 :  *      MemoryChunkSetHdrMaskExternal() was called on the chunk.
      56                 :  *
      57                 :  * MemoryChunkGetValue:
      58                 :  *      For non-external chunks, return the stored 30-bit value as it was set
      59                 :  *      in the call to MemoryChunkSetHdrMask().
      60                 :  *
      61                 :  * MemoryChunkGetBlock:
      62                 :  *      For non-external chunks, return a pointer to the block as it was set
      63                 :  *      in the call to MemoryChunkSetHdrMask().
      64                 :  *
      65                 :  * Also exports:
      66                 :  *      MEMORYCHUNK_MAX_VALUE
      67                 :  *      MEMORYCHUNK_MAX_BLOCKOFFSET
      68                 :  *      PointerGetMemoryChunk
      69                 :  *      MemoryChunkGetPointer
      70                 :  *
      71                 :  * Portions Copyright (c) 2022-2023, PostgreSQL Global Development Group
      72                 :  * Portions Copyright (c) 1994, Regents of the University of California
      73                 :  *
      74                 :  * src/include/utils/memutils_memorychunk.h
      75                 :  *
      76                 :  *-------------------------------------------------------------------------
      77                 :  */
      78                 : 
      79                 : #ifndef MEMUTILS_MEMORYCHUNK_H
      80                 : #define MEMUTILS_MEMORYCHUNK_H
      81                 : 
      82                 : #include "utils/memutils_internal.h"
      83                 : 
      84                 :  /*
      85                 :   * The maximum allowed value that MemoryContexts can store in the value
      86                 :   * field.  Must be 1 less than a power of 2.
      87                 :   */
      88                 : #define MEMORYCHUNK_MAX_VALUE           UINT64CONST(0x3FFFFFFF)
      89                 : 
      90                 : /*
      91                 :  * The maximum distance in bytes that a MemoryChunk can be offset from the
      92                 :  * block that is storing the chunk.  Must be 1 less than a power of 2.
      93                 :  */
      94                 : #define MEMORYCHUNK_MAX_BLOCKOFFSET     UINT64CONST(0x3FFFFFFF)
      95                 : 
      96                 : /* define the least significant base-0 bit of each portion of the hdrmask */
      97                 : #define MEMORYCHUNK_EXTERNAL_BASEBIT    MEMORY_CONTEXT_METHODID_BITS
      98                 : #define MEMORYCHUNK_VALUE_BASEBIT       (MEMORYCHUNK_EXTERNAL_BASEBIT + 1)
      99                 : #define MEMORYCHUNK_BLOCKOFFSET_BASEBIT (MEMORYCHUNK_VALUE_BASEBIT + 30)
     100                 : 
     101                 : /*
     102                 :  * A magic number for storing in the free bits of an external chunk.  This
     103                 :  * must mask out the bits used for storing the MemoryContextMethodID and the
     104                 :  * external bit.
     105                 :  */
     106                 : #define MEMORYCHUNK_MAGIC       (UINT64CONST(0xB1A8DB858EB6EFBA) >> \
     107                 :                                  MEMORYCHUNK_VALUE_BASEBIT << \
     108                 :                                  MEMORYCHUNK_VALUE_BASEBIT)
     109                 : 
     110                 : typedef struct MemoryChunk
     111                 : {
     112                 : #ifdef MEMORY_CONTEXT_CHECKING
     113                 :     Size        requested_size;
     114                 : #endif
     115                 : 
     116                 :     /* bitfield for storing details about the chunk */
     117                 :     uint64      hdrmask;        /* must be last */
     118                 : } MemoryChunk;
     119                 : 
     120                 : /* Get the MemoryChunk from the pointer */
     121                 : #define PointerGetMemoryChunk(p) \
     122                 :     ((MemoryChunk *) ((char *) (p) - sizeof(MemoryChunk)))
     123                 : /* Get the pointer from the MemoryChunk */
     124                 : #define MemoryChunkGetPointer(c) \
     125                 :     ((void *) ((char *) (c) + sizeof(MemoryChunk)))
     126                 : 
     127                 : /* private macros for making the inline functions below more simple */
     128                 : #define HdrMaskIsExternal(hdrmask) \
     129                 :     ((hdrmask) & (((uint64) 1) << MEMORYCHUNK_EXTERNAL_BASEBIT))
     130                 : #define HdrMaskGetValue(hdrmask) \
     131                 :     (((hdrmask) >> MEMORYCHUNK_VALUE_BASEBIT) & MEMORYCHUNK_MAX_VALUE)
     132                 : 
     133                 : /*
     134                 :  * We should have used up all the bits here, so the compiler is likely to
     135                 :  * optimize out the & MEMORYCHUNK_MAX_BLOCKOFFSET.
     136                 :  */
     137                 : #define HdrMaskBlockOffset(hdrmask) \
     138                 :     (((hdrmask) >> MEMORYCHUNK_BLOCKOFFSET_BASEBIT) & MEMORYCHUNK_MAX_BLOCKOFFSET)
     139                 : 
     140                 : /* For external chunks only, check the magic number matches */
     141                 : #define HdrMaskCheckMagic(hdrmask) \
     142                 :     (MEMORYCHUNK_MAGIC == \
     143                 :      ((hdrmask) >> MEMORYCHUNK_VALUE_BASEBIT << MEMORYCHUNK_VALUE_BASEBIT))
     144                 : /*
     145                 :  * MemoryChunkSetHdrMask
     146                 :  *      Store the given 'block', 'chunk_size' and 'methodid' in the given
     147                 :  *      MemoryChunk.
     148                 :  *
     149                 :  * The number of bytes between 'block' and 'chunk' must be <=
     150                 :  * MEMORYCHUNK_MAX_BLOCKOFFSET.
     151                 :  * 'value' must be <= MEMORYCHUNK_MAX_VALUE.
     152                 :  */
     153                 : static inline void
     154 GNC   417962095 : MemoryChunkSetHdrMask(MemoryChunk *chunk, void *block,
     155                 :                       Size value, MemoryContextMethodID methodid)
     156                 : {
     157       417962095 :     Size        blockoffset = (char *) chunk - (char *) block;
     158                 : 
     159       417962095 :     Assert((char *) chunk >= (char *) block);
     160       417962095 :     Assert(blockoffset <= MEMORYCHUNK_MAX_BLOCKOFFSET);
     161       417962095 :     Assert(value <= MEMORYCHUNK_MAX_VALUE);
     162       417962095 :     Assert((int) methodid <= MEMORY_CONTEXT_METHODID_MASK);
     163                 : 
     164       417962095 :     chunk->hdrmask = (((uint64) blockoffset) << MEMORYCHUNK_BLOCKOFFSET_BASEBIT) |
     165       417962095 :         (((uint64) value) << MEMORYCHUNK_VALUE_BASEBIT) |
     166                 :         methodid;
     167       417962095 : }
     168                 : 
     169                 : /*
     170                 :  * MemoryChunkSetHdrMaskExternal
     171                 :  *      Set 'chunk' as an externally managed chunk.  Here we only record the
     172                 :  *      MemoryContextMethodID and set the external chunk bit.
     173                 :  */
     174                 : static inline void
     175        11334463 : MemoryChunkSetHdrMaskExternal(MemoryChunk *chunk,
     176                 :                               MemoryContextMethodID methodid)
     177                 : {
     178        11334463 :     Assert((int) methodid <= MEMORY_CONTEXT_METHODID_MASK);
     179                 : 
     180        11334463 :     chunk->hdrmask = MEMORYCHUNK_MAGIC | (((uint64) 1) << MEMORYCHUNK_EXTERNAL_BASEBIT) |
     181                 :         methodid;
     182        11334463 : }
     183                 : 
     184                 : /*
     185                 :  * MemoryChunkIsExternal
     186                 :  *      Return true if 'chunk' is marked as external.
     187                 :  */
     188                 : static inline bool
     189      4127461249 : MemoryChunkIsExternal(MemoryChunk *chunk)
     190                 : {
     191                 :     /*
     192                 :      * External chunks should always store MEMORYCHUNK_MAGIC in the upper
     193                 :      * portion of the hdrmask, check that nothing has stomped on that.
     194                 :      */
     195      4127461249 :     Assert(!HdrMaskIsExternal(chunk->hdrmask) ||
     196                 :            HdrMaskCheckMagic(chunk->hdrmask));
     197                 : 
     198      4127461249 :     return HdrMaskIsExternal(chunk->hdrmask);
     199                 : }
     200                 : 
     201                 : /*
     202                 :  * MemoryChunkGetValue
     203                 :  *      For non-external chunks, returns the value field as it was set in
     204                 :  *      MemoryChunkSetHdrMask.
     205                 :  */
     206                 : static inline Size
     207      4329954035 : MemoryChunkGetValue(MemoryChunk *chunk)
     208                 : {
     209      4329954035 :     Assert(!HdrMaskIsExternal(chunk->hdrmask));
     210                 : 
     211      4329954035 :     return HdrMaskGetValue(chunk->hdrmask);
     212                 : }
     213                 : 
     214                 : /*
     215                 :  * MemoryChunkGetBlock
     216                 :  *      For non-external chunks, returns the pointer to the block as was set
     217                 :  *      in MemoryChunkSetHdrMask.
     218                 :  */
     219                 : static inline void *
     220      4073405479 : MemoryChunkGetBlock(MemoryChunk *chunk)
     221                 : {
     222      4073405479 :     Assert(!HdrMaskIsExternal(chunk->hdrmask));
     223                 : 
     224      4073405479 :     return (void *) ((char *) chunk - HdrMaskBlockOffset(chunk->hdrmask));
     225                 : }
     226                 : 
     227                 : /* cleanup all internal definitions */
     228                 : #undef MEMORYCHUNK_EXTERNAL_BASEBIT
     229                 : #undef MEMORYCHUNK_VALUE_BASEBIT
     230                 : #undef MEMORYCHUNK_BLOCKOFFSET_BASEBIT
     231                 : #undef MEMORYCHUNK_MAGIC
     232                 : #undef HdrMaskIsExternal
     233                 : #undef HdrMaskGetValue
     234                 : #undef HdrMaskBlockOffset
     235                 : #undef HdrMaskCheckMagic
     236                 : 
     237                 : #endif                          /* MEMUTILS_MEMORYCHUNK_H */
        

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