Ensure sizeof(GenerationChunk) is maxaligned.

Per buildfarm.

Also improve some comments.
This commit is contained in:
Tom Lane 2017-11-23 17:02:15 -05:00
parent 3c49c6facb
commit 07bd77b95a
1 changed files with 24 additions and 17 deletions

View File

@ -9,7 +9,7 @@
* Portions Copyright (c) 2017, PostgreSQL Global Development Group * Portions Copyright (c) 2017, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* src/backend/utils/mmgr/Generation.c * src/backend/utils/mmgr/generation.c
* *
* *
* This memory context is based on the assumption that the chunks are freed * This memory context is based on the assumption that the chunks are freed
@ -21,8 +21,8 @@
* The memory context uses a very simple approach to free space management. * The memory context uses a very simple approach to free space management.
* Instead of a complex global freelist, each block tracks a number * Instead of a complex global freelist, each block tracks a number
* of allocated and freed chunks. Freed chunks are not reused, and once all * of allocated and freed chunks. Freed chunks are not reused, and once all
* chunks on a block are freed, the whole block is thrown away. When the * chunks in a block are freed, the whole block is thrown away. When the
* chunks allocated on the same block have similar lifespan, this works * chunks allocated in the same block have similar lifespan, this works
* very well and is very cheap. * very well and is very cheap.
* *
* The current implementation only uses a fixed block size - maybe it should * The current implementation only uses a fixed block size - maybe it should
@ -38,15 +38,15 @@
#include "postgres.h" #include "postgres.h"
#include "lib/ilist.h"
#include "utils/memdebug.h" #include "utils/memdebug.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "lib/ilist.h"
#define Generation_BLOCKHDRSZ MAXALIGN(sizeof(GenerationBlock)) #define Generation_BLOCKHDRSZ MAXALIGN(sizeof(GenerationBlock))
#define Generation_CHUNKHDRSZ sizeof(GenerationChunk) #define Generation_CHUNKHDRSZ sizeof(GenerationChunk)
/* Portion of Generation_CHUNKHDRSZ examined outside Generation.c. */ /* Portion of Generation_CHUNKHDRSZ examined outside generation.c. */
#define Generation_CHUNK_PUBLIC \ #define Generation_CHUNK_PUBLIC \
(offsetof(GenerationChunk, size) + sizeof(Size)) (offsetof(GenerationChunk, size) + sizeof(Size))
@ -65,36 +65,35 @@ typedef struct GenerationChunk GenerationChunk;
typedef void *GenerationPointer; typedef void *GenerationPointer;
/* /*
* GenerationContext is a simple memory context not reusing allocated chunks, and * GenerationContext is a simple memory context not reusing allocated chunks,
* freeing blocks once all chunks are freed. * and freeing blocks once all chunks are freed.
*/ */
typedef struct GenerationContext typedef struct GenerationContext
{ {
MemoryContextData header; /* Standard memory-context fields */ MemoryContextData header; /* Standard memory-context fields */
/* Generationerational context parameters */ /* Generational context parameters */
Size blockSize; /* block size */ Size blockSize; /* block size */
GenerationBlock *block; /* current (most recently allocated) block */ GenerationBlock *block; /* current (most recently allocated) block */
dlist_head blocks; /* list of blocks */ dlist_head blocks; /* list of blocks */
} GenerationContext; } GenerationContext;
/* /*
* GenerationBlock * GenerationBlock
* A GenerationBlock is the unit of memory that is obtained by Generation.c * GenerationBlock is the unit of memory that is obtained by generation.c
* from malloc(). It contains one or more GenerationChunks, which are * from malloc(). It contains one or more GenerationChunks, which are
* the units requested by palloc() and freed by pfree(). GenerationChunks * the units requested by palloc() and freed by pfree(). GenerationChunks
* cannot be returned to malloc() individually, instead pfree() * cannot be returned to malloc() individually, instead pfree()
* updates a free counter on a block and when all chunks on a block * updates the free counter of the block and when all chunks in a block
* are freed the whole block is returned to malloc(). * are free the whole block is returned to malloc().
* *
* GenerationBloc is the header data for a block --- the usable space * GenerationBlock is the header data for a block --- the usable space
* within the block begins at the next alignment boundary. * within the block begins at the next alignment boundary.
*/ */
struct GenerationBlock struct GenerationBlock
{ {
dlist_node node; /* doubly-linked list */ dlist_node node; /* doubly-linked list of blocks */
int nchunks; /* number of chunks in the block */ int nchunks; /* number of chunks in the block */
int nfree; /* number of free chunks */ int nfree; /* number of free chunks */
char *freeptr; /* start of free space in this block */ char *freeptr; /* start of free space in this block */
@ -103,7 +102,7 @@ struct GenerationBlock
/* /*
* GenerationChunk * GenerationChunk
* The prefix of each piece of memory in an GenerationBlock * The prefix of each piece of memory in a GenerationBlock
*/ */
struct GenerationChunk struct GenerationChunk
{ {
@ -116,9 +115,17 @@ struct GenerationChunk
/* when debugging memory usage, also store actual requested size */ /* when debugging memory usage, also store actual requested size */
/* this is zero in a free chunk */ /* this is zero in a free chunk */
Size requested_size; Size requested_size;
#endif /* MEMORY_CONTEXT_CHECKING */ #define GENERATIONCHUNK_RAWSIZE (SIZEOF_VOID_P * 2 + SIZEOF_SIZE_T * 2)
#else
#define GENERATIONCHUNK_RAWSIZE (SIZEOF_VOID_P * 2 + SIZEOF_SIZE_T)
#endif /* MEMORY_CONTEXT_CHECKING */
GenerationContext *context; /* owning context */ /* ensure proper alignment by adding padding if needed */
#if (GENERATIONCHUNK_RAWSIZE % MAXIMUM_ALIGNOF) != 0
char padding[MAXIMUM_ALIGNOF - (GENERATIONCHUNK_RAWSIZE % MAXIMUM_ALIGNOF)];
#endif
GenerationContext *context; /* owning context */
/* there must not be any padding to reach a MAXALIGN boundary here! */ /* there must not be any padding to reach a MAXALIGN boundary here! */
}; };