src/backend/utils/mmgr/slab.c
static void
SlabCheck(MemoryContext context)
{
	int			i;
	SlabContext *slab = castNode(SlabContext, context);
	const char *name = slab->header.name;

	Assert(slab);
	Assert(slab->chunksPerBlock > 0);

	/* walk all the freelists */
	for (i = 0; i <= slab->chunksPerBlock; i++)
	{
		int			j,
					nfree;
		dlist_iter	iter;

		/* walk all blocks on this freelist */
		dlist_foreach(iter, &slab->freelist[i])
		{
			int			idx;
			SlabBlock  *block = dlist_container(SlabBlock, node, iter.cur);

			/*
			 * Make sure the number of free chunks (in the block header)
			 * matches position in the freelist.
			 */
			if (block->nfree != i)
				elog(WARNING, "problem in slab %s: number of free chunks %d in block %p does not match freelist %d",
					 name, block->nfree, block, i);

			/* reset the bitmap of free chunks for this block */
			memset(slab->freechunks, 0, (slab->chunksPerBlock * sizeof(bool)));
			idx = block->firstFreeChunk;

			/*
			 * Now walk through the chunks, count the free ones and also
			 * perform some additional checks for the used ones. As the chunk
			 * freelist is stored within the chunks themselves, we have to
			 * walk through the chunks and construct our own bitmap.
			 */

			nfree = 0;
			while (idx < slab->chunksPerBlock)
			{
				SlabChunk  *chunk;

				/* count the chunk as free, add it to the bitmap */
				nfree++;
				slab->freechunks[idx] = true;

				/* read index of the next free chunk */
				chunk = SlabBlockGetChunk(slab, block, idx);
				VALGRIND_MAKE_MEM_DEFINED(SlabChunkGetPointer(chunk), sizeof(int32));
				idx = *(int32 *) SlabChunkGetPointer(chunk);
			}

			for (j = 0; j < slab->chunksPerBlock; j++)
			{
				/* non-zero bit in the bitmap means chunk the chunk is used */
				if (!slab->freechunks[j])
				{
					SlabChunk  *chunk = SlabBlockGetChunk(slab, block, j);

					/* chunks have both block and slab pointers, so check both */
					if (chunk->block != block)
						elog(WARNING, "problem in slab %s: bogus block link in block %p, chunk %p",
							 name, block, chunk);

					if (chunk->slab != slab)
						elog(WARNING, "problem in slab %s: bogus slab link in block %p, chunk %p",
							 name, block, chunk);

					/* there might be sentinel (thanks to alignment) */
					if (slab->chunkSize < (slab->fullChunkSize - sizeof(SlabChunk)))
						if (!sentinel_ok(chunk, slab->chunkSize))
							elog(WARNING, "problem in slab %s: detected write past chunk end in block %p, chunk %p",
								 name, block, chunk);
				}
			}

			/*
			 * Make sure we got the expected number of free chunks (as tracked
			 * in the block header).
			 */
			if (nfree != block->nfree)
				elog(WARNING, "problem in slab %s: number of free chunks %d in block %p does not match bitmap %d",
					 name, block->nfree, block, nfree);
		}
	}

	Assert(slab->nblocks * slab->blockSize == context->mem_allocated);
}
/*
 * SlabCheck
 *		Walk through chunks and check consistency of memory.
 *
 * NOTE: report errors as WARNING, *not* ERROR or FATAL.  Otherwise you'll
 * find yourself in an infinite loop when trouble occurs, because this
 * routine will be entered again when elog cleanup tries to release memory!
 */
SlabCheck
Walk through chunks and check consistency of memory.

report errors as WARNING, *not* ERROR or FATAL.  Otherwise you'll
find yourself in an infinite loop when trouble occurs, because this
routine will be entered again when elog cleanup tries to release memory!
SlabCheck Walk through chunks and check consistency of memory . report errors as WARNING * not * ERROR or FATAL . Otherwise you ' ll find yourself in an infinite loop when trouble occurs because this routine will be entered again when elog cleanup tries to release memory!
static void
SlabCheck(MemoryContext context)
{
	int			i;
	SlabContext *slab = castNode(SlabContext, context);
	const char *name = slab->header.name;
	Assert(slab);
	Assert(slab->chunksPerBlock > 0);
	for (i = 0; i <= slab->chunksPerBlock; i++)
	{
		int			j,
					nfree;
		dlist_iter	iter;
		dlist_foreach(iter, &slab->freelist[i])
		{
			int			idx;
			SlabBlock  *block = dlist_container(SlabBlock, node, iter.cur);
			if (block->nfree != i)
				elog(WARNING, "problem in slab %s: number of free chunks %d in block %p does not match freelist %d",
					 name, block->nfree, block, i);
			memset(slab->freechunks, 0, (slab->chunksPerBlock * sizeof(bool)));
			idx = block->firstFreeChunk;
			nfree = 0;
			while (idx < slab->chunksPerBlock)
			{
				SlabChunk  *chunk;
				nfree++;
				slab->freechunks[idx] = true;
				chunk = SlabBlockGetChunk(slab, block, idx);
				VALGRIND_MAKE_MEM_DEFINED(SlabChunkGetPointer(chunk), sizeof(int32));
				idx = *(int32 *) SlabChunkGetPointer(chunk);
			}
			for (j = 0; j < slab->chunksPerBlock; j++)
			{
				if (!slab->freechunks[j])
				{
					SlabChunk  *chunk = SlabBlockGetChunk(slab, block, j);
					if (chunk->block != block)
						elog(WARNING, "problem in slab %s: bogus block link in block %p, chunk %p",
							 name, block, chunk);
					if (chunk->slab != slab)
						elog(WARNING, "problem in slab %s: bogus slab link in block %p, chunk %p",
							 name, block, chunk);
					if (slab->chunkSize < (slab->fullChunkSize - sizeof(SlabChunk)))
						if (!sentinel_ok(chunk, slab->chunkSize))
							elog(WARNING, "problem in slab %s: detected write past chunk end in block %p, chunk %p",
								 name, block, chunk);
				}
			}
			if (nfree != block->nfree)
				elog(WARNING, "problem in slab %s: number of free chunks %d in block %p does not match bitmap %d",
					 name, block->nfree, block, nfree);
		}
	}
	Assert(slab->nblocks * slab->blockSize == context->mem_allocated);
}
static void SlabCheck ( MemoryContext context ) { int i ; SlabContext * slab = castNode ( SlabContext , context ) ; const char * name = slab -> header . name ; Assert ( slab ) ; Assert ( slab -> chunksPerBlock > 0 ) ; for ( i = 0 ; i <= slab -> chunksPerBlock ; i ++ ) { int j , nfree ; dlist_iter iter ; dlist_foreach ( iter , & slab -> freelist [ i ] ) { int idx ; SlabBlock * block = dlist_container ( SlabBlock , node , iter . cur ) ; if ( block -> nfree != i ) elog ( WARNING , " " , name , block -> nfree , block , i ) ; memset ( slab -> freechunks , 0 , ( slab -> chunksPerBlock * sizeof ( bool ) ) ) ; idx = block -> firstFreeChunk ; nfree = 0 ; while ( idx < slab -> chunksPerBlock ) { SlabChunk * chunk ; nfree ++ ; slab -> freechunks [ idx ] = true ; chunk = SlabBlockGetChunk ( slab , block , idx ) ; VALGRIND_MAKE_MEM_DEFINED ( SlabChunkGetPointer ( chunk ) , sizeof ( int32 ) ) ; idx = * ( int32 * ) SlabChunkGetPointer ( chunk ) ; } for ( j = 0 ; j < slab -> chunksPerBlock ; j ++ ) { if ( ! slab -> freechunks [ j ] ) { SlabChunk * chunk = SlabBlockGetChunk ( slab , block , j ) ; if ( chunk -> block != block ) elog ( WARNING , " " , name , block , chunk ) ; if ( chunk -> slab != slab ) elog ( WARNING , " " , name , block , chunk ) ; if ( slab -> chunkSize < ( slab -> fullChunkSize - sizeof ( SlabChunk ) ) ) if ( ! sentinel_ok ( chunk , slab -> chunkSize ) ) elog ( WARNING , " " , name , block , chunk ) ; } } if ( nfree != block -> nfree ) elog ( WARNING , " " , name , block -> nfree , block , nfree ) ; } } Assert ( slab -> nblocks * slab -> blockSize == context -> mem_allocated ) ; }
SlabCheck
              Walk through chunks and check consistency of memory.
SlabCheck Walk through chunks and check consistency of memory .
/* walk all the freelists */ /* walk all blocks on this freelist */ /*
			 * Make sure the number of free chunks (in the block header)
			 * matches position in the freelist.
			 */ /* reset the bitmap of free chunks for this block */ /*
			 * Now walk through the chunks, count the free ones and also
			 * perform some additional checks for the used ones. As the chunk
			 * freelist is stored within the chunks themselves, we have to
			 * walk through the chunks and construct our own bitmap.
			 */ /* count the chunk as free, add it to the bitmap */ /* read index of the next free chunk */ /* non-zero bit in the bitmap means chunk the chunk is used */ /* chunks have both block and slab pointers, so check both */ /* there might be sentinel (thanks to alignment) */ /*
			 * Make sure we got the expected number of free chunks (as tracked
			 * in the block header).
			 */