PostgreSQL Source Code git master
slab.c File Reference
#include "postgres.h"
#include "lib/ilist.h"
#include "utils/memdebug.h"
#include "utils/memutils.h"
#include "utils/memutils_internal.h"
#include "utils/memutils_memorychunk.h"
Include dependency graph for slab.c:

Go to the source code of this file.

Data Structures

struct  SlabContext
 
struct  SlabBlock
 

Macros

#define Slab_BLOCKHDRSZ   MAXALIGN(sizeof(SlabBlock))
 
#define Slab_CONTEXT_HDRSZ(chunksPerBlock)   sizeof(SlabContext)
 
#define SLAB_BLOCKLIST_COUNT   3
 
#define SLAB_MAXIMUM_EMPTY_BLOCKS   10
 
#define Slab_CHUNKHDRSZ   sizeof(MemoryChunk)
 
#define SlabChunkGetPointer(chk)    ((void *) (((char *) (chk)) + sizeof(MemoryChunk)))
 
#define SlabBlockGetChunk(slab, block, n)
 
#define SlabIsValid(set)   (PointerIsValid(set) && IsA(set, SlabContext))
 
#define SlabBlockIsValid(block)    (PointerIsValid(block) && SlabIsValid((block)->slab))
 

Typedefs

typedef struct SlabContext SlabContext
 
typedef struct SlabBlock SlabBlock
 

Functions

static int32 SlabBlocklistIndex (SlabContext *slab, int nfree)
 
static int32 SlabFindNextBlockListIndex (SlabContext *slab)
 
static MemoryChunkSlabGetNextFreeChunk (SlabContext *slab, SlabBlock *block)
 
MemoryContext SlabContextCreate (MemoryContext parent, const char *name, Size blockSize, Size chunkSize)
 
void SlabReset (MemoryContext context)
 
void SlabDelete (MemoryContext context)
 
static void * SlabAllocSetupNewChunk (MemoryContext context, SlabBlock *block, MemoryChunk *chunk, Size size)
 
static pg_noinline void * SlabAllocFromNewBlock (MemoryContext context, Size size, int flags)
 
static pg_noinline void pg_attribute_noreturn () SlabAllocInvalidSize(MemoryContext context
 
 elog (ERROR, "unexpected alloc chunk size %zu (expected %u)", size, slab->chunkSize)
 
void * SlabAlloc (MemoryContext context, Size size, int flags)
 
void SlabFree (void *pointer)
 
void * SlabRealloc (void *pointer, Size size, int flags)
 
MemoryContext SlabGetChunkContext (void *pointer)
 
Size SlabGetChunkSpace (void *pointer)
 
bool SlabIsEmpty (MemoryContext context)
 
void SlabStats (MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
 

Variables

static pg_noinline void Size size
 

Macro Definition Documentation

◆ Slab_BLOCKHDRSZ

#define Slab_BLOCKHDRSZ   MAXALIGN(sizeof(SlabBlock))

Definition at line 77 of file slab.c.

◆ SLAB_BLOCKLIST_COUNT

#define SLAB_BLOCKLIST_COUNT   3

Definition at line 95 of file slab.c.

◆ Slab_CHUNKHDRSZ

#define Slab_CHUNKHDRSZ   sizeof(MemoryChunk)

Definition at line 157 of file slab.c.

◆ Slab_CONTEXT_HDRSZ

#define Slab_CONTEXT_HDRSZ (   chunksPerBlock)    sizeof(SlabContext)

Definition at line 88 of file slab.c.

◆ SLAB_MAXIMUM_EMPTY_BLOCKS

#define SLAB_MAXIMUM_EMPTY_BLOCKS   10

Definition at line 98 of file slab.c.

◆ SlabBlockGetChunk

#define SlabBlockGetChunk (   slab,
  block,
 
)
Value:
((MemoryChunk *) ((char *) (block) + Slab_BLOCKHDRSZ \
+ ((n) * (slab)->fullChunkSize)))
#define Slab_BLOCKHDRSZ
Definition: slab.c:77

Definition at line 165 of file slab.c.

◆ SlabBlockIsValid

#define SlabBlockIsValid (   block)     (PointerIsValid(block) && SlabIsValid((block)->slab))

Definition at line 202 of file slab.c.

◆ SlabChunkGetPointer

#define SlabChunkGetPointer (   chk)     ((void *) (((char *) (chk)) + sizeof(MemoryChunk)))

Definition at line 158 of file slab.c.

◆ SlabIsValid

#define SlabIsValid (   set)    (PointerIsValid(set) && IsA(set, SlabContext))

Definition at line 196 of file slab.c.

Typedef Documentation

◆ SlabBlock

typedef struct SlabBlock SlabBlock

◆ SlabContext

typedef struct SlabContext SlabContext

Function Documentation

◆ elog()

elog ( ERROR  ,
"unexpected alloc chunk size %zu (expected %u)"  ,
size  ,
slab->  chunkSize 
)

◆ pg_attribute_noreturn()

static pg_noinline void pg_attribute_noreturn ( )
static

◆ SlabAlloc()

void * SlabAlloc ( MemoryContext  context,
Size  size,
int  flags 
)

Definition at line 630 of file slab.c.

631{
632 SlabContext *slab = (SlabContext *) context;
633 SlabBlock *block;
635
636 Assert(SlabIsValid(slab));
637
638 /* sanity check that this is pointing to a valid blocklist */
639 Assert(slab->curBlocklistIndex >= 0);
641
642 /*
643 * Make sure we only allow correct request size. This doubles as the
644 * MemoryContextCheckSize check.
645 */
646 if (unlikely(size != slab->chunkSize))
647 SlabAllocInvalidSize(context, size);
648
649 if (unlikely(slab->curBlocklistIndex == 0))
650 {
651 /*
652 * Handle the case when there are no partially filled blocks
653 * available. This happens either when the last allocation took the
654 * last chunk in the block, or when SlabFree() free'd the final block.
655 */
656 return SlabAllocFromNewBlock(context, size, flags);
657 }
658 else
659 {
660 dlist_head *blocklist = &slab->blocklist[slab->curBlocklistIndex];
661 int new_blocklist_idx;
662
663 Assert(!dlist_is_empty(blocklist));
664
665 /* grab the block from the blocklist */
666 block = dlist_head_element(SlabBlock, node, blocklist);
667
668 /* make sure we actually got a valid block, with matching nfree */
669 Assert(block != NULL);
670 Assert(slab->curBlocklistIndex == SlabBlocklistIndex(slab, block->nfree));
671 Assert(block->nfree > 0);
672
673 /* fetch the next chunk from this block */
674 chunk = SlabGetNextFreeChunk(slab, block);
675
676 /* get the new blocklist index based on the new free chunk count */
677 new_blocklist_idx = SlabBlocklistIndex(slab, block->nfree);
678
679 /*
680 * Handle the case where the blocklist index changes. This also deals
681 * with blocks becoming full as only full blocks go at index 0.
682 */
683 if (unlikely(slab->curBlocklistIndex != new_blocklist_idx))
684 {
685 dlist_delete_from(blocklist, &block->node);
686 dlist_push_head(&slab->blocklist[new_blocklist_idx], &block->node);
687
688 if (dlist_is_empty(blocklist))
690 }
691 }
692
693 return SlabAllocSetupNewChunk(context, block, chunk, size);
694}
#define Assert(condition)
Definition: c.h:815
#define unlikely(x)
Definition: c.h:333
uint64 chunk
static void dlist_delete_from(dlist_head *head, dlist_node *node)
Definition: ilist.h:429
#define dlist_head_element(type, membername, lhead)
Definition: ilist.h:603
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:347
static bool dlist_is_empty(const dlist_head *head)
Definition: ilist.h:336
static pg_noinline void * SlabAllocFromNewBlock(MemoryContext context, Size size, int flags)
Definition: slab.c:539
static pg_noinline void Size size
Definition: slab.c:607
#define SlabIsValid(set)
Definition: slab.c:196
static MemoryChunk * SlabGetNextFreeChunk(SlabContext *slab, SlabBlock *block)
Definition: slab.c:271
static int32 SlabBlocklistIndex(SlabContext *slab, int nfree)
Definition: slab.c:211
static void * SlabAllocSetupNewChunk(MemoryContext context, SlabBlock *block, MemoryChunk *chunk, Size size)
Definition: slab.c:498
static int32 SlabFindNextBlockListIndex(SlabContext *slab)
Definition: slab.c:251
int32 nfree
Definition: slab.c:149
dlist_node node
Definition: slab.c:153
dlist_head blocklist[SLAB_BLOCKLIST_COUNT]
Definition: slab.c:129
int32 chunksPerBlock
Definition: slab.c:110
int32 curBlocklistIndex
Definition: slab.c:111
uint32 chunkSize
Definition: slab.c:107

References Assert, SlabContext::blocklist, chunk, SlabContext::chunkSize, SlabContext::chunksPerBlock, SlabContext::curBlocklistIndex, dlist_delete_from(), dlist_head_element, dlist_is_empty(), dlist_push_head(), SlabBlock::nfree, SlabBlock::node, size, SlabAllocFromNewBlock(), SlabAllocSetupNewChunk(), SlabBlocklistIndex(), SlabFindNextBlockListIndex(), SlabGetNextFreeChunk(), SlabIsValid, and unlikely.

◆ SlabAllocFromNewBlock()

static pg_noinline void * SlabAllocFromNewBlock ( MemoryContext  context,
Size  size,
int  flags 
)
static

Definition at line 539 of file slab.c.

540{
541 SlabContext *slab = (SlabContext *) context;
542 SlabBlock *block;
544 dlist_head *blocklist;
545 int blocklist_idx;
546
547 /* to save allocating a new one, first check the empty blocks list */
548 if (dclist_count(&slab->emptyblocks) > 0)
549 {
551
552 block = dlist_container(SlabBlock, node, node);
553
554 /*
555 * SlabFree() should have left this block in a valid state with all
556 * chunks free. Ensure that's the case.
557 */
558 Assert(block->nfree == slab->chunksPerBlock);
559
560 /* fetch the next chunk from this block */
561 chunk = SlabGetNextFreeChunk(slab, block);
562 }
563 else
564 {
565 block = (SlabBlock *) malloc(slab->blockSize);
566
567 if (unlikely(block == NULL))
568 return MemoryContextAllocationFailure(context, size, flags);
569
570 block->slab = slab;
571 context->mem_allocated += slab->blockSize;
572
573 /* use the first chunk in the new block */
574 chunk = SlabBlockGetChunk(slab, block, 0);
575
576 block->nfree = slab->chunksPerBlock - 1;
577 block->unused = SlabBlockGetChunk(slab, block, 1);
578 block->freehead = NULL;
579 block->nunused = slab->chunksPerBlock - 1;
580 }
581
582 /* find the blocklist element for storing blocks with 1 used chunk */
583 blocklist_idx = SlabBlocklistIndex(slab, block->nfree);
584 blocklist = &slab->blocklist[blocklist_idx];
585
586 /* this better be empty. We just added a block thinking it was */
587 Assert(dlist_is_empty(blocklist));
588
589 dlist_push_head(blocklist, &block->node);
590
591 slab->curBlocklistIndex = blocklist_idx;
592
593 return SlabAllocSetupNewChunk(context, block, chunk, size);
594}
#define malloc(a)
Definition: header.h:50
static uint32 dclist_count(const dclist_head *head)
Definition: ilist.h:932
static dlist_node * dclist_pop_head_node(dclist_head *head)
Definition: ilist.h:789
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
void * MemoryContextAllocationFailure(MemoryContext context, Size size, int flags)
Definition: mcxt.c:1147
#define SlabBlockGetChunk(slab, block, n)
Definition: slab.c:165
MemoryChunk * freehead
Definition: slab.c:151
MemoryChunk * unused
Definition: slab.c:152
SlabContext * slab
Definition: slab.c:148
int32 nunused
Definition: slab.c:150
uint32 blockSize
Definition: slab.c:109
dclist_head emptyblocks
Definition: slab.c:120

References Assert, SlabContext::blocklist, SlabContext::blockSize, chunk, SlabContext::chunksPerBlock, SlabContext::curBlocklistIndex, dclist_count(), dclist_pop_head_node(), dlist_container, dlist_is_empty(), dlist_push_head(), SlabContext::emptyblocks, SlabBlock::freehead, malloc, MemoryContextData::mem_allocated, MemoryContextAllocationFailure(), SlabBlock::nfree, SlabBlock::node, SlabBlock::nunused, size, SlabBlock::slab, SlabAllocSetupNewChunk(), SlabBlockGetChunk, SlabBlocklistIndex(), SlabGetNextFreeChunk(), unlikely, and SlabBlock::unused.

Referenced by SlabAlloc().

◆ SlabAllocSetupNewChunk()

static void * SlabAllocSetupNewChunk ( MemoryContext  context,
SlabBlock block,
MemoryChunk chunk,
Size  size 
)
inlinestatic

Definition at line 498 of file slab.c.

500{
501 SlabContext *slab = (SlabContext *) context;
502
503 /*
504 * Check that the chunk pointer is actually somewhere on the block and is
505 * aligned as expected.
506 */
507 Assert(chunk >= SlabBlockGetChunk(slab, block, 0));
508 Assert(chunk <= SlabBlockGetChunk(slab, block, slab->chunksPerBlock - 1));
509 Assert(SlabChunkMod(slab, block, chunk) == 0);
510
511 /* Prepare to initialize the chunk header. */
513
515
516#ifdef MEMORY_CONTEXT_CHECKING
517 /* slab mark to catch clobber of "unused" space */
519 set_sentinel(MemoryChunkGetPointer(chunk), size);
521 slab->chunkSize,
522 slab->fullChunkSize -
523 (slab->chunkSize + Slab_CHUNKHDRSZ));
524#endif
525
526#ifdef RANDOMIZE_ALLOCATED_MEMORY
527 /* fill the allocated space with junk */
528 randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
529#endif
530
531 /* Disallow access to the chunk header. */
533
535}
#define MAXALIGN(LEN)
Definition: c.h:768
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
Definition: memdebug.h:27
#define VALGRIND_MAKE_MEM_UNDEFINED(addr, size)
Definition: memdebug.h:28
@ MCTX_SLAB_ID
#define MemoryChunkGetPointer(c)
static void MemoryChunkSetHdrMask(MemoryChunk *chunk, void *block, Size value, MemoryContextMethodID methodid)
#define Slab_CHUNKHDRSZ
Definition: slab.c:157
uint32 fullChunkSize
Definition: slab.c:108

References Assert, chunk, SlabContext::chunkSize, SlabContext::chunksPerBlock, SlabContext::fullChunkSize, MAXALIGN, MCTX_SLAB_ID, MemoryChunkGetPointer, MemoryChunkSetHdrMask(), size, Slab_CHUNKHDRSZ, SlabBlockGetChunk, VALGRIND_MAKE_MEM_NOACCESS, and VALGRIND_MAKE_MEM_UNDEFINED.

Referenced by SlabAlloc(), and SlabAllocFromNewBlock().

◆ SlabBlocklistIndex()

static int32 SlabBlocklistIndex ( SlabContext slab,
int  nfree 
)
inlinestatic

Definition at line 211 of file slab.c.

212{
213 int32 index;
214 int32 blocklist_shift = slab->blocklist_shift;
215
216 Assert(nfree >= 0 && nfree <= slab->chunksPerBlock);
217
218 /*
219 * Determine the blocklist index based on the number of free chunks. We
220 * must ensure that 0 free chunks is dedicated to index 0. Everything
221 * else must be >= 1 and < SLAB_BLOCKLIST_COUNT.
222 *
223 * To make this as efficient as possible, we exploit some two's complement
224 * arithmetic where we reverse the sign before bit shifting. This results
225 * in an nfree of 0 using index 0 and anything non-zero staying non-zero.
226 * This is exploiting 0 and -0 being the same in two's complement. When
227 * we're done, we just need to flip the sign back over again for a
228 * positive index.
229 */
230 index = -((-nfree) >> blocklist_shift);
231
232 if (nfree == 0)
233 Assert(index == 0);
234 else
236
237 return index;
238}
int32_t int32
Definition: c.h:484
#define SLAB_BLOCKLIST_COUNT
Definition: slab.c:95
int32 blocklist_shift
Definition: slab.c:118
Definition: type.h:96

References Assert, SlabContext::blocklist_shift, and SLAB_BLOCKLIST_COUNT.

Referenced by SlabAlloc(), SlabAllocFromNewBlock(), and SlabFree().

◆ SlabContextCreate()

MemoryContext SlabContextCreate ( MemoryContext  parent,
const char *  name,
Size  blockSize,
Size  chunkSize 
)

Definition at line 322 of file slab.c.

326{
327 int chunksPerBlock;
328 Size fullChunkSize;
329 SlabContext *slab;
330 int i;
331
332 /* ensure MemoryChunk's size is properly maxaligned */
334 "sizeof(MemoryChunk) is not maxaligned");
336
337 /*
338 * Ensure there's enough space to store the pointer to the next free chunk
339 * in the memory of the (otherwise) unused allocation.
340 */
341 if (chunkSize < sizeof(MemoryChunk *))
342 chunkSize = sizeof(MemoryChunk *);
343
344 /* length of the maxaligned chunk including the chunk header */
345#ifdef MEMORY_CONTEXT_CHECKING
346 /* ensure there's always space for the sentinel byte */
347 fullChunkSize = Slab_CHUNKHDRSZ + MAXALIGN(chunkSize + 1);
348#else
349 fullChunkSize = Slab_CHUNKHDRSZ + MAXALIGN(chunkSize);
350#endif
351
352 Assert(fullChunkSize <= MEMORYCHUNK_MAX_VALUE);
353
354 /* compute the number of chunks that will fit on each block */
355 chunksPerBlock = (blockSize - Slab_BLOCKHDRSZ) / fullChunkSize;
356
357 /* Make sure the block can store at least one chunk. */
358 if (chunksPerBlock == 0)
359 elog(ERROR, "block size %zu for slab is too small for %zu-byte chunks",
360 blockSize, chunkSize);
361
362
363
364 slab = (SlabContext *) malloc(Slab_CONTEXT_HDRSZ(chunksPerBlock));
365 if (slab == NULL)
366 {
369 (errcode(ERRCODE_OUT_OF_MEMORY),
370 errmsg("out of memory"),
371 errdetail("Failed while creating memory context \"%s\".",
372 name)));
373 }
374
375 /*
376 * Avoid writing code that can fail between here and MemoryContextCreate;
377 * we'd leak the header if we ereport in this stretch.
378 */
379
380 /* Fill in SlabContext-specific header fields */
381 slab->chunkSize = (uint32) chunkSize;
382 slab->fullChunkSize = (uint32) fullChunkSize;
383 slab->blockSize = (uint32) blockSize;
384 slab->chunksPerBlock = chunksPerBlock;
385 slab->curBlocklistIndex = 0;
386
387 /*
388 * Compute a shift that guarantees that shifting chunksPerBlock with it is
389 * < SLAB_BLOCKLIST_COUNT - 1. The reason that we subtract 1 from
390 * SLAB_BLOCKLIST_COUNT in this calculation is that we reserve the 0th
391 * blocklist element for blocks which have no free chunks.
392 *
393 * We calculate the number of bits to shift by rather than a divisor to
394 * divide by as performing division each time we need to find the
395 * blocklist index would be much slower.
396 */
397 slab->blocklist_shift = 0;
398 while ((slab->chunksPerBlock >> slab->blocklist_shift) >= (SLAB_BLOCKLIST_COUNT - 1))
399 slab->blocklist_shift++;
400
401 /* initialize the list to store empty blocks to be reused */
402 dclist_init(&slab->emptyblocks);
403
404 /* initialize each blocklist slot */
405 for (i = 0; i < SLAB_BLOCKLIST_COUNT; i++)
406 dlist_init(&slab->blocklist[i]);
407
408#ifdef MEMORY_CONTEXT_CHECKING
409 /* set the isChunkFree pointer right after the end of the context */
410 slab->isChunkFree = (bool *) ((char *) slab + sizeof(SlabContext));
411#endif
412
413 /* Finally, do the type-independent part of context creation */
415 T_SlabContext,
417 parent,
418 name);
419
420 return (MemoryContext) slab;
421}
uint32_t uint32
Definition: c.h:488
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:893
size_t Size
Definition: c.h:562
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
static void dlist_init(dlist_head *head)
Definition: ilist.h:314
static void dclist_init(dclist_head *head)
Definition: ilist.h:671
int i
Definition: isn.c:72
void MemoryContextCreate(MemoryContext node, NodeTag tag, MemoryContextMethodID method_id, MemoryContext parent, const char *name)
Definition: mcxt.c:1100
MemoryContext TopMemoryContext
Definition: mcxt.c:149
void MemoryContextStats(MemoryContext context)
Definition: mcxt.c:814
#define MEMORYCHUNK_MAX_BLOCKOFFSET
#define MEMORYCHUNK_MAX_VALUE
elog(ERROR, "unexpected alloc chunk size %zu (expected %u)", size, slab->chunkSize)
struct SlabContext SlabContext
#define Slab_CONTEXT_HDRSZ(chunksPerBlock)
Definition: slab.c:88
const char * name

References Assert, SlabContext::blocklist, SlabContext::blocklist_shift, SlabContext::blockSize, SlabContext::chunkSize, SlabContext::chunksPerBlock, SlabContext::curBlocklistIndex, dclist_init(), dlist_init(), elog(), SlabContext::emptyblocks, ereport, errcode(), errdetail(), errmsg(), ERROR, SlabContext::fullChunkSize, i, malloc, MAXALIGN, MCTX_SLAB_ID, MEMORYCHUNK_MAX_BLOCKOFFSET, MEMORYCHUNK_MAX_VALUE, MemoryContextCreate(), MemoryContextStats(), name, Slab_BLOCKHDRSZ, SLAB_BLOCKLIST_COUNT, Slab_CHUNKHDRSZ, Slab_CONTEXT_HDRSZ, StaticAssertDecl, and TopMemoryContext.

Referenced by for(), ReorderBufferAllocate(), and test_random().

◆ SlabDelete()

void SlabDelete ( MemoryContext  context)

Definition at line 485 of file slab.c.

486{
487 /* Reset to release all the SlabBlocks */
488 SlabReset(context);
489 /* And free the context header */
490 free(context);
491}
#define free(a)
Definition: header.h:65
void SlabReset(MemoryContext context)
Definition: slab.c:431

References free, and SlabReset().

◆ SlabFindNextBlockListIndex()

static int32 SlabFindNextBlockListIndex ( SlabContext slab)
static

Definition at line 251 of file slab.c.

252{
253 /* start at 1 as blocklist[0] is for full blocks. */
254 for (int i = 1; i < SLAB_BLOCKLIST_COUNT; i++)
255 {
256 /* return the first found non-empty index */
257 if (!dlist_is_empty(&slab->blocklist[i]))
258 return i;
259 }
260
261 /* no blocks with free space */
262 return 0;
263}

References SlabContext::blocklist, dlist_is_empty(), i, and SLAB_BLOCKLIST_COUNT.

Referenced by SlabAlloc(), and SlabFree().

◆ SlabFree()

void SlabFree ( void *  pointer)

Definition at line 701 of file slab.c.

702{
704 SlabBlock *block;
705 SlabContext *slab;
706 int curBlocklistIdx;
707 int newBlocklistIdx;
708
709 /* Allow access to the chunk header. */
711
712 block = MemoryChunkGetBlock(chunk);
713
714 /*
715 * For speed reasons we just Assert that the referenced block is good.
716 * Future field experience may show that this Assert had better become a
717 * regular runtime test-and-elog check.
718 */
719 Assert(SlabBlockIsValid(block));
720 slab = block->slab;
721
722#ifdef MEMORY_CONTEXT_CHECKING
723 /* Test for someone scribbling on unused space in chunk */
725 if (!sentinel_ok(pointer, slab->chunkSize))
726 elog(WARNING, "detected write past chunk end in %s %p",
727 slab->header.name, chunk);
728#endif
729
730 /* push this chunk onto the head of the block's free list */
731 *(MemoryChunk **) pointer = block->freehead;
732 block->freehead = chunk;
733
734 block->nfree++;
735
736 Assert(block->nfree > 0);
737 Assert(block->nfree <= slab->chunksPerBlock);
738
739#ifdef CLOBBER_FREED_MEMORY
740 /* don't wipe the free list MemoryChunk pointer stored in the chunk */
741 wipe_mem((char *) pointer + sizeof(MemoryChunk *),
742 slab->chunkSize - sizeof(MemoryChunk *));
743#endif
744
745 curBlocklistIdx = SlabBlocklistIndex(slab, block->nfree - 1);
746 newBlocklistIdx = SlabBlocklistIndex(slab, block->nfree);
747
748 /*
749 * Check if the block needs to be moved to another element on the
750 * blocklist based on it now having 1 more free chunk.
751 */
752 if (unlikely(curBlocklistIdx != newBlocklistIdx))
753 {
754 /* do the move */
755 dlist_delete_from(&slab->blocklist[curBlocklistIdx], &block->node);
756 dlist_push_head(&slab->blocklist[newBlocklistIdx], &block->node);
757
758 /*
759 * The blocklist[curBlocklistIdx] may now be empty or we may now be
760 * able to use a lower-element blocklist. We'll need to redetermine
761 * what the slab->curBlocklistIndex is if the current blocklist was
762 * changed or if a lower element one was changed. We must ensure we
763 * use the list with the fullest block(s).
764 */
765 if (slab->curBlocklistIndex >= curBlocklistIdx)
766 {
768
769 /*
770 * We know there must be a block with at least 1 unused chunk as
771 * we just pfree'd one. Ensure curBlocklistIndex reflects this.
772 */
773 Assert(slab->curBlocklistIndex > 0);
774 }
775 }
776
777 /* Handle when a block becomes completely empty */
778 if (unlikely(block->nfree == slab->chunksPerBlock))
779 {
780 /* remove the block */
781 dlist_delete_from(&slab->blocklist[newBlocklistIdx], &block->node);
782
783 /*
784 * To avoid thrashing malloc/free, we keep a list of empty blocks that
785 * we can reuse again instead of having to malloc a new one.
786 */
788 dclist_push_head(&slab->emptyblocks, &block->node);
789 else
790 {
791 /*
792 * When we have enough empty blocks stored already, we actually
793 * free the block.
794 */
795#ifdef CLOBBER_FREED_MEMORY
796 wipe_mem(block, slab->blockSize);
797#endif
798 free(block);
799 slab->header.mem_allocated -= slab->blockSize;
800 }
801
802 /*
803 * Check if we need to reset the blocklist index. This is required
804 * when the blocklist this block is on has become completely empty.
805 */
806 if (slab->curBlocklistIndex == newBlocklistIdx &&
807 dlist_is_empty(&slab->blocklist[newBlocklistIdx]))
809 }
810}
#define WARNING
Definition: elog.h:36
static void dclist_push_head(dclist_head *head, dlist_node *node)
Definition: ilist.h:693
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
static void * MemoryChunkGetBlock(MemoryChunk *chunk)
#define PointerGetMemoryChunk(p)
#define SlabBlockIsValid(block)
Definition: slab.c:202
#define SLAB_MAXIMUM_EMPTY_BLOCKS
Definition: slab.c:98
const char * name
Definition: memnodes.h:131
MemoryContextData header
Definition: slab.c:105

References Assert, SlabContext::blocklist, SlabContext::blockSize, chunk, SlabContext::chunkSize, SlabContext::chunksPerBlock, SlabContext::curBlocklistIndex, dclist_count(), dclist_push_head(), dlist_delete_from(), dlist_is_empty(), dlist_push_head(), elog(), SlabContext::emptyblocks, free, SlabBlock::freehead, SlabContext::fullChunkSize, SlabContext::header, MemoryContextData::mem_allocated, MemoryChunkGetBlock(), MemoryContextData::name, SlabBlock::nfree, SlabBlock::node, PointerGetMemoryChunk, SlabBlock::slab, Slab_CHUNKHDRSZ, SLAB_MAXIMUM_EMPTY_BLOCKS, SlabBlockIsValid, SlabBlocklistIndex(), SlabFindNextBlockListIndex(), unlikely, VALGRIND_MAKE_MEM_DEFINED, and WARNING.

◆ SlabGetChunkContext()

MemoryContext SlabGetChunkContext ( void *  pointer)

Definition at line 863 of file slab.c.

864{
866 SlabBlock *block;
867
868 /* Allow access to the chunk header. */
870
871 block = MemoryChunkGetBlock(chunk);
872
873 /* Disallow access to the chunk header. */
875
876 Assert(SlabBlockIsValid(block));
877
878 return &block->slab->header;
879}

References Assert, chunk, SlabContext::header, MemoryChunkGetBlock(), PointerGetMemoryChunk, SlabBlock::slab, Slab_CHUNKHDRSZ, SlabBlockIsValid, VALGRIND_MAKE_MEM_DEFINED, and VALGRIND_MAKE_MEM_NOACCESS.

◆ SlabGetChunkSpace()

Size SlabGetChunkSpace ( void *  pointer)

Definition at line 887 of file slab.c.

888{
890 SlabBlock *block;
891 SlabContext *slab;
892
893 /* Allow access to the chunk header. */
895
896 block = MemoryChunkGetBlock(chunk);
897
898 /* Disallow access to the chunk header. */
900
901 Assert(SlabBlockIsValid(block));
902 slab = block->slab;
903
904 return slab->fullChunkSize;
905}

References Assert, chunk, SlabContext::fullChunkSize, MemoryChunkGetBlock(), PointerGetMemoryChunk, SlabBlock::slab, Slab_CHUNKHDRSZ, SlabBlockIsValid, VALGRIND_MAKE_MEM_DEFINED, and VALGRIND_MAKE_MEM_NOACCESS.

◆ SlabGetNextFreeChunk()

static MemoryChunk * SlabGetNextFreeChunk ( SlabContext slab,
SlabBlock block 
)
inlinestatic

Definition at line 271 of file slab.c.

272{
274
275 Assert(block->nfree > 0);
276
277 if (block->freehead != NULL)
278 {
279 chunk = block->freehead;
280
281 /*
282 * Pop the chunk from the linked list of free chunks. The pointer to
283 * the next free chunk is stored in the chunk itself.
284 */
287
288 /* check nothing stomped on the free chunk's memory */
289 Assert(block->freehead == NULL ||
290 (block->freehead >= SlabBlockGetChunk(slab, block, 0) &&
291 block->freehead <= SlabBlockGetChunk(slab, block, slab->chunksPerBlock - 1) &&
292 SlabChunkMod(slab, block, block->freehead) == 0));
293 }
294 else
295 {
296 Assert(block->nunused > 0);
297
298 chunk = block->unused;
299 block->unused = (MemoryChunk *) (((char *) block->unused) + slab->fullChunkSize);
300 block->nunused--;
301 }
302
303 block->nfree--;
304
305 return chunk;
306}
#define SlabChunkGetPointer(chk)
Definition: slab.c:158

References Assert, chunk, SlabContext::chunksPerBlock, SlabBlock::freehead, SlabContext::fullChunkSize, SlabBlock::nfree, SlabBlock::nunused, SlabBlockGetChunk, SlabChunkGetPointer, SlabBlock::unused, and VALGRIND_MAKE_MEM_DEFINED.

Referenced by SlabAlloc(), and SlabAllocFromNewBlock().

◆ SlabIsEmpty()

bool SlabIsEmpty ( MemoryContext  context)

Definition at line 912 of file slab.c.

913{
914 Assert(SlabIsValid((SlabContext *) context));
915
916 return (context->mem_allocated == 0);
917}

References Assert, MemoryContextData::mem_allocated, and SlabIsValid.

◆ SlabRealloc()

void * SlabRealloc ( void *  pointer,
Size  size,
int  flags 
)

Definition at line 826 of file slab.c.

827{
829 SlabBlock *block;
830 SlabContext *slab;
831
832 /* Allow access to the chunk header. */
834
835 block = MemoryChunkGetBlock(chunk);
836
837 /* Disallow access to the chunk header. */
839
840 /*
841 * Try to verify that we have a sane block pointer: the block header
842 * should reference a slab context. (We use a test-and-elog, not just
843 * Assert, because it seems highly likely that we're here in error in the
844 * first place.)
845 */
846 if (!SlabBlockIsValid(block))
847 elog(ERROR, "could not find block containing chunk %p", chunk);
848 slab = block->slab;
849
850 /* can't do actual realloc with slab, but let's try to be gentle */
851 if (size == slab->chunkSize)
852 return pointer;
853
854 elog(ERROR, "slab allocator does not support realloc()");
855 return NULL; /* keep compiler quiet */
856}

References chunk, SlabContext::chunkSize, elog(), ERROR, MemoryChunkGetBlock(), PointerGetMemoryChunk, size, SlabBlock::slab, Slab_CHUNKHDRSZ, SlabBlockIsValid, VALGRIND_MAKE_MEM_DEFINED, and VALGRIND_MAKE_MEM_NOACCESS.

◆ SlabReset()

void SlabReset ( MemoryContext  context)

Definition at line 431 of file slab.c.

432{
433 SlabContext *slab = (SlabContext *) context;
434 dlist_mutable_iter miter;
435 int i;
436
437 Assert(SlabIsValid(slab));
438
439#ifdef MEMORY_CONTEXT_CHECKING
440 /* Check for corruption and leaks before freeing */
441 SlabCheck(context);
442#endif
443
444 /* release any retained empty blocks */
446 {
447 SlabBlock *block = dlist_container(SlabBlock, node, miter.cur);
448
449 dclist_delete_from(&slab->emptyblocks, miter.cur);
450
451#ifdef CLOBBER_FREED_MEMORY
452 wipe_mem(block, slab->blockSize);
453#endif
454 free(block);
455 context->mem_allocated -= slab->blockSize;
456 }
457
458 /* walk over blocklist and free the blocks */
459 for (i = 0; i < SLAB_BLOCKLIST_COUNT; i++)
460 {
461 dlist_foreach_modify(miter, &slab->blocklist[i])
462 {
463 SlabBlock *block = dlist_container(SlabBlock, node, miter.cur);
464
465 dlist_delete(miter.cur);
466
467#ifdef CLOBBER_FREED_MEMORY
468 wipe_mem(block, slab->blockSize);
469#endif
470 free(block);
471 context->mem_allocated -= slab->blockSize;
472 }
473 }
474
475 slab->curBlocklistIndex = 0;
476
477 Assert(context->mem_allocated == 0);
478}
static void dlist_delete(dlist_node *node)
Definition: ilist.h:405
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:640
static void dclist_delete_from(dclist_head *head, dlist_node *node)
Definition: ilist.h:763
#define dclist_foreach_modify(iter, lhead)
Definition: ilist.h:973
dlist_node * cur
Definition: ilist.h:200

References Assert, SlabContext::blocklist, SlabContext::blockSize, dlist_mutable_iter::cur, SlabContext::curBlocklistIndex, dclist_delete_from(), dclist_foreach_modify, dlist_container, dlist_delete(), dlist_foreach_modify, SlabContext::emptyblocks, free, i, MemoryContextData::mem_allocated, SLAB_BLOCKLIST_COUNT, and SlabIsValid.

Referenced by SlabDelete().

◆ SlabStats()

void SlabStats ( MemoryContext  context,
MemoryStatsPrintFunc  printfunc,
void *  passthru,
MemoryContextCounters totals,
bool  print_to_stderr 
)

Definition at line 929 of file slab.c.

933{
934 SlabContext *slab = (SlabContext *) context;
935 Size nblocks = 0;
936 Size freechunks = 0;
937 Size totalspace;
938 Size freespace = 0;
939 int i;
940
941 Assert(SlabIsValid(slab));
942
943 /* Include context header in totalspace */
944 totalspace = Slab_CONTEXT_HDRSZ(slab->chunksPerBlock);
945
946 /* Add the space consumed by blocks in the emptyblocks list */
947 totalspace += dclist_count(&slab->emptyblocks) * slab->blockSize;
948
949 for (i = 0; i < SLAB_BLOCKLIST_COUNT; i++)
950 {
951 dlist_iter iter;
952
953 dlist_foreach(iter, &slab->blocklist[i])
954 {
955 SlabBlock *block = dlist_container(SlabBlock, node, iter.cur);
956
957 nblocks++;
958 totalspace += slab->blockSize;
959 freespace += slab->fullChunkSize * block->nfree;
960 freechunks += block->nfree;
961 }
962 }
963
964 if (printfunc)
965 {
966 char stats_string[200];
967
968 /* XXX should we include free chunks on empty blocks? */
969 snprintf(stats_string, sizeof(stats_string),
970 "%zu total in %zu blocks; %u empty blocks; %zu free (%zu chunks); %zu used",
971 totalspace, nblocks, dclist_count(&slab->emptyblocks),
972 freespace, freechunks, totalspace - freespace);
973 printfunc(context, passthru, stats_string, print_to_stderr);
974 }
975
976 if (totals)
977 {
978 totals->nblocks += nblocks;
979 totals->freechunks += freechunks;
980 totals->totalspace += totalspace;
981 totals->freespace += freespace;
982 }
983}
#define dlist_foreach(iter, lhead)
Definition: ilist.h:623
#define snprintf
Definition: port.h:238
dlist_node * cur
Definition: ilist.h:179

References Assert, SlabContext::blocklist, SlabContext::blockSize, SlabContext::chunksPerBlock, dlist_iter::cur, dclist_count(), dlist_container, dlist_foreach, SlabContext::emptyblocks, MemoryContextCounters::freechunks, MemoryContextCounters::freespace, SlabContext::fullChunkSize, i, MemoryContextCounters::nblocks, SlabBlock::nfree, SLAB_BLOCKLIST_COUNT, Slab_CONTEXT_HDRSZ, SlabIsValid, snprintf, and MemoryContextCounters::totalspace.

Variable Documentation

◆ size

pg_noinline void Size size
Initial value:
{
SlabContext *slab = (SlabContext *) context

Definition at line 606 of file slab.c.

Referenced by _bt_pageinit(), _crypt_blowfish_rn(), _crypt_gensalt_blowfish_rn(), _crypt_gensalt_extended_rn(), _crypt_gensalt_md5_rn(), _crypt_gensalt_traditional_rn(), _hash_pageinit(), _intbig_alloc(), _ltree_union(), _pglstat64(), _pgstat64(), add_file_to_manifest(), AddFileToBackupManifest(), addOrReplaceTuple(), ahwrite(), AlignedAllocRealloc(), alloc_object(), allocacl(), allocate_reloption(), allocateReloptStruct(), AllocSetAlloc(), AllocSetAllocChunkFromBlock(), AllocSetAllocFromNewBlock(), AllocSetAllocLarge(), AllocSetFreeIndex(), AllocSetRealloc(), AppendJumble(), ApplyLauncherShmemSize(), array_agg_array_combine(), array_agg_array_deserialize(), ASN1_STRING_to_text(), AssignPostmasterChildSlot(), AsyncShmemInit(), AsyncShmemSize(), AutoVacuumShmemSize(), BackendStatusShmemInit(), BackendStatusShmemSize(), BackgroundWorkerShmemSize(), BF_decode(), BF_encode(), bms_copy(), box_poly(), brin_form_placeholder_tuple(), brin_form_tuple(), bringetbitmap(), brinGetTupleForHeapBlock(), bsearch_arg(), BTreeShmemSize(), BufferManagerShmemSize(), BufFileRead(), BufFileReadCommon(), BufFileReadExact(), BufFileReadMaybeEOF(), BufFileWrite(), BufTableShmemSize(), build_hash_table(), BumpAlloc(), BumpAllocChunkFromBlock(), BumpAllocFromNewBlock(), BumpAllocLarge(), calc_rank_and(), calc_rank_or(), calcstrlen(), calculate_indexes_size(), calculate_table_size(), calculate_toast_table_size(), calculate_total_relation_size(), CalculateShmemSize(), check_synchronized_standby_slots(), checkdig(), CheckpointerShmemInit(), CheckpointerShmemSize(), chooseNextStatEntry(), circle_poly(), combinebackup_per_file_cb(), compact_palloc0(), CopyIndexTuple(), CopyMultiInsertBufferFlush(), CopySnapshot(), count_usable_fds(), crc32_sz(), create_internal(), CreateAnonymousSegment(), CreateSharedMemoryAndSemaphores(), cube_a_f8(), cube_a_f8_f8(), cube_c_f8(), cube_c_f8_f8(), cube_enlarge(), cube_f8(), cube_f8_f8(), cube_inter(), cube_subset(), cube_union_v0(), datumGetSize(), decoct(), DecodeXLogRecordRequiredSpace(), dense_alloc(), digestControlFile(), doPickSplit(), dsa_allocate_extended(), dsa_create_in_place_ext(), dsa_free(), dsa_get_total_size(), dsa_minimum_size(), dshash_destroy(), dshash_memcmp(), dshash_memcpy(), dshash_memhash(), dshash_strcmp(), dshash_strcpy(), dshash_strhash(), dsm_create(), dsm_impl_posix_resize(), dsm_shmem_init(), dummy_ssl_passwd_cb(), DynaHashAlloc(), ecpg_alloc(), ecpg_auto_alloc(), ecpg_build_compat_sqlda(), ecpg_build_native_sqlda(), ecpg_get_data(), ecpg_realloc(), ecpg_sqlda_align_add_size(), ECPGdump_a_simple(), ECPGmake_array_type(), ECPGmake_simple_type(), emalloc(), entrySplitPage(), erealloc(), estimate_variable_size(), EstimateClientConnectionInfoSpace(), EstimateComboCIDStateSpace(), EstimateGUCStateSpace(), EstimateLibraryStateSpace(), EstimateSnapshotSpace(), EstimateTransactionStateSpace(), evalStandardFunc(), ExecAggEstimate(), ExecAggInitializeDSM(), ExecAggRetrieveInstrumentation(), ExecBitmapHeapEstimate(), ExecBitmapHeapInitializeDSM(), ExecBitmapHeapRetrieveInstrumentation(), ExecHashEstimate(), ExecHashInitializeDSM(), ExecHashRetrieveInstrumentation(), ExecIncrementalSortEstimate(), ExecIncrementalSortInitializeDSM(), ExecIncrementalSortRetrieveInstrumentation(), ExecMemoizeEstimate(), ExecMemoizeInitializeDSM(), ExecMemoizeRetrieveInstrumentation(), ExecParallelHashIncreaseNumBuckets(), ExecParallelHashTupleAlloc(), ExecParallelHashTuplePrealloc(), ExecSortEstimate(), ExecSortInitializeDSM(), ExecSortRetrieveInstrumentation(), executeItemOptUnwrapTarget(), fill_buffer(), fillRelOptions(), filter_get_keyword(), filter_read_item(), findoprnd(), form_and_insert_tuple(), form_and_spill_tuple(), g_int_union(), g_intbig_union(), gbt_bit_union(), gbt_bytea_union(), gbt_numeric_union(), gbt_text_union(), gbt_var_union(), GenerationAlloc(), GenerationAllocChunkFromBlock(), GenerationAllocFromNewBlock(), GenerationAllocLarge(), GenerationRealloc(), get_decomposed_size(), get_object_type(), GetFileBackupMethod(), GetNamedDSMSegment(), GetPermutation(), gets_none(), GetSessionDsmHandle(), ghstore_alloc(), ghstore_union(), gimme_pool_size(), gistfitpage(), gistnospace(), gtrgm_alloc(), gtrgm_union(), gtsquery_union(), gtsvector_alloc(), gtsvector_union(), guc_malloc(), guc_realloc(), hash_estimate_size(), index_form_tuple_context(), inet_cidr_ntop_ipv4(), inet_cidr_ntop_ipv6(), inet_cidr_pton_ipv4(), inet_cidr_pton_ipv6(), inet_net_ntop_ipv4(), inet_net_ntop_ipv6(), inet_net_pton_ipv4(), InitBufTable(), InitPostmasterChildSlots(), injection_shmem_request(), internal_size(), InternalIpcMemoryCreate(), json_manifest_finalize_file(), json_parse_manifest(), json_parse_manifest_incremental_chunk(), len_utf8(), loc_alloc(), LockManagerShmemSize(), LogicalTapeBackspace(), LogicalTapeRead(), LogicalTapeWrite(), LogLogicalMessage(), lrq_alloc(), ltree_crc32_sz(), ltree_gist_alloc(), ltree_union(), LWLockShmemSize(), main(), make_multirange(), makeParamList(), makeSublist(), manifest_process_file(), memcpyInnerDatum(), MemoryContextAlloc(), MemoryContextAllocAligned(), MemoryContextAllocationFailure(), MemoryContextAllocExtended(), MemoryContextAllocHuge(), MemoryContextAllocZero(), MemoryContextCheckSize(), MemoryContextSizeFailure(), mm_alloc(), moveLeafs(), multirange_size_estimate(), MultiXactShmemSize(), mXactCacheGetById(), newNode(), open_walfile(), PageAddItemExtended(), PageIndexMultiDelete(), PageIndexTupleDelete(), PageIndexTupleDeleteNoCompact(), PageSetPageSizeAndVersion(), pagetable_allocate(), palloc(), palloc0(), palloc_aligned(), palloc_extended(), path_add(), path_in(), path_poly(), path_recv(), perform_rewind(), permute(), pg_database_size_name(), pg_database_size_oid(), pg_indexes_size(), pg_inet_cidr_ntop(), pg_inet_net_ntop(), pg_inet_net_pton(), pg_malloc(), pg_malloc0(), pg_malloc_extended(), pg_malloc_internal(), pg_pread(), pg_pwrite(), pg_pwrite_zeros(), pg_realloc(), pg_relation_size(), pg_size_pretty(), pg_size_pretty_numeric(), pg_table_size(), pg_tablespace_size_name(), pg_tablespace_size_oid(), pg_total_relation_size(), PgArchShmemSize(), pgconn_bio_read(), pgconn_bio_write(), PGSharedMemoryCreate(), pgss_memsize(), pgstat_cmp_hash_key(), pgstat_hash_hash_key(), pgtypes_alloc(), PGTYPESnumeric_from_long(), PLyBytes_FromBytea(), PLyObject_ToBytea(), PLyUnicode_FromStringAndSize(), PMSignalShmemSize(), pnstrdup(), poly_in(), poly_path(), poly_recv(), port_bio_read(), port_bio_write(), pq_getkeepalivescount(), pq_getkeepalivesidle(), pq_getkeepalivesinterval(), pq_gettcpusertimeout(), PQdefaultSSLKeyPassHook_OpenSSL(), PQssl_passwd_cb(), PredicateLockShmemSize(), ProcArrayShmemSize(), process_source_file(), process_target_file(), ProcGlobalShmemSize(), ProcSignalShmemInit(), ProcSignalShmemSize(), random_init_pool(), range_search(), rbt_populate(), read_gucstate_binary(), read_none(), read_stream_begin_impl(), ReorderBufferCopySnap(), ReorderBufferRestoreChange(), ReorderBufferSerializeChange(), ReorderBufferSerializeTXN(), repalloc(), repalloc0(), repalloc_extended(), repalloc_huge(), ReplicationOriginShmemSize(), ReplicationSlotsShmemSize(), ReportTemporaryFileUsage(), RequestAddinShmemSpace(), ReserveXLogInsertLocation(), ReserveXLogSwitch(), resize(), RestoreSnapshot(), rot13_passphrase(), rt__int_size(), rt_cube_size(), rt_seg_size(), run_ssl_passphrase_command(), sendDir(), sendTablespace(), SerializeParamExecParams(), SerializeUncommittedEnums(), setup_simple_rel_arrays(), SharedInvalShmemSize(), shm_mq_create(), ShmemAlloc(), ShmemAllocNoError(), ShmemAllocRaw(), ShmemAllocUnlocked(), ShmemInitStruct(), sizebitvec(), SlabAlloc(), SlabAllocFromNewBlock(), SlabAllocSetupNewChunk(), SlabRealloc(), SlotSyncShmemInit(), SN_set_current(), SnapBuildRestoreContents(), SortAndUniqItems(), spgFormInnerTuple(), spgFormLeafTuple(), spgFormNodeTuple(), SpGistGetInnerTypeSize(), SpGistGetLeafTupleSize(), SpGistPageAddNewItem(), SPI_palloc(), SPI_repalloc(), ssl_external_passwd_cb(), StrategyShmemSize(), sts_flush_chunk(), sts_puttuple(), sts_read_tuple(), tarCreateHeader(), test_rb_tree(), testdelete(), testfind(), testfindltgt(), testleftmost(), testleftright(), testrightleft(), transfer_single_new_db(), tsqueryrecv(), tsvector_concat(), tuplesort_putbrintuple(), TwoPhaseShmemSize(), unicode_assigned(), unicode_is_normalized(), unicode_normalize_func(), verify_manifest_checksum(), verifybackup_per_file_cb(), WalRcvShmemSize(), WalSndShmemSize(), weight_checkdig(), write_none(), write_target_range(), writeListPage(), writeTimeLineHistoryFile(), X509_NAME_to_cstring(), XLogReaderSetDecodeBuffer(), XLogRecoveryShmemSize(), XLOGShmemSize(), yyalloc(), and yyrealloc().