diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c index 0bbbf93672..c3affaf5a8 100644 --- a/src/backend/utils/mmgr/aset.c +++ b/src/backend/utils/mmgr/aset.c @@ -156,11 +156,10 @@ typedef struct AllocSetContext AllocBlock blocks; /* head of list of blocks in this set */ MemoryChunk *freelist[ALLOCSET_NUM_FREELISTS]; /* free chunk lists */ /* Allocation parameters for this context: */ - Size initBlockSize; /* initial block size */ - Size maxBlockSize; /* maximum block size */ - Size nextBlockSize; /* next block size to allocate */ - Size allocChunkLimit; /* effective chunk size limit */ - AllocBlock keeper; /* keep this block over resets */ + uint32 initBlockSize; /* initial block size */ + uint32 maxBlockSize; /* maximum block size */ + uint32 nextBlockSize; /* next block size to allocate */ + uint32 allocChunkLimit; /* effective chunk size limit */ /* freelist this context could be put in, or -1 if not a candidate: */ int freeListIndex; /* index in context_freelists[], or -1 */ } AllocSetContext; @@ -241,6 +240,13 @@ typedef struct AllocBlockData */ #define MAX_FREE_CONTEXTS 100 /* arbitrary limit on freelist length */ +/* Obtain the keeper block for an allocation set */ +#define KeeperBlock(set) \ + ((AllocBlock) (((char *) set) + MAXALIGN(sizeof(AllocSetContext)))) + +/* Check if the block is the keeper block of the given allocation set */ +#define IsKeeperBlock(set, block) ((block) == (KeeperBlock(set))) + typedef struct AllocSetFreeList { int num_free; /* current list length */ @@ -417,7 +423,7 @@ AllocSetContextCreateInternal(MemoryContext parent, name); ((MemoryContext) set)->mem_allocated = - set->keeper->endptr - ((char *) set); + KeeperBlock(set)->endptr - ((char *) set); return (MemoryContext) set; } @@ -453,7 +459,7 @@ AllocSetContextCreateInternal(MemoryContext parent, */ /* Fill in the initial block's block header */ - block = (AllocBlock) (((char *) set) + MAXALIGN(sizeof(AllocSetContext))); + block = KeeperBlock(set); block->aset = set; block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ; block->endptr = ((char *) set) + firstBlockSize; @@ -465,15 +471,13 @@ AllocSetContextCreateInternal(MemoryContext parent, /* Remember block as part of block list */ set->blocks = block; - /* Mark block as not to be released at reset time */ - set->keeper = block; /* Finish filling in aset-specific parts of the context header */ MemSetAligned(set->freelist, 0, sizeof(set->freelist)); - set->initBlockSize = initBlockSize; - set->maxBlockSize = maxBlockSize; - set->nextBlockSize = initBlockSize; + set->initBlockSize = (uint32) initBlockSize; + set->maxBlockSize = (uint32) maxBlockSize; + set->nextBlockSize = (uint32) initBlockSize; set->freeListIndex = freeListIndex; /* @@ -544,7 +548,7 @@ AllocSetReset(MemoryContext context) #endif /* Remember keeper block size for Assert below */ - keepersize = set->keeper->endptr - ((char *) set); + keepersize = KeeperBlock(set)->endptr - ((char *) set); /* Clear chunk freelists */ MemSetAligned(set->freelist, 0, sizeof(set->freelist)); @@ -552,13 +556,13 @@ AllocSetReset(MemoryContext context) block = set->blocks; /* New blocks list will be just the keeper block */ - set->blocks = set->keeper; + set->blocks = KeeperBlock(set); while (block != NULL) { AllocBlock next = block->next; - if (block == set->keeper) + if (IsKeeperBlock(set, block)) { /* Reset the block, but don't return it to malloc */ char *datastart = ((char *) block) + ALLOC_BLOCKHDRSZ; @@ -614,7 +618,7 @@ AllocSetDelete(MemoryContext context) #endif /* Remember keeper block size for Assert below */ - keepersize = set->keeper->endptr - ((char *) set); + keepersize = KeeperBlock(set)->endptr - ((char *) set); /* * If the context is a candidate for a freelist, put it into that freelist @@ -663,14 +667,14 @@ AllocSetDelete(MemoryContext context) { AllocBlock next = block->next; - if (block != set->keeper) + if (!IsKeeperBlock(set, block)) context->mem_allocated -= block->endptr - ((char *) block); #ifdef CLOBBER_FREED_MEMORY wipe_mem(block, block->freeptr - ((char *) block)); #endif - if (block != set->keeper) + if (!IsKeeperBlock(set, block)) free(block); block = next; @@ -1547,7 +1551,7 @@ AllocSetCheck(MemoryContext context) long nchunks = 0; bool has_external_chunk = false; - if (set->keeper == block) + if (IsKeeperBlock(set, block)) total_allocated += block->endptr - ((char *) set); else total_allocated += block->endptr - ((char *) block); @@ -1557,7 +1561,7 @@ AllocSetCheck(MemoryContext context) */ if (!blk_used) { - if (set->keeper != block) + if (!IsKeeperBlock(set, block)) elog(WARNING, "problem in alloc set %s: empty block %p", name, block); } diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c index 4fb8663cd6..92401ccf73 100644 --- a/src/backend/utils/mmgr/generation.c +++ b/src/backend/utils/mmgr/generation.c @@ -61,17 +61,16 @@ typedef struct GenerationContext MemoryContextData header; /* Standard memory-context fields */ /* Generational context parameters */ - Size initBlockSize; /* initial block size */ - Size maxBlockSize; /* maximum block size */ - Size nextBlockSize; /* next block size to allocate */ - Size allocChunkLimit; /* effective chunk size limit */ + uint32 initBlockSize; /* initial block size */ + uint32 maxBlockSize; /* maximum block size */ + uint32 nextBlockSize; /* next block size to allocate */ + uint32 allocChunkLimit; /* effective chunk size limit */ GenerationBlock *block; /* current (most recently allocated) block, or * NULL if we've just freed the most recent * block */ GenerationBlock *freeblock; /* pointer to a block that's being recycled, * or NULL if there's no such block. */ - GenerationBlock *keeper; /* keep this block over resets */ dlist_head blocks; /* list of blocks */ } GenerationContext; @@ -120,6 +119,14 @@ struct GenerationBlock #define ExternalChunkGetBlock(chunk) \ (GenerationBlock *) ((char *) chunk - Generation_BLOCKHDRSZ) +/* Obtain the keeper block for a generation context */ +#define KeeperBlock(set) \ + ((GenerationBlock *) (((char *) set) + \ + MAXALIGN(sizeof(GenerationContext)))) + +/* Check if the block is the keeper block of the given generation context */ +#define IsKeeperBlock(set, block) ((block) == (KeeperBlock(set))) + /* Inlined helper functions */ static inline void GenerationBlockInit(GenerationContext *context, GenerationBlock *block, @@ -214,7 +221,7 @@ GenerationContextCreate(MemoryContext parent, dlist_init(&set->blocks); /* Fill in the initial block's block header */ - block = (GenerationBlock *) (((char *) set) + MAXALIGN(sizeof(GenerationContext))); + block = KeeperBlock(set); /* determine the block size and initialize it */ firstBlockSize = allocSize - MAXALIGN(sizeof(GenerationContext)); GenerationBlockInit(set, block, firstBlockSize); @@ -228,13 +235,10 @@ GenerationContextCreate(MemoryContext parent, /* No free block, yet */ set->freeblock = NULL; - /* Mark block as not to be released at reset time */ - set->keeper = block; - /* Fill in GenerationContext-specific header fields */ - set->initBlockSize = initBlockSize; - set->maxBlockSize = maxBlockSize; - set->nextBlockSize = initBlockSize; + set->initBlockSize = (uint32) initBlockSize; + set->maxBlockSize = (uint32) maxBlockSize; + set->nextBlockSize = (uint32) initBlockSize; /* * Compute the allocation chunk size limit for this context. @@ -294,14 +298,14 @@ GenerationReset(MemoryContext context) { GenerationBlock *block = dlist_container(GenerationBlock, node, miter.cur); - if (block == set->keeper) + if (IsKeeperBlock(set, block)) GenerationBlockMarkEmpty(block); else GenerationBlockFree(set, block); } /* set it so new allocations to make use of the keeper block */ - set->block = set->keeper; + set->block = KeeperBlock(set); /* Reset block size allocation sequence, too */ set->nextBlockSize = set->initBlockSize; @@ -440,10 +444,10 @@ GenerationAlloc(MemoryContext context, Size size) */ set->freeblock = NULL; } - else if (GenerationBlockIsEmpty(set->keeper) && - GenerationBlockFreeBytes(set->keeper) >= required_size) + else if (GenerationBlockIsEmpty(KeeperBlock(set)) && + GenerationBlockFreeBytes(KeeperBlock(set)) >= required_size) { - block = set->keeper; + block = KeeperBlock(set); } else { @@ -594,7 +598,7 @@ static inline void GenerationBlockFree(GenerationContext *set, GenerationBlock *block) { /* Make sure nobody tries to free the keeper block */ - Assert(block != set->keeper); + Assert(!IsKeeperBlock(set, block)); /* We shouldn't be freeing the freeblock either */ Assert(block != set->freeblock); @@ -691,7 +695,7 @@ GenerationFree(void *pointer) set = block->context; /* Don't try to free the keeper block, just mark it empty */ - if (block == set->keeper) + if (IsKeeperBlock(set, block)) { GenerationBlockMarkEmpty(block); return; diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c index 718dd2ba03..40c1d401c4 100644 --- a/src/backend/utils/mmgr/slab.c +++ b/src/backend/utils/mmgr/slab.c @@ -104,9 +104,9 @@ typedef struct SlabContext { MemoryContextData header; /* Standard memory-context fields */ /* Allocation parameters for this context: */ - Size chunkSize; /* the requested (non-aligned) chunk size */ - Size fullChunkSize; /* chunk size with chunk header and alignment */ - Size blockSize; /* the size to make each block of chunks */ + uint32 chunkSize; /* the requested (non-aligned) chunk size */ + uint32 fullChunkSize; /* chunk size with chunk header and alignment */ + uint32 blockSize; /* the size to make each block of chunks */ int32 chunksPerBlock; /* number of chunks that fit in 1 block */ int32 curBlocklistIndex; /* index into the blocklist[] element * containing the fullest, blocks */ @@ -314,7 +314,9 @@ SlabGetNextFreeChunk(SlabContext *slab, SlabBlock *block) * blockSize: allocation block size * chunkSize: allocation chunk size * - * The MAXALIGN(chunkSize) may not exceed MEMORYCHUNK_MAX_VALUE + * The Slab_CHUNKHDRSZ + MAXALIGN(chunkSize + 1) may not exceed + * MEMORYCHUNK_MAX_VALUE. + * 'blockSize' may not exceed MEMORYCHUNK_MAX_BLOCKOFFSET. */ MemoryContext SlabContextCreate(MemoryContext parent, @@ -330,7 +332,7 @@ SlabContextCreate(MemoryContext parent, /* ensure MemoryChunk's size is properly maxaligned */ StaticAssertDecl(Slab_CHUNKHDRSZ == MAXALIGN(Slab_CHUNKHDRSZ), "sizeof(MemoryChunk) is not maxaligned"); - Assert(MAXALIGN(chunkSize) <= MEMORYCHUNK_MAX_VALUE); + Assert(blockSize <= MEMORYCHUNK_MAX_BLOCKOFFSET); /* * Ensure there's enough space to store the pointer to the next free chunk @@ -347,6 +349,8 @@ SlabContextCreate(MemoryContext parent, fullChunkSize = Slab_CHUNKHDRSZ + MAXALIGN(chunkSize); #endif + Assert(fullChunkSize <= MEMORYCHUNK_MAX_VALUE); + /* compute the number of chunks that will fit on each block */ chunksPerBlock = (blockSize - Slab_BLOCKHDRSZ) / fullChunkSize; @@ -374,9 +378,9 @@ SlabContextCreate(MemoryContext parent, */ /* Fill in SlabContext-specific header fields */ - slab->chunkSize = chunkSize; - slab->fullChunkSize = fullChunkSize; - slab->blockSize = blockSize; + slab->chunkSize = (uint32) chunkSize; + slab->fullChunkSize = (uint32) fullChunkSize; + slab->blockSize = (uint32) blockSize; slab->chunksPerBlock = chunksPerBlock; slab->curBlocklistIndex = 0; @@ -506,7 +510,7 @@ SlabAlloc(MemoryContext context, Size size) /* make sure we only allow correct request size */ if (unlikely(size != slab->chunkSize)) - elog(ERROR, "unexpected alloc chunk size %zu (expected %zu)", + elog(ERROR, "unexpected alloc chunk size %zu (expected %u)", size, slab->chunkSize); /*