mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03:00
Reduce size of common allocation header.
The new slab allocator needs different per-allocation information than
the classical aset.c. The definition in 58b25e981 wasn't sufficiently
careful on 32 platforms with 8 byte alignment, leading to buildfarm
failures. That's not entirely easy to fix by just adjusting the
definition.
As slab.c doesn't actually need the size part(s) of the common header,
all chunks are equally sized after all, it seems better to instead
reduce the header to the part needed by all allocators, namely which
context an allocation belongs to. That has the advantage of reducing
the overhead of slab allocations, and also allows for more flexibility
in future allocators.
To avoid spreading the logic about accessing a chunk's context around,
centralize it in GetMemoryChunkContext(), which allows to delete a
good number of lines.
A followup commit will revise the mmgr/README portion about
StandardChunkHeader, and more.
Author: Andres Freund
Discussion: https://postgr.es/m/20170228074420.aazv4iw6k562mnxg@alap3.anarazel.de
This commit is contained in:
@@ -97,20 +97,7 @@
|
||||
*/
|
||||
|
||||
#define ALLOC_BLOCKHDRSZ MAXALIGN(sizeof(AllocBlockData))
|
||||
#define ALLOC_CHUNKHDRSZ MAXALIGN(sizeof(AllocChunkData))
|
||||
|
||||
/* Portion of ALLOC_CHUNKHDRSZ examined outside aset.c. */
|
||||
#define ALLOC_CHUNK_PUBLIC \
|
||||
(offsetof(AllocChunkData, size) + sizeof(Size))
|
||||
|
||||
/* Portion of ALLOC_CHUNKHDRSZ excluding trailing padding. */
|
||||
#ifdef MEMORY_CONTEXT_CHECKING
|
||||
#define ALLOC_CHUNK_USED \
|
||||
(offsetof(AllocChunkData, requested_size) + sizeof(Size))
|
||||
#else
|
||||
#define ALLOC_CHUNK_USED \
|
||||
(offsetof(AllocChunkData, size) + sizeof(Size))
|
||||
#endif
|
||||
#define ALLOC_CHUNKHDRSZ sizeof(struct AllocChunkData)
|
||||
|
||||
typedef struct AllocBlockData *AllocBlock; /* forward reference */
|
||||
typedef struct AllocChunkData *AllocChunk;
|
||||
@@ -169,20 +156,25 @@ typedef struct AllocBlockData
|
||||
/*
|
||||
* AllocChunk
|
||||
* The prefix of each piece of memory in an AllocBlock
|
||||
*
|
||||
* NB: this MUST match StandardChunkHeader as defined by utils/memutils.h.
|
||||
*/
|
||||
typedef struct AllocChunkData
|
||||
{
|
||||
/* aset is the owning aset if allocated, or the freelist link if free */
|
||||
void *aset;
|
||||
/* size is always the size of the usable space in the chunk */
|
||||
Size size;
|
||||
#ifdef MEMORY_CONTEXT_CHECKING
|
||||
/* when debugging memory usage, also store actual requested size */
|
||||
/* this is zero in a free chunk */
|
||||
Size requested_size;
|
||||
#if MAXIMUM_ALIGNOF > 4 && SIZEOF_VOID_P == 4
|
||||
Size padding;
|
||||
#endif
|
||||
|
||||
#endif /* MEMORY_CONTEXT_CHECKING */
|
||||
|
||||
/* aset is the owning aset if allocated, or the freelist link if free */
|
||||
void *aset;
|
||||
|
||||
/* there must not be any padding to reach a MAXALIGN boundary here! */
|
||||
} AllocChunkData;
|
||||
|
||||
/*
|
||||
@@ -334,6 +326,10 @@ AllocSetContextCreate(MemoryContext parent,
|
||||
{
|
||||
AllocSet set;
|
||||
|
||||
StaticAssertStmt(offsetof(AllocChunkData, aset) + sizeof(MemoryContext) ==
|
||||
MAXALIGN(sizeof(AllocChunkData)),
|
||||
"padding calculation in AllocChunkData is wrong");
|
||||
|
||||
/*
|
||||
* First, validate allocation parameters. (If we're going to throw an
|
||||
* error, we should do so before the context is created, not after.) We
|
||||
@@ -616,13 +612,13 @@ AllocSetAlloc(MemoryContext context, Size size)
|
||||
AllocAllocInfo(set, chunk);
|
||||
|
||||
/*
|
||||
* Chunk header public fields remain DEFINED. The requested
|
||||
* allocation itself can be NOACCESS or UNDEFINED; our caller will
|
||||
* soon make it UNDEFINED. Make extra space at the end of the chunk,
|
||||
* if any, NOACCESS.
|
||||
* Chunk's metadata fields remain DEFINED. The requested allocation
|
||||
* itself can be NOACCESS or UNDEFINED; our caller will soon make it
|
||||
* UNDEFINED. Make extra space at the end of the chunk, if any,
|
||||
* NOACCESS.
|
||||
*/
|
||||
VALGRIND_MAKE_MEM_NOACCESS((char *) chunk + ALLOC_CHUNK_PUBLIC,
|
||||
chunk_size + ALLOC_CHUNKHDRSZ - ALLOC_CHUNK_PUBLIC);
|
||||
VALGRIND_MAKE_MEM_NOACCESS((char *) chunk + ALLOC_CHUNKHDRSZ,
|
||||
chunk_size - ALLOC_CHUNKHDRSZ);
|
||||
|
||||
return AllocChunkGetPointer(chunk);
|
||||
}
|
||||
@@ -709,7 +705,7 @@ AllocSetAlloc(MemoryContext context, Size size)
|
||||
chunk = (AllocChunk) (block->freeptr);
|
||||
|
||||
/* Prepare to initialize the chunk header. */
|
||||
VALGRIND_MAKE_MEM_UNDEFINED(chunk, ALLOC_CHUNK_USED);
|
||||
VALGRIND_MAKE_MEM_UNDEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
||||
|
||||
block->freeptr += (availchunk + ALLOC_CHUNKHDRSZ);
|
||||
availspace -= (availchunk + ALLOC_CHUNKHDRSZ);
|
||||
@@ -799,7 +795,7 @@ AllocSetAlloc(MemoryContext context, Size size)
|
||||
chunk = (AllocChunk) (block->freeptr);
|
||||
|
||||
/* Prepare to initialize the chunk header. */
|
||||
VALGRIND_MAKE_MEM_UNDEFINED(chunk, ALLOC_CHUNK_USED);
|
||||
VALGRIND_MAKE_MEM_UNDEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
||||
|
||||
block->freeptr += (chunk_size + ALLOC_CHUNKHDRSZ);
|
||||
Assert(block->freeptr <= block->endptr);
|
||||
|
||||
Reference in New Issue
Block a user