summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorDavid Rowley2024-04-07 11:32:00 +0000
committerDavid Rowley2024-04-07 11:32:00 +0000
commit0ba8b75e7ea6b7b3090c81239ebcb866772a624b (patch)
tree3015678f6979d3f4fff6dedf80fb0ff938ee273c /src/backend
parentc4ab7da60617f020e8d75b1584d0754005d71830 (diff)
Enlarge bit-space for MemoryContextMethodID
Reserve 4 bits for MemoryContextMethodID rather than 3. 3 bits did technically allow a maximum of 8 memory context types, however, we've opted to reserve some bit patterns which left us with only 4 slots, all of which were used. Here we add another bit which frees up 8 slots for future memory context types. In passing, adjust the enum names in MemoryContextMethodID to make it more clear which ones can be used and which ones are reserved. Author: Matthias van de Meent, David Rowley Discussion: https://postgr.es/m/CAApHDvqGSpCU95TmM=Bp=6xjL_nLys4zdZOpfNyWBk97Xrdj2w@mail.gmail.com
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/utils/mmgr/README21
-rw-r--r--src/backend/utils/mmgr/mcxt.c43
2 files changed, 35 insertions, 29 deletions
diff --git a/src/backend/utils/mmgr/README b/src/backend/utils/mmgr/README
index b20b9d48526..f484f7d6f5b 100644
--- a/src/backend/utils/mmgr/README
+++ b/src/backend/utils/mmgr/README
@@ -395,14 +395,14 @@ relevant MemoryContext as a parameter, operations like free and
realloc are trickier. To make those work, we require all memory
context types to produce allocated chunks that are immediately,
without any padding, preceded by a uint64 value of which the least
-significant 3 bits are set to the owning context's MemoryContextMethodID.
+significant 4 bits are set to the owning context's MemoryContextMethodID.
This allows the code to determine the correct MemoryContextMethods to
-use by looking up the mcxt_methods[] array using the 3 bits as an index
+use by looking up the mcxt_methods[] array using the 4 bits as an index
into that array.
If a type of allocator needs additional information about its chunks,
like e.g. the size of the allocation, that information can in turn
-either be encoded into the remaining 61 bits of the preceding uint64 value
+either be encoded into the remaining 60 bits of the preceding uint64 value
or if more space is required, additional values may be stored directly prior
to the uint64 value. It is up to the context implementation to manage this.
@@ -420,13 +420,20 @@ pfree(void *pointer)
All of the current memory contexts make use of the MemoryChunk header type
which is defined in memutils_memorychunk.h. This suits all of the existing
-context types well as it makes use of the remaining 61-bits of the uint64
+context types well as it makes use of the remaining 60-bits of the uint64
header to efficiently encode the size of the chunk of memory (or freelist
index, in the case of aset.c) and the number of bytes which must be subtracted
from the chunk in order to obtain a reference to the block that the chunk
-belongs to. 30 bits are used for each of these. If more than 30 bits are
-required then the memory context must manage that itself. This can be done by
-calling the MemoryChunkSetHdrMaskExternal() function on the given chunk.
+belongs to. 30 bits are used for each of these, but only a total of 59 bits
+as the lowest bit for the chunk to block offset is the same bit as the highest
+bit of the chunk size. This overlapping is possible as the relative offset
+between the block and the chunk is expected to be a MAXALIGNed value which
+guarantees the lowest bit is always 0. If more than 30 bits are required for
+each of these fields then the memory context must manage that itself. This
+can be done by calling the MemoryChunkSetHdrMaskExternal() function on the
+given chunk. Whether a chunk is an external chunk can be determined by the 1
+remaining bit from the 64-bit MemoryChunk.
+
Currently, each memory context type stores large allocations on dedicated
blocks (which always contain only a single chunk). For these, finding the
block is simple as we know that the chunk must be the first on the given
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index 5d426795d9d..b2143b2fc6c 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -37,6 +37,11 @@ static Size BogusGetChunkSpace(void *pointer);
/*****************************************************************************
* GLOBAL MEMORY *
*****************************************************************************/
+#define BOGUS_MCTX(id) \
+ [id].free_p = BogusFree, \
+ [id].realloc = BogusRealloc, \
+ [id].get_chunk_context = BogusGetChunkContext, \
+ [id].get_chunk_space = BogusGetChunkSpace
static const MemoryContextMethods mcxt_methods[] = {
/* aset.c */
@@ -97,33 +102,27 @@ static const MemoryContextMethods mcxt_methods[] = {
/*
- * Unused (as yet) IDs should have dummy entries here. This allows us to
- * fail cleanly if a bogus pointer is passed to pfree or the like. It
+ * Reserved and unused IDs should have dummy entries here. This allows us
+ * to fail cleanly if a bogus pointer is passed to pfree or the like. It
* seems sufficient to provide routines for the methods that might get
* invoked from inspection of a chunk (see MCXT_METHOD calls below).
*/
-
- [MCTX_UNUSED1_ID].free_p = BogusFree,
- [MCTX_UNUSED1_ID].realloc = BogusRealloc,
- [MCTX_UNUSED1_ID].get_chunk_context = BogusGetChunkContext,
- [MCTX_UNUSED1_ID].get_chunk_space = BogusGetChunkSpace,
-
- [MCTX_UNUSED2_ID].free_p = BogusFree,
- [MCTX_UNUSED2_ID].realloc = BogusRealloc,
- [MCTX_UNUSED2_ID].get_chunk_context = BogusGetChunkContext,
- [MCTX_UNUSED2_ID].get_chunk_space = BogusGetChunkSpace,
-
- [MCTX_UNUSED3_ID].free_p = BogusFree,
- [MCTX_UNUSED3_ID].realloc = BogusRealloc,
- [MCTX_UNUSED3_ID].get_chunk_context = BogusGetChunkContext,
- [MCTX_UNUSED3_ID].get_chunk_space = BogusGetChunkSpace,
-
- [MCTX_UNUSED4_ID].free_p = BogusFree,
- [MCTX_UNUSED4_ID].realloc = BogusRealloc,
- [MCTX_UNUSED4_ID].get_chunk_context = BogusGetChunkContext,
- [MCTX_UNUSED4_ID].get_chunk_space = BogusGetChunkSpace,
+ BOGUS_MCTX(MCTX_1_RESERVED_GLIBC_ID),
+ BOGUS_MCTX(MCTX_2_RESERVED_GLIBC_ID),
+ BOGUS_MCTX(MCTX_7_UNUSED_ID),
+ BOGUS_MCTX(MCTX_8_UNUSED_ID),
+ BOGUS_MCTX(MCTX_9_UNUSED_ID),
+ BOGUS_MCTX(MCTX_10_UNUSED_ID),
+ BOGUS_MCTX(MCTX_11_UNUSED_ID),
+ BOGUS_MCTX(MCTX_12_UNUSED_ID),
+ BOGUS_MCTX(MCTX_13_UNUSED_ID),
+ BOGUS_MCTX(MCTX_14_UNUSED_ID),
+ BOGUS_MCTX(MCTX_0_RESERVED_UNUSEDMEM_ID),
+ BOGUS_MCTX(MCTX_15_RESERVED_WIPEDMEM_ID)
};
+#undef BOGUS_MCTX
+
/*
* CurrentMemoryContext
* Default memory context for allocations.