aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/mmgr/slab.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/mmgr/slab.c')
-rw-r--r--src/backend/utils/mmgr/slab.c87
1 files changed, 31 insertions, 56 deletions
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index a5e140eef70..11a126acf36 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -57,12 +57,6 @@
#include "lib/ilist.h"
-#define SLAB_CHUNKHDRSZ MAXALIGN(sizeof(SlabChunk))
-
-/* Portion of SLAB_CHUNKHDRSZ excluding trailing padding. */
-#define SLAB_CHUNK_USED \
- (offsetof(SlabChunk, header) + sizeof(StandardChunkHeader))
-
/*
* SlabContext is a specialized implementation of MemoryContext.
*/
@@ -103,17 +97,15 @@ typedef struct SlabChunk
{
/* block owning this chunk */
void *block;
-
- /* include StandardChunkHeader because mcxt.c expects that */
- StandardChunkHeader header;
-
+ SlabContext *slab; /* owning context */
+ /* there must not be any padding to reach a MAXALIGN boundary here! */
} SlabChunk;
#define SlabPointerGetChunk(ptr) \
- ((SlabChunk *)(((char *)(ptr)) - SLAB_CHUNKHDRSZ))
+ ((SlabChunk *)(((char *)(ptr)) - sizeof(SlabChunk)))
#define SlabChunkGetPointer(chk) \
- ((void *)(((char *)(chk)) + SLAB_CHUNKHDRSZ))
+ ((void *)(((char *)(chk)) + sizeof(SlabChunk)))
#define SlabBlockGetChunk(slab, block, idx) \
((SlabChunk *) ((char *) (block) + sizeof(SlabBlock) \
+ (idx * slab->fullChunkSize)))
@@ -198,6 +190,10 @@ SlabContextCreate(MemoryContext parent,
Size freelistSize;
SlabContext *slab;
+ StaticAssertStmt(offsetof(SlabChunk, slab) +sizeof(MemoryContext) ==
+ MAXALIGN(sizeof(SlabChunk)),
+ "padding calculation in SlabChunk is wrong");
+
/* otherwise the linked list inside freed chunk isn't guaranteed to fit */
StaticAssertStmt(MAXIMUM_ALIGNOF >= sizeof(int),
"MAXALIGN too small to fit int32");
@@ -207,7 +203,7 @@ SlabContextCreate(MemoryContext parent,
/* Make sure the block can store at least one chunk. */
if (blockSize - sizeof(SlabBlock) < fullChunkSize)
- elog(ERROR, "block size %ld for slab is too small for %ld chunks",
+ elog(ERROR, "block size %zu for slab is too small for %zu chunks",
blockSize, chunkSize);
/* Compute maximum number of chunks per block */
@@ -333,7 +329,7 @@ SlabAlloc(MemoryContext context, Size size)
/* make sure we only allow correct request size */
if (size != slab->chunkSize)
- elog(ERROR, "unexpected alloc chunk size %ld (expected %ld)",
+ elog(ERROR, "unexpected alloc chunk size %zu (expected %zu)",
size, slab->chunkSize);
/*
@@ -445,20 +441,21 @@ SlabAlloc(MemoryContext context, Size size)
slab->minFreeChunks = 0;
/* Prepare to initialize the chunk header. */
- VALGRIND_MAKE_MEM_UNDEFINED(chunk, SLAB_CHUNK_USED);
+ VALGRIND_MAKE_MEM_UNDEFINED(chunk, sizeof(SlabChunk));
chunk->block = (void *) block;
-
- chunk->header.context = (MemoryContext) slab;
- chunk->header.size = MAXALIGN(size);
+ chunk->slab = slab;
#ifdef MEMORY_CONTEXT_CHECKING
- chunk->header.requested_size = size;
- VALGRIND_MAKE_MEM_NOACCESS(&chunk->header.requested_size,
- sizeof(chunk->header.requested_size));
/* slab mark to catch clobber of "unused" space */
- if (size < chunk->header.size)
+ if (slab->chunkSize < (slab->fullChunkSize - sizeof(SlabChunk)))
+ {
set_sentinel(SlabChunkGetPointer(chunk), size);
+ VALGRIND_MAKE_MEM_NOACCESS(((char *) chunk) +
+ sizeof(SlabChunk) + slab->chunkSize,
+ slab->fullChunkSize -
+ (slab->chunkSize + sizeof(SlabChunk)));
+ }
#endif
#ifdef RANDOMIZE_ALLOCATED_MEMORY
/* fill the allocated space with junk */
@@ -484,11 +481,9 @@ SlabFree(MemoryContext context, void *pointer)
SlabFreeInfo(slab, chunk);
#ifdef MEMORY_CONTEXT_CHECKING
- VALGRIND_MAKE_MEM_DEFINED(&chunk->header.requested_size,
- sizeof(chunk->header.requested_size));
/* Test for someone scribbling on unused space in chunk */
- if (chunk->header.requested_size < chunk->header.size)
- if (!sentinel_ok(pointer, chunk->header.requested_size))
+ if (slab->chunkSize < (slab->fullChunkSize - sizeof(SlabChunk)))
+ if (!sentinel_ok(pointer, slab->chunkSize))
elog(WARNING, "detected write past chunk end in %s %p",
slab->header.name, chunk);
#endif
@@ -507,12 +502,7 @@ SlabFree(MemoryContext context, void *pointer)
#ifdef CLOBBER_FREED_MEMORY
/* XXX don't wipe the int32 index, used for block-level freelist */
wipe_mem((char *) pointer + sizeof(int32),
- chunk->header.size - sizeof(int32));
-#endif
-
-#ifdef MEMORY_CONTEXT_CHECKING
- /* Reset requested_size to 0 in chunks that are on freelist */
- chunk->header.requested_size = 0;
+ slab->chunkSize - sizeof(int32));
#endif
/* remove the block from a freelist */
@@ -590,9 +580,11 @@ SlabRealloc(MemoryContext context, void *pointer, Size size)
static Size
SlabGetChunkSpace(MemoryContext context, void *pointer)
{
- SlabChunk *chunk = SlabPointerGetChunk(pointer);
+ SlabContext *slab = castNode(SlabContext, context);
+
+ Assert(slab);
- return chunk->header.size + SLAB_CHUNKHDRSZ;
+ return slab->fullChunkSize;
}
/*
@@ -742,37 +734,20 @@ SlabCheck(MemoryContext context)
{
SlabChunk *chunk = SlabBlockGetChunk(slab, block, j);
- VALGRIND_MAKE_MEM_DEFINED(&chunk->header.requested_size,
- sizeof(chunk->header.requested_size));
-
- /* we're in a no-freelist branch */
- VALGRIND_MAKE_MEM_NOACCESS(&chunk->header.requested_size,
- sizeof(chunk->header.requested_size));
-
/* chunks have both block and slab pointers, so check both */
if (chunk->block != block)
elog(WARNING, "problem in slab %s: bogus block link in block %p, chunk %p",
name, block, chunk);
- if (chunk->header.context != (MemoryContext) slab)
+ if (chunk->slab != slab)
elog(WARNING, "problem in slab %s: bogus slab link in block %p, chunk %p",
name, block, chunk);
- /* now make sure the chunk size is correct */
- if (chunk->header.size != MAXALIGN(slab->chunkSize))
- elog(WARNING, "problem in slab %s: bogus chunk size in block %p, chunk %p",
- name, block, chunk);
-
- /* now make sure the chunk size is correct */
- if (chunk->header.requested_size != slab->chunkSize)
- elog(WARNING, "problem in slab %s: bogus chunk requested size in block %p, chunk %p",
- name, block, chunk);
-
/* there might be sentinel (thanks to alignment) */
- if (chunk->header.requested_size < chunk->header.size &&
- !sentinel_ok(chunk, SLAB_CHUNKHDRSZ + chunk->header.requested_size))
- elog(WARNING, "problem in slab %s: detected write past chunk end in block %p, chunk %p",
- name, block, chunk);
+ if (slab->chunkSize < (slab->fullChunkSize - sizeof(SlabChunk)))
+ if (!sentinel_ok(chunk, slab->chunkSize))
+ elog(WARNING, "problem in slab %s: detected write past chunk end in block %p, chunk %p",
+ name, block, chunk);
}
}