@ -103,6 +103,8 @@
# define ALLOC_BLOCKHDRSZ MAXALIGN(sizeof(AllocBlockData))
# define ALLOC_BLOCKHDRSZ MAXALIGN(sizeof(AllocBlockData))
# define ALLOC_CHUNKHDRSZ sizeof(MemoryChunk)
# define ALLOC_CHUNKHDRSZ sizeof(MemoryChunk)
# define FIRST_BLOCKHDRSZ (MAXALIGN(sizeof(AllocSetContext)) + \
ALLOC_BLOCKHDRSZ )
typedef struct AllocBlockData * AllocBlock ; /* forward reference */
typedef struct AllocBlockData * AllocBlock ; /* forward reference */
@ -458,6 +460,21 @@ AllocSetContextCreateInternal(MemoryContext parent,
* we ' d leak the header / initial block if we ereport in this stretch .
* we ' d leak the header / initial block if we ereport in this stretch .
*/
*/
/* Create a vpool associated with the context */
VALGRIND_CREATE_MEMPOOL ( set , 0 , false ) ;
/*
* Create a vchunk covering both the AllocSetContext struct and the keeper
* block ' s header . ( Perhaps it would be more sensible for these to be two
* separate vchunks , but doing that seems to tickle bugs in some versions
* of Valgrind . ) We must have these vchunks , and also a vchunk for each
* subsequently - added block header , so that Valgrind considers the
* pointers within them while checking for leaked memory . Note that
* Valgrind doesn ' t distinguish between these vchunks and those created by
* mcxt . c for the user - accessible - data chunks we allocate .
*/
VALGRIND_MEMPOOL_ALLOC ( set , set , FIRST_BLOCKHDRSZ ) ;
/* Fill in the initial block's block header */
/* Fill in the initial block's block header */
block = KeeperBlock ( set ) ;
block = KeeperBlock ( set ) ;
block - > aset = set ;
block - > aset = set ;
@ -585,6 +602,14 @@ AllocSetReset(MemoryContext context)
# ifdef CLOBBER_FREED_MEMORY
# ifdef CLOBBER_FREED_MEMORY
wipe_mem ( block , block - > freeptr - ( ( char * ) block ) ) ;
wipe_mem ( block , block - > freeptr - ( ( char * ) block ) ) ;
# endif
# endif
/*
* We need to free the block header ' s vchunk explicitly , although
* the user - data vchunks within will go away in the TRIM below .
* Otherwise Valgrind complains about leaked allocations .
*/
VALGRIND_MEMPOOL_FREE ( set , block ) ;
free ( block ) ;
free ( block ) ;
}
}
block = next ;
block = next ;
@ -592,6 +617,14 @@ AllocSetReset(MemoryContext context)
Assert ( context - > mem_allocated = = keepersize ) ;
Assert ( context - > mem_allocated = = keepersize ) ;
/*
* Instruct Valgrind to throw away all the vchunks associated with this
* context , except for the one covering the AllocSetContext and
* keeper - block header . This gets rid of the vchunks for whatever user
* data is getting discarded by the context reset .
*/
VALGRIND_MEMPOOL_TRIM ( set , set , FIRST_BLOCKHDRSZ ) ;
/* Reset block size allocation sequence, too */
/* Reset block size allocation sequence, too */
set - > nextBlockSize = set - > initBlockSize ;
set - > nextBlockSize = set - > initBlockSize ;
}
}
@ -648,6 +681,9 @@ AllocSetDelete(MemoryContext context)
freelist - > first_free = ( AllocSetContext * ) oldset - > header . nextchild ;
freelist - > first_free = ( AllocSetContext * ) oldset - > header . nextchild ;
freelist - > num_free - - ;
freelist - > num_free - - ;
/* Destroy the context's vpool --- see notes below */
VALGRIND_DESTROY_MEMPOOL ( oldset ) ;
/* All that remains is to free the header/initial block */
/* All that remains is to free the header/initial block */
free ( oldset ) ;
free ( oldset ) ;
}
}
@ -675,13 +711,24 @@ AllocSetDelete(MemoryContext context)
# endif
# endif
if ( ! IsKeeperBlock ( set , block ) )
if ( ! IsKeeperBlock ( set , block ) )
{
/* As in AllocSetReset, free block-header vchunks explicitly */
VALGRIND_MEMPOOL_FREE ( set , block ) ;
free ( block ) ;
free ( block ) ;
}
block = next ;
block = next ;
}
}
Assert ( context - > mem_allocated = = keepersize ) ;
Assert ( context - > mem_allocated = = keepersize ) ;
/*
* Destroy the vpool . We don ' t seem to need to explicitly free the
* initial block ' s header vchunk , nor any user - data vchunks that Valgrind
* still knows about ; they ' ll all go away automatically .
*/
VALGRIND_DESTROY_MEMPOOL ( set ) ;
/* Finally, free the context header, including the keeper block */
/* Finally, free the context header, including the keeper block */
free ( set ) ;
free ( set ) ;
}
}
@ -716,6 +763,9 @@ AllocSetAllocLarge(MemoryContext context, Size size, int flags)
if ( block = = NULL )
if ( block = = NULL )
return MemoryContextAllocationFailure ( context , size , flags ) ;
return MemoryContextAllocationFailure ( context , size , flags ) ;
/* Make a vchunk covering the new block's header */
VALGRIND_MEMPOOL_ALLOC ( set , block , ALLOC_BLOCKHDRSZ ) ;
context - > mem_allocated + = blksize ;
context - > mem_allocated + = blksize ;
block - > aset = set ;
block - > aset = set ;
@ -922,6 +972,9 @@ AllocSetAllocFromNewBlock(MemoryContext context, Size size, int flags,
if ( block = = NULL )
if ( block = = NULL )
return MemoryContextAllocationFailure ( context , size , flags ) ;
return MemoryContextAllocationFailure ( context , size , flags ) ;
/* Make a vchunk covering the new block's header */
VALGRIND_MEMPOOL_ALLOC ( set , block , ALLOC_BLOCKHDRSZ ) ;
context - > mem_allocated + = blksize ;
context - > mem_allocated + = blksize ;
block - > aset = set ;
block - > aset = set ;
@ -1104,6 +1157,10 @@ AllocSetFree(void *pointer)
# ifdef CLOBBER_FREED_MEMORY
# ifdef CLOBBER_FREED_MEMORY
wipe_mem ( block , block - > freeptr - ( ( char * ) block ) ) ;
wipe_mem ( block , block - > freeptr - ( ( char * ) block ) ) ;
# endif
# endif
/* As in AllocSetReset, free block-header vchunks explicitly */
VALGRIND_MEMPOOL_FREE ( set , block ) ;
free ( block ) ;
free ( block ) ;
}
}
else
else
@ -1184,6 +1241,7 @@ AllocSetRealloc(void *pointer, Size size, int flags)
* realloc ( ) to make the containing block bigger , or smaller , with
* realloc ( ) to make the containing block bigger , or smaller , with
* minimum space wastage .
* minimum space wastage .
*/
*/
AllocBlock newblock ;
Size chksize ;
Size chksize ;
Size blksize ;
Size blksize ;
Size oldblksize ;
Size oldblksize ;
@ -1223,14 +1281,21 @@ AllocSetRealloc(void *pointer, Size size, int flags)
blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ;
blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ;
oldblksize = block - > endptr - ( ( char * ) block ) ;
oldblksize = block - > endptr - ( ( char * ) block ) ;
block = ( AllocBlock ) realloc ( block , blksize ) ;
new block = ( AllocBlock ) realloc ( block , blksize ) ;
if ( block = = NULL )
if ( new block = = NULL )
{
{
/* Disallow access to the chunk header. */
/* Disallow access to the chunk header. */
VALGRIND_MAKE_MEM_NOACCESS ( chunk , ALLOC_CHUNKHDRSZ ) ;
VALGRIND_MAKE_MEM_NOACCESS ( chunk , ALLOC_CHUNKHDRSZ ) ;
return MemoryContextAllocationFailure ( & set - > header , size , flags ) ;
return MemoryContextAllocationFailure ( & set - > header , size , flags ) ;
}
}
/*
* Move the block - header vchunk explicitly . ( mcxt . c will take care of
* moving the vchunk for the user data . )
*/
VALGRIND_MEMPOOL_CHANGE ( set , block , newblock , ALLOC_BLOCKHDRSZ ) ;
block = newblock ;
/* updated separately, not to underflow when (oldblksize > blksize) */
/* updated separately, not to underflow when (oldblksize > blksize) */
set - > header . mem_allocated - = oldblksize ;
set - > header . mem_allocated - = oldblksize ;
set - > header . mem_allocated + = blksize ;
set - > header . mem_allocated + = blksize ;
@ -1294,7 +1359,7 @@ AllocSetRealloc(void *pointer, Size size, int flags)
/* Ensure any padding bytes are marked NOACCESS. */
/* Ensure any padding bytes are marked NOACCESS. */
VALGRIND_MAKE_MEM_NOACCESS ( ( char * ) pointer + size , chksize - size ) ;
VALGRIND_MAKE_MEM_NOACCESS ( ( char * ) pointer + size , chksize - size ) ;
/* Disallow access to the chunk header . */
/* Disallow access to the chunk header. */
VALGRIND_MAKE_MEM_NOACCESS ( chunk , ALLOC_CHUNKHDRSZ ) ;
VALGRIND_MAKE_MEM_NOACCESS ( chunk , ALLOC_CHUNKHDRSZ ) ;
return pointer ;
return pointer ;