@ -70,6 +70,9 @@ typedef struct SlabContext
int chunksPerBlock ; /* number of chunks per block */
int chunksPerBlock ; /* number of chunks per block */
int minFreeChunks ; /* min number of free chunks in any block */
int minFreeChunks ; /* min number of free chunks in any block */
int nblocks ; /* number of blocks allocated */
int nblocks ; /* number of blocks allocated */
# ifdef MEMORY_CONTEXT_CHECKING
bool * freechunks ; /* bitmap of free chunks in a block */
# endif
/* blocks with free space, grouped by number of free chunks: */
/* blocks with free space, grouped by number of free chunks: */
dlist_head freelist [ FLEXIBLE_ARRAY_MEMBER ] ;
dlist_head freelist [ FLEXIBLE_ARRAY_MEMBER ] ;
} SlabContext ;
} SlabContext ;
@ -229,6 +232,15 @@ SlabContextCreate(MemoryContext parent,
/* Size of the memory context header */
/* Size of the memory context header */
headerSize = offsetof ( SlabContext , freelist ) + freelistSize ;
headerSize = offsetof ( SlabContext , freelist ) + freelistSize ;
# ifdef MEMORY_CONTEXT_CHECKING
/*
* With memory checking , we need to allocate extra space for the bitmap
* of free chunks . The bitmap is an array of bools , so we don ' t need to
* worry about alignment .
*/
headerSize + = chunksPerBlock * sizeof ( bool ) ;
# endif
slab = ( SlabContext * ) malloc ( headerSize ) ;
slab = ( SlabContext * ) malloc ( headerSize ) ;
if ( slab = = NULL )
if ( slab = = NULL )
{
{
@ -258,6 +270,12 @@ SlabContextCreate(MemoryContext parent,
for ( i = 0 ; i < ( slab - > chunksPerBlock + 1 ) ; i + + )
for ( i = 0 ; i < ( slab - > chunksPerBlock + 1 ) ; i + + )
dlist_init ( & slab - > freelist [ i ] ) ;
dlist_init ( & slab - > freelist [ i ] ) ;
# ifdef MEMORY_CONTEXT_CHECKING
/* set the freechunks pointer right after the freelists array */
slab - > freechunks
= ( bool * ) slab + offsetof ( SlabContext , freelist ) + freelistSize ;
# endif
/* Finally, do the type-independent part of context creation */
/* Finally, do the type-independent part of context creation */
MemoryContextCreate ( ( MemoryContext ) slab ,
MemoryContextCreate ( ( MemoryContext ) slab ,
T_SlabContext ,
T_SlabContext ,
@ -701,14 +719,10 @@ SlabCheck(MemoryContext context)
int i ;
int i ;
SlabContext * slab = castNode ( SlabContext , context ) ;
SlabContext * slab = castNode ( SlabContext , context ) ;
const char * name = slab - > header . name ;
const char * name = slab - > header . name ;
char * freechunks ;
Assert ( slab ) ;
Assert ( slab ) ;
Assert ( slab - > chunksPerBlock > 0 ) ;
Assert ( slab - > chunksPerBlock > 0 ) ;
/* bitmap of free chunks on a block */
freechunks = palloc ( slab - > chunksPerBlock * sizeof ( bool ) ) ;
/* walk all the freelists */
/* walk all the freelists */
for ( i = 0 ; i < = slab - > chunksPerBlock ; i + + )
for ( i = 0 ; i < = slab - > chunksPerBlock ; i + + )
{
{
@ -731,7 +745,7 @@ SlabCheck(MemoryContext context)
name , block - > nfree , block , i ) ;
name , block - > nfree , block , i ) ;
/* reset the bitmap of free chunks for this block */
/* reset the bitmap of free chunks for this block */
memset ( freechunks , 0 , ( slab - > chunksPerBlock * sizeof ( bool ) ) ) ;
memset ( slab - > freechunks , 0 , ( slab - > chunksPerBlock * sizeof ( bool ) ) ) ;
idx = block - > firstFreeChunk ;
idx = block - > firstFreeChunk ;
/*
/*
@ -748,7 +762,7 @@ SlabCheck(MemoryContext context)
/* count the chunk as free, add it to the bitmap */
/* count the chunk as free, add it to the bitmap */
nfree + + ;
nfree + + ;
freechunks [ idx ] = true ;
slab - > freechunks [ idx ] = true ;
/* read index of the next free chunk */
/* read index of the next free chunk */
chunk = SlabBlockGetChunk ( slab , block , idx ) ;
chunk = SlabBlockGetChunk ( slab , block , idx ) ;
@ -759,7 +773,7 @@ SlabCheck(MemoryContext context)
for ( j = 0 ; j < slab - > chunksPerBlock ; j + + )
for ( j = 0 ; j < slab - > chunksPerBlock ; j + + )
{
{
/* non-zero bit in the bitmap means chunk the chunk is used */
/* non-zero bit in the bitmap means chunk the chunk is used */
if ( ! freechunks [ j ] )
if ( ! slab - > freechunks [ j ] )
{
{
SlabChunk * chunk = SlabBlockGetChunk ( slab , block , j ) ;
SlabChunk * chunk = SlabBlockGetChunk ( slab , block , j ) ;