PostgreSQL Source Code  git master
memutils.h File Reference
#include "nodes/memnodes.h"
Include dependency graph for memutils.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define MaxAllocSize   ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
 
#define AllocSizeIsValid(size)   ((Size) (size) <= MaxAllocSize)
 
#define MaxAllocHugeSize   (SIZE_MAX / 2)
 
#define InvalidAllocSize   SIZE_MAX
 
#define AllocHugeSizeIsValid(size)   ((Size) (size) <= MaxAllocHugeSize)
 
#define MemoryContextCopyAndSetIdentifier(cxt, id)    MemoryContextSetIdentifier(cxt, MemoryContextStrdup(cxt, id))
 
#define AllocSetContextCreate    AllocSetContextCreateInternal
 
#define ALLOCSET_DEFAULT_MINSIZE   0
 
#define ALLOCSET_DEFAULT_INITSIZE   (8 * 1024)
 
#define ALLOCSET_DEFAULT_MAXSIZE   (8 * 1024 * 1024)
 
#define ALLOCSET_DEFAULT_SIZES    ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE
 
#define ALLOCSET_SMALL_MINSIZE   0
 
#define ALLOCSET_SMALL_INITSIZE   (1 * 1024)
 
#define ALLOCSET_SMALL_MAXSIZE   (8 * 1024)
 
#define ALLOCSET_SMALL_SIZES    ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MAXSIZE
 
#define ALLOCSET_START_SMALL_SIZES    ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE
 
#define ALLOCSET_SEPARATE_THRESHOLD   8192
 
#define SLAB_DEFAULT_BLOCK_SIZE   (8 * 1024)
 
#define SLAB_LARGE_BLOCK_SIZE   (8 * 1024 * 1024)
 

Functions

void MemoryContextInit (void)
 
void MemoryContextReset (MemoryContext context)
 
void MemoryContextDelete (MemoryContext context)
 
void MemoryContextResetOnly (MemoryContext context)
 
void MemoryContextResetChildren (MemoryContext context)
 
void MemoryContextDeleteChildren (MemoryContext context)
 
void MemoryContextSetIdentifier (MemoryContext context, const char *id)
 
void MemoryContextSetParent (MemoryContext context, MemoryContext new_parent)
 
MemoryContext GetMemoryChunkContext (void *pointer)
 
Size GetMemoryChunkSpace (void *pointer)
 
MemoryContext MemoryContextGetParent (MemoryContext context)
 
bool MemoryContextIsEmpty (MemoryContext context)
 
Size MemoryContextMemAllocated (MemoryContext context, bool recurse)
 
void MemoryContextMemConsumed (MemoryContext context, MemoryContextCounters *consumed)
 
void MemoryContextStats (MemoryContext context)
 
void MemoryContextStatsDetail (MemoryContext context, int max_level, int max_children, bool print_to_stderr)
 
void MemoryContextAllowInCriticalSection (MemoryContext context, bool allow)
 
void HandleLogMemoryContextInterrupt (void)
 
void ProcessLogMemoryContextInterrupt (void)
 
MemoryContext AllocSetContextCreateInternal (MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
 
MemoryContext SlabContextCreate (MemoryContext parent, const char *name, Size blockSize, Size chunkSize)
 
MemoryContext GenerationContextCreate (MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
 
MemoryContext BumpContextCreate (MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
 

Variables

PGDLLIMPORT MemoryContext TopMemoryContext
 
PGDLLIMPORT MemoryContext ErrorContext
 
PGDLLIMPORT MemoryContext PostmasterContext
 
PGDLLIMPORT MemoryContext CacheMemoryContext
 
PGDLLIMPORT MemoryContext MessageContext
 
PGDLLIMPORT MemoryContext TopTransactionContext
 
PGDLLIMPORT MemoryContext CurTransactionContext
 
PGDLLIMPORT MemoryContext PortalContext
 

Macro Definition Documentation

◆ AllocHugeSizeIsValid

#define AllocHugeSizeIsValid (   size)    ((Size) (size) <= MaxAllocHugeSize)

Definition at line 49 of file memutils.h.

◆ ALLOCSET_DEFAULT_INITSIZE

#define ALLOCSET_DEFAULT_INITSIZE   (8 * 1024)

Definition at line 158 of file memutils.h.

◆ ALLOCSET_DEFAULT_MAXSIZE

#define ALLOCSET_DEFAULT_MAXSIZE   (8 * 1024 * 1024)

Definition at line 159 of file memutils.h.

◆ ALLOCSET_DEFAULT_MINSIZE

#define ALLOCSET_DEFAULT_MINSIZE   0

Definition at line 157 of file memutils.h.

◆ ALLOCSET_DEFAULT_SIZES

Definition at line 160 of file memutils.h.

◆ ALLOCSET_SEPARATE_THRESHOLD

#define ALLOCSET_SEPARATE_THRESHOLD   8192

Definition at line 187 of file memutils.h.

◆ ALLOCSET_SMALL_INITSIZE

#define ALLOCSET_SMALL_INITSIZE   (1 * 1024)

Definition at line 168 of file memutils.h.

◆ ALLOCSET_SMALL_MAXSIZE

#define ALLOCSET_SMALL_MAXSIZE   (8 * 1024)

Definition at line 169 of file memutils.h.

◆ ALLOCSET_SMALL_MINSIZE

#define ALLOCSET_SMALL_MINSIZE   0

Definition at line 167 of file memutils.h.

◆ ALLOCSET_SMALL_SIZES

Definition at line 170 of file memutils.h.

◆ ALLOCSET_START_SMALL_SIZES

#define ALLOCSET_START_SMALL_SIZES    ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE

Definition at line 177 of file memutils.h.

◆ AllocSetContextCreate

#define AllocSetContextCreate    AllocSetContextCreateInternal

Definition at line 129 of file memutils.h.

◆ AllocSizeIsValid

#define AllocSizeIsValid (   size)    ((Size) (size) <= MaxAllocSize)

Definition at line 42 of file memutils.h.

◆ InvalidAllocSize

#define InvalidAllocSize   SIZE_MAX

Definition at line 47 of file memutils.h.

◆ MaxAllocHugeSize

#define MaxAllocHugeSize   (SIZE_MAX / 2)

Definition at line 45 of file memutils.h.

◆ MaxAllocSize

#define MaxAllocSize   ((Size) 0x3fffffff) /* 1 gigabyte - 1 */

Definition at line 40 of file memutils.h.

◆ MemoryContextCopyAndSetIdentifier

#define MemoryContextCopyAndSetIdentifier (   cxt,
  id 
)     MemoryContextSetIdentifier(cxt, MemoryContextStrdup(cxt, id))

Definition at line 101 of file memutils.h.

◆ SLAB_DEFAULT_BLOCK_SIZE

#define SLAB_DEFAULT_BLOCK_SIZE   (8 * 1024)

Definition at line 189 of file memutils.h.

◆ SLAB_LARGE_BLOCK_SIZE

#define SLAB_LARGE_BLOCK_SIZE   (8 * 1024 * 1024)

Definition at line 190 of file memutils.h.

Function Documentation

◆ AllocSetContextCreateInternal()

MemoryContext AllocSetContextCreateInternal ( MemoryContext  parent,
const char *  name,
Size  minContextSize,
Size  initBlockSize,
Size  maxBlockSize 
)

Definition at line 347 of file aset.c.

352 {
353  int freeListIndex;
354  Size firstBlockSize;
355  AllocSet set;
356  AllocBlock block;
357 
358  /* ensure MemoryChunk's size is properly maxaligned */
360  "sizeof(MemoryChunk) is not maxaligned");
361  /* check we have enough space to store the freelist link */
363  "sizeof(AllocFreeListLink) larger than minimum allocation size");
364 
365  /*
366  * First, validate allocation parameters. Once these were regular runtime
367  * tests and elog's, but in practice Asserts seem sufficient because
368  * nobody varies their parameters at runtime. We somewhat arbitrarily
369  * enforce a minimum 1K block size. We restrict the maximum block size to
370  * MEMORYCHUNK_MAX_BLOCKOFFSET as MemoryChunks are limited to this in
371  * regards to addressing the offset between the chunk and the block that
372  * the chunk is stored on. We would be unable to store the offset between
373  * the chunk and block for any chunks that were beyond
374  * MEMORYCHUNK_MAX_BLOCKOFFSET bytes into the block if the block was to be
375  * larger than this.
376  */
377  Assert(initBlockSize == MAXALIGN(initBlockSize) &&
378  initBlockSize >= 1024);
379  Assert(maxBlockSize == MAXALIGN(maxBlockSize) &&
380  maxBlockSize >= initBlockSize &&
381  AllocHugeSizeIsValid(maxBlockSize)); /* must be safe to double */
382  Assert(minContextSize == 0 ||
383  (minContextSize == MAXALIGN(minContextSize) &&
384  minContextSize >= 1024 &&
385  minContextSize <= maxBlockSize));
386  Assert(maxBlockSize <= MEMORYCHUNK_MAX_BLOCKOFFSET);
387 
388  /*
389  * Check whether the parameters match either available freelist. We do
390  * not need to demand a match of maxBlockSize.
391  */
392  if (minContextSize == ALLOCSET_DEFAULT_MINSIZE &&
393  initBlockSize == ALLOCSET_DEFAULT_INITSIZE)
394  freeListIndex = 0;
395  else if (minContextSize == ALLOCSET_SMALL_MINSIZE &&
396  initBlockSize == ALLOCSET_SMALL_INITSIZE)
397  freeListIndex = 1;
398  else
399  freeListIndex = -1;
400 
401  /*
402  * If a suitable freelist entry exists, just recycle that context.
403  */
404  if (freeListIndex >= 0)
405  {
406  AllocSetFreeList *freelist = &context_freelists[freeListIndex];
407 
408  if (freelist->first_free != NULL)
409  {
410  /* Remove entry from freelist */
411  set = freelist->first_free;
412  freelist->first_free = (AllocSet) set->header.nextchild;
413  freelist->num_free--;
414 
415  /* Update its maxBlockSize; everything else should be OK */
416  set->maxBlockSize = maxBlockSize;
417 
418  /* Reinitialize its header, installing correct name and parent */
420  T_AllocSetContext,
421  MCTX_ASET_ID,
422  parent,
423  name);
424 
425  ((MemoryContext) set)->mem_allocated =
426  KeeperBlock(set)->endptr - ((char *) set);
427 
428  return (MemoryContext) set;
429  }
430  }
431 
432  /* Determine size of initial block */
433  firstBlockSize = MAXALIGN(sizeof(AllocSetContext)) +
435  if (minContextSize != 0)
436  firstBlockSize = Max(firstBlockSize, minContextSize);
437  else
438  firstBlockSize = Max(firstBlockSize, initBlockSize);
439 
440  /*
441  * Allocate the initial block. Unlike other aset.c blocks, it starts with
442  * the context header and its block header follows that.
443  */
444  set = (AllocSet) malloc(firstBlockSize);
445  if (set == NULL)
446  {
447  if (TopMemoryContext)
449  ereport(ERROR,
450  (errcode(ERRCODE_OUT_OF_MEMORY),
451  errmsg("out of memory"),
452  errdetail("Failed while creating memory context \"%s\".",
453  name)));
454  }
455 
456  /*
457  * Avoid writing code that can fail between here and MemoryContextCreate;
458  * we'd leak the header/initial block if we ereport in this stretch.
459  */
460 
461  /* Fill in the initial block's block header */
462  block = KeeperBlock(set);
463  block->aset = set;
464  block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
465  block->endptr = ((char *) set) + firstBlockSize;
466  block->prev = NULL;
467  block->next = NULL;
468 
469  /* Mark unallocated space NOACCESS; leave the block header alone. */
470  VALGRIND_MAKE_MEM_NOACCESS(block->freeptr, block->endptr - block->freeptr);
471 
472  /* Remember block as part of block list */
473  set->blocks = block;
474 
475  /* Finish filling in aset-specific parts of the context header */
476  MemSetAligned(set->freelist, 0, sizeof(set->freelist));
477 
478  set->initBlockSize = (uint32) initBlockSize;
479  set->maxBlockSize = (uint32) maxBlockSize;
480  set->nextBlockSize = (uint32) initBlockSize;
481  set->freeListIndex = freeListIndex;
482 
483  /*
484  * Compute the allocation chunk size limit for this context. It can't be
485  * more than ALLOC_CHUNK_LIMIT because of the fixed number of freelists.
486  * If maxBlockSize is small then requests exceeding the maxBlockSize, or
487  * even a significant fraction of it, should be treated as large chunks
488  * too. For the typical case of maxBlockSize a power of 2, the chunk size
489  * limit will be at most 1/8th maxBlockSize, so that given a stream of
490  * requests that are all the maximum chunk size we will waste at most
491  * 1/8th of the allocated space.
492  *
493  * Also, allocChunkLimit must not exceed ALLOCSET_SEPARATE_THRESHOLD.
494  */
496  "ALLOC_CHUNK_LIMIT != ALLOCSET_SEPARATE_THRESHOLD");
497 
498  /*
499  * Determine the maximum size that a chunk can be before we allocate an
500  * entire AllocBlock dedicated for that chunk. We set the absolute limit
501  * of that size as ALLOC_CHUNK_LIMIT but we reduce it further so that we
502  * can fit about ALLOC_CHUNK_FRACTION chunks this size on a maximally
503  * sized block. (We opt to keep allocChunkLimit a power-of-2 value
504  * primarily for legacy reasons rather than calculating it so that exactly
505  * ALLOC_CHUNK_FRACTION chunks fit on a maximally sized block.)
506  */
508  while ((Size) (set->allocChunkLimit + ALLOC_CHUNKHDRSZ) >
509  (Size) ((maxBlockSize - ALLOC_BLOCKHDRSZ) / ALLOC_CHUNK_FRACTION))
510  set->allocChunkLimit >>= 1;
511 
512  /* Finally, do the type-independent part of context creation */
514  T_AllocSetContext,
515  MCTX_ASET_ID,
516  parent,
517  name);
518 
519  ((MemoryContext) set)->mem_allocated = firstBlockSize;
520 
521  return (MemoryContext) set;
522 }
#define ALLOC_CHUNKHDRSZ
Definition: aset.c:105
#define KeeperBlock(set)
Definition: aset.c:244
#define ALLOC_MINBITS
Definition: aset.c:83
#define ALLOC_BLOCKHDRSZ
Definition: aset.c:104
#define ALLOC_CHUNK_FRACTION
Definition: aset.c:87
#define ALLOC_CHUNK_LIMIT
Definition: aset.c:85
static AllocSetFreeList context_freelists[2]
Definition: aset.c:257
AllocSetContext * AllocSet
Definition: aset.c:167
unsigned int uint32
Definition: c.h:506
#define MAXALIGN(LEN)
Definition: c.h:811
#define Max(x, y)
Definition: c.h:998
#define Assert(condition)
Definition: c.h:858
#define MemSetAligned(start, val, len)
Definition: c.h:1050
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:936
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:938
size_t Size
Definition: c.h:605
int errdetail(const char *fmt,...)
Definition: elog.c:1205
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define malloc(a)
Definition: header.h:50
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 VALGRIND_MAKE_MEM_NOACCESS(addr, size)
Definition: memdebug.h:27
#define ALLOCSET_SMALL_MINSIZE
Definition: memutils.h:167
#define ALLOCSET_DEFAULT_MINSIZE
Definition: memutils.h:157
#define AllocHugeSizeIsValid(size)
Definition: memutils.h:49
#define ALLOCSET_SEPARATE_THRESHOLD
Definition: memutils.h:187
#define ALLOCSET_SMALL_INITSIZE
Definition: memutils.h:168
#define ALLOCSET_DEFAULT_INITSIZE
Definition: memutils.h:158
@ MCTX_ASET_ID
#define MEMORYCHUNK_MAX_BLOCKOFFSET
struct MemoryContextData * MemoryContext
Definition: palloc.h:36
AllocBlock prev
Definition: aset.c:184
AllocSet aset
Definition: aset.c:183
char * freeptr
Definition: aset.c:186
AllocBlock next
Definition: aset.c:185
char * endptr
Definition: aset.c:187
uint32 initBlockSize
Definition: aset.c:159
uint32 maxBlockSize
Definition: aset.c:160
uint32 allocChunkLimit
Definition: aset.c:162
MemoryContextData header
Definition: aset.c:154
int freeListIndex
Definition: aset.c:164
AllocBlock blocks
Definition: aset.c:156
uint32 nextBlockSize
Definition: aset.c:161
MemoryChunk * freelist[ALLOCSET_NUM_FREELISTS]
Definition: aset.c:157
int num_free
Definition: aset.c:252
AllocSetContext * first_free
Definition: aset.c:253
MemoryContext nextchild
Definition: memnodes.h:130
const char * name

References ALLOC_BLOCKHDRSZ, ALLOC_CHUNK_FRACTION, ALLOC_CHUNK_LIMIT, ALLOC_CHUNKHDRSZ, ALLOC_MINBITS, AllocSetContext::allocChunkLimit, AllocHugeSizeIsValid, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_SEPARATE_THRESHOLD, ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MINSIZE, AllocBlockData::aset, Assert, AllocSetContext::blocks, context_freelists, AllocBlockData::endptr, ereport, errcode(), errdetail(), errmsg(), ERROR, AllocSetFreeList::first_free, AllocSetContext::freelist, AllocSetContext::freeListIndex, AllocBlockData::freeptr, AllocSetContext::header, AllocSetContext::initBlockSize, KeeperBlock, malloc, Max, MAXALIGN, AllocSetContext::maxBlockSize, MCTX_ASET_ID, MEMORYCHUNK_MAX_BLOCKOFFSET, MemoryContextCreate(), MemoryContextStats(), MemSetAligned, name, AllocBlockData::next, AllocSetContext::nextBlockSize, MemoryContextData::nextchild, AllocSetFreeList::num_free, AllocBlockData::prev, StaticAssertDecl, StaticAssertStmt, TopMemoryContext, and VALGRIND_MAKE_MEM_NOACCESS.

◆ BumpContextCreate()

MemoryContext BumpContextCreate ( MemoryContext  parent,
const char *  name,
Size  minContextSize,
Size  initBlockSize,
Size  maxBlockSize 
)

Definition at line 131 of file bump.c.

133 {
134  Size firstBlockSize;
135  Size allocSize;
136  BumpContext *set;
137  BumpBlock *block;
138 
139  /* ensure MemoryChunk's size is properly maxaligned */
141  "sizeof(MemoryChunk) is not maxaligned");
142 
143  /*
144  * First, validate allocation parameters. Asserts seem sufficient because
145  * nobody varies their parameters at runtime. We somewhat arbitrarily
146  * enforce a minimum 1K block size. We restrict the maximum block size to
147  * MEMORYCHUNK_MAX_BLOCKOFFSET as MemoryChunks are limited to this in
148  * regards to addressing the offset between the chunk and the block that
149  * the chunk is stored on. We would be unable to store the offset between
150  * the chunk and block for any chunks that were beyond
151  * MEMORYCHUNK_MAX_BLOCKOFFSET bytes into the block if the block was to be
152  * larger than this.
153  */
154  Assert(initBlockSize == MAXALIGN(initBlockSize) &&
155  initBlockSize >= 1024);
156  Assert(maxBlockSize == MAXALIGN(maxBlockSize) &&
157  maxBlockSize >= initBlockSize &&
158  AllocHugeSizeIsValid(maxBlockSize)); /* must be safe to double */
159  Assert(minContextSize == 0 ||
160  (minContextSize == MAXALIGN(minContextSize) &&
161  minContextSize >= 1024 &&
162  minContextSize <= maxBlockSize));
163  Assert(maxBlockSize <= MEMORYCHUNK_MAX_BLOCKOFFSET);
164 
165  /* Determine size of initial block */
166  allocSize = MAXALIGN(sizeof(BumpContext)) + Bump_BLOCKHDRSZ +
168  if (minContextSize != 0)
169  allocSize = Max(allocSize, minContextSize);
170  else
171  allocSize = Max(allocSize, initBlockSize);
172 
173  /*
174  * Allocate the initial block. Unlike other bump.c blocks, it starts with
175  * the context header and its block header follows that.
176  */
177  set = (BumpContext *) malloc(allocSize);
178  if (set == NULL)
179  {
181  ereport(ERROR,
182  (errcode(ERRCODE_OUT_OF_MEMORY),
183  errmsg("out of memory"),
184  errdetail("Failed while creating memory context \"%s\".",
185  name)));
186  }
187 
188  /*
189  * Avoid writing code that can fail between here and MemoryContextCreate;
190  * we'd leak the header and initial block if we ereport in this stretch.
191  */
192  dlist_init(&set->blocks);
193 
194  /* Fill in the initial block's block header */
195  block = KeeperBlock(set);
196  /* determine the block size and initialize it */
197  firstBlockSize = allocSize - MAXALIGN(sizeof(BumpContext));
198  BumpBlockInit(set, block, firstBlockSize);
199 
200  /* add it to the doubly-linked list of blocks */
201  dlist_push_head(&set->blocks, &block->node);
202 
203  /*
204  * Fill in BumpContext-specific header fields. The Asserts above should
205  * ensure that these all fit inside a uint32.
206  */
207  set->initBlockSize = (uint32) initBlockSize;
208  set->maxBlockSize = (uint32) maxBlockSize;
209  set->nextBlockSize = (uint32) initBlockSize;
210 
211  /*
212  * Compute the allocation chunk size limit for this context.
213  *
214  * Limit the maximum size a non-dedicated chunk can be so that we can fit
215  * at least Bump_CHUNK_FRACTION of chunks this big onto the maximum sized
216  * block. We must further limit this value so that it's no more than
217  * MEMORYCHUNK_MAX_VALUE. We're unable to have non-external chunks larger
218  * than that value as we store the chunk size in the MemoryChunk 'value'
219  * field in the call to MemoryChunkSetHdrMask().
220  */
221  set->allocChunkLimit = Min(maxBlockSize, MEMORYCHUNK_MAX_VALUE);
222  while ((Size) (set->allocChunkLimit + Bump_CHUNKHDRSZ) >
223  (Size) ((Size) (maxBlockSize - Bump_BLOCKHDRSZ) / Bump_CHUNK_FRACTION))
224  set->allocChunkLimit >>= 1;
225 
226  /* Finally, do the type-independent part of context creation */
227  MemoryContextCreate((MemoryContext) set, T_BumpContext, MCTX_BUMP_ID,
228  parent, name);
229 
230  ((MemoryContext) set)->mem_allocated = allocSize;
231 
232  return (MemoryContext) set;
233 }
#define Bump_CHUNK_FRACTION
Definition: bump.c:57
#define KeeperBlock(set)
Definition: bump.c:60
#define Bump_CHUNKHDRSZ
Definition: bump.c:54
static void BumpBlockInit(BumpContext *context, BumpBlock *block, Size blksize)
Definition: bump.c:535
#define Bump_BLOCKHDRSZ
Definition: bump.c:48
#define Min(x, y)
Definition: c.h:1004
static void dlist_init(dlist_head *head)
Definition: ilist.h:314
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:347
@ MCTX_BUMP_ID
#define MEMORYCHUNK_MAX_VALUE
Definition: bump.c:87
dlist_node node
Definition: bump.c:88
dlist_head blocks
Definition: bump.c:76
uint32 initBlockSize
Definition: bump.c:71
uint32 maxBlockSize
Definition: bump.c:72
uint32 nextBlockSize
Definition: bump.c:73
uint32 allocChunkLimit
Definition: bump.c:74

References BumpContext::allocChunkLimit, AllocHugeSizeIsValid, Assert, BumpContext::blocks, Bump_BLOCKHDRSZ, Bump_CHUNK_FRACTION, Bump_CHUNKHDRSZ, BumpBlockInit(), dlist_init(), dlist_push_head(), ereport, errcode(), errdetail(), errmsg(), ERROR, BumpContext::initBlockSize, KeeperBlock, malloc, Max, MAXALIGN, BumpContext::maxBlockSize, MCTX_BUMP_ID, MEMORYCHUNK_MAX_BLOCKOFFSET, MEMORYCHUNK_MAX_VALUE, MemoryContextCreate(), MemoryContextStats(), Min, name, BumpContext::nextBlockSize, BumpBlock::node, StaticAssertDecl, and TopMemoryContext.

Referenced by TidStoreCreateLocal(), and tuplesort_begin_batch().

◆ GenerationContextCreate()

MemoryContext GenerationContextCreate ( MemoryContext  parent,
const char *  name,
Size  minContextSize,
Size  initBlockSize,
Size  maxBlockSize 
)

Definition at line 160 of file generation.c.

165 {
166  Size firstBlockSize;
167  Size allocSize;
168  GenerationContext *set;
169  GenerationBlock *block;
170 
171  /* ensure MemoryChunk's size is properly maxaligned */
173  "sizeof(MemoryChunk) is not maxaligned");
174 
175  /*
176  * First, validate allocation parameters. Asserts seem sufficient because
177  * nobody varies their parameters at runtime. We somewhat arbitrarily
178  * enforce a minimum 1K block size. We restrict the maximum block size to
179  * MEMORYCHUNK_MAX_BLOCKOFFSET as MemoryChunks are limited to this in
180  * regards to addressing the offset between the chunk and the block that
181  * the chunk is stored on. We would be unable to store the offset between
182  * the chunk and block for any chunks that were beyond
183  * MEMORYCHUNK_MAX_BLOCKOFFSET bytes into the block if the block was to be
184  * larger than this.
185  */
186  Assert(initBlockSize == MAXALIGN(initBlockSize) &&
187  initBlockSize >= 1024);
188  Assert(maxBlockSize == MAXALIGN(maxBlockSize) &&
189  maxBlockSize >= initBlockSize &&
190  AllocHugeSizeIsValid(maxBlockSize)); /* must be safe to double */
191  Assert(minContextSize == 0 ||
192  (minContextSize == MAXALIGN(minContextSize) &&
193  minContextSize >= 1024 &&
194  minContextSize <= maxBlockSize));
195  Assert(maxBlockSize <= MEMORYCHUNK_MAX_BLOCKOFFSET);
196 
197  /* Determine size of initial block */
198  allocSize = MAXALIGN(sizeof(GenerationContext)) +
200  if (minContextSize != 0)
201  allocSize = Max(allocSize, minContextSize);
202  else
203  allocSize = Max(allocSize, initBlockSize);
204 
205  /*
206  * Allocate the initial block. Unlike other generation.c blocks, it
207  * starts with the context header and its block header follows that.
208  */
209  set = (GenerationContext *) malloc(allocSize);
210  if (set == NULL)
211  {
213  ereport(ERROR,
214  (errcode(ERRCODE_OUT_OF_MEMORY),
215  errmsg("out of memory"),
216  errdetail("Failed while creating memory context \"%s\".",
217  name)));
218  }
219 
220  /*
221  * Avoid writing code that can fail between here and MemoryContextCreate;
222  * we'd leak the header if we ereport in this stretch.
223  */
224  dlist_init(&set->blocks);
225 
226  /* Fill in the initial block's block header */
227  block = KeeperBlock(set);
228  /* determine the block size and initialize it */
229  firstBlockSize = allocSize - MAXALIGN(sizeof(GenerationContext));
230  GenerationBlockInit(set, block, firstBlockSize);
231 
232  /* add it to the doubly-linked list of blocks */
233  dlist_push_head(&set->blocks, &block->node);
234 
235  /* use it as the current allocation block */
236  set->block = block;
237 
238  /* No free block, yet */
239  set->freeblock = NULL;
240 
241  /* Fill in GenerationContext-specific header fields */
242  set->initBlockSize = (uint32) initBlockSize;
243  set->maxBlockSize = (uint32) maxBlockSize;
244  set->nextBlockSize = (uint32) initBlockSize;
245 
246  /*
247  * Compute the allocation chunk size limit for this context.
248  *
249  * Limit the maximum size a non-dedicated chunk can be so that we can fit
250  * at least Generation_CHUNK_FRACTION of chunks this big onto the maximum
251  * sized block. We must further limit this value so that it's no more
252  * than MEMORYCHUNK_MAX_VALUE. We're unable to have non-external chunks
253  * larger than that value as we store the chunk size in the MemoryChunk
254  * 'value' field in the call to MemoryChunkSetHdrMask().
255  */
256  set->allocChunkLimit = Min(maxBlockSize, MEMORYCHUNK_MAX_VALUE);
257  while ((Size) (set->allocChunkLimit + Generation_CHUNKHDRSZ) >
258  (Size) ((Size) (maxBlockSize - Generation_BLOCKHDRSZ) / Generation_CHUNK_FRACTION))
259  set->allocChunkLimit >>= 1;
260 
261  /* Finally, do the type-independent part of context creation */
263  T_GenerationContext,
265  parent,
266  name);
267 
268  ((MemoryContext) set)->mem_allocated = firstBlockSize;
269 
270  return (MemoryContext) set;
271 }
static void GenerationBlockInit(GenerationContext *context, GenerationBlock *block, Size blksize)
Definition: generation.c:609
#define Generation_CHUNK_FRACTION
Definition: generation.c:49
#define KeeperBlock(set)
Definition: generation.c:127
#define Generation_CHUNKHDRSZ
Definition: generation.c:47
#define Generation_BLOCKHDRSZ
Definition: generation.c:46
@ MCTX_GENERATION_ID
dlist_node node
Definition: generation.c:89
GenerationBlock * freeblock
Definition: generation.c:70
uint32 maxBlockSize
Definition: generation.c:65
uint32 nextBlockSize
Definition: generation.c:66
dlist_head blocks
Definition: generation.c:72
uint32 initBlockSize
Definition: generation.c:64
GenerationBlock * block
Definition: generation.c:69
uint32 allocChunkLimit
Definition: generation.c:67

References GenerationContext::allocChunkLimit, AllocHugeSizeIsValid, Assert, GenerationContext::block, GenerationContext::blocks, dlist_init(), dlist_push_head(), ereport, errcode(), errdetail(), errmsg(), ERROR, GenerationContext::freeblock, Generation_BLOCKHDRSZ, Generation_CHUNK_FRACTION, Generation_CHUNKHDRSZ, GenerationBlockInit(), GenerationContext::initBlockSize, KeeperBlock, malloc, Max, MAXALIGN, GenerationContext::maxBlockSize, MCTX_GENERATION_ID, MEMORYCHUNK_MAX_BLOCKOFFSET, MEMORYCHUNK_MAX_VALUE, MemoryContextCreate(), MemoryContextStats(), Min, name, GenerationContext::nextBlockSize, GenerationBlock::node, StaticAssertDecl, and TopMemoryContext.

Referenced by gistvacuumscan(), and ReorderBufferAllocate().

◆ GetMemoryChunkContext()

MemoryContext GetMemoryChunkContext ( void *  pointer)

Definition at line 707 of file mcxt.c.

708 {
709  return MCXT_METHOD(pointer, get_chunk_context) (pointer);
710 }
#define MCXT_METHOD(pointer, method)
Definition: mcxt.c:182

References MCXT_METHOD.

Referenced by AlignedAllocFree(), AlignedAllocGetChunkContext(), AlignedAllocRealloc(), create_unique_path(), enlarge_list(), guc_free(), guc_realloc(), list_delete_first_n(), list_delete_nth_cell(), mark_dummy_rel(), pfree(), repalloc(), repalloc_extended(), and reparameterize_path_by_child().

◆ GetMemoryChunkSpace()

◆ HandleLogMemoryContextInterrupt()

void HandleLogMemoryContextInterrupt ( void  )

Definition at line 1271 of file mcxt.c.

1272 {
1273  InterruptPending = true;
1274  LogMemoryContextPending = true;
1275  /* latch will be set by procsignal_sigusr1_handler */
1276 }
volatile sig_atomic_t LogMemoryContextPending
Definition: globals.c:39
volatile sig_atomic_t InterruptPending
Definition: globals.c:30

References InterruptPending, and LogMemoryContextPending.

Referenced by procsignal_sigusr1_handler().

◆ MemoryContextAllowInCriticalSection()

void MemoryContextAllowInCriticalSection ( MemoryContext  context,
bool  allow 
)

Definition at line 694 of file mcxt.c.

695 {
697 
698  context->allowInCritSection = allow;
699 }
#define MemoryContextIsValid(context)
Definition: memnodes.h:145
tree context
Definition: radixtree.h:1833

References Assert, context, and MemoryContextIsValid.

Referenced by InitSync(), MemoryContextInit(), and XLOGShmemInit().

◆ MemoryContextDelete()

void MemoryContextDelete ( MemoryContext  context)

Definition at line 454 of file mcxt.c.

455 {
456  MemoryContext curr;
457 
459 
460  /*
461  * Delete subcontexts from the bottom up.
462  *
463  * Note: Do not use recursion here. A "stack depth limit exceeded" error
464  * would be unpleasant if we're already in the process of cleaning up from
465  * transaction abort. We also cannot use MemoryContextTraverseNext() here
466  * because we modify the tree as we go.
467  */
468  curr = context;
469  for (;;)
470  {
471  MemoryContext parent;
472 
473  /* Descend down until we find a leaf context with no children */
474  while (curr->firstchild != NULL)
475  curr = curr->firstchild;
476 
477  /*
478  * We're now at a leaf with no children. Free it and continue from the
479  * parent. Or if this was the original node, we're all done.
480  */
481  parent = curr->parent;
483 
484  if (curr == context)
485  break;
486  curr = parent;
487  }
488 }
static void MemoryContextDeleteOnly(MemoryContext context)
Definition: mcxt.c:496
MemoryContext firstchild
Definition: memnodes.h:128
MemoryContext parent
Definition: memnodes.h:127

References Assert, context, MemoryContextData::firstchild, MemoryContextDeleteOnly(), MemoryContextIsValid, and MemoryContextData::parent.

Referenced by _brin_parallel_merge(), AfterTriggerEndXact(), afterTriggerInvokeEvents(), ApplyLauncherMain(), AtCleanup_Memory(), AtCommit_Memory(), AtEOSubXact_SPI(), AtEOXact_LargeObject(), AtSubCleanup_Memory(), AtSubCommit_Memory(), AttachPartitionEnsureIndexes(), autovacuum_do_vac_analyze(), AutoVacWorkerMain(), AuxiliaryProcessMainCommon(), BackgroundWorkerMain(), blbuild(), blinsert(), brin_free_desc(), brin_minmax_multi_union(), bringetbitmap(), brininsert(), bt_check_every_level(), btendscan(), btree_xlog_cleanup(), btvacuumscan(), BuildParamLogString(), BuildRelationExtStatistics(), CloneRowTriggersToPartition(), cluster(), compactify_ranges(), compile_plperl_function(), compile_pltcl_function(), compute_expr_stats(), compute_index_stats(), ComputeExtStatisticsRows(), createTrgmNFA(), CreateTriggerFiringOn(), daitch_mokotoff(), decr_dcc_refcount(), DeleteExpandedObject(), DiscreteKnapsack(), do_analyze_rel(), do_start_worker(), DoCopyTo(), DropCachedPlan(), each_worker(), each_worker_jsonb(), elements_worker(), elements_worker_jsonb(), end_heap_rewrite(), EndCopy(), EndCopyFrom(), ensure_free_space_in_buffer(), EventTriggerEndCompleteQuery(), EventTriggerInvoke(), exec_replication_command(), exec_simple_query(), ExecEndAgg(), ExecEndMemoize(), ExecEndRecursiveUnion(), ExecEndSetOp(), ExecEndWindowAgg(), ExecHashTableDestroy(), execute_sql_string(), ExecVacuum(), file_acquire_sample_rows(), fill_hba_view(), fill_ident_view(), fmgr_sql(), free_auth_file(), free_plperl_function(), FreeCachedExpression(), FreeDecodingContext(), FreeExecutorState(), FreeExprContext(), freeGISTstate(), FreeSnapshotBuilder(), geqo_eval(), get_actual_variable_range(), get_rel_sync_entry(), GetWALRecordsInfo(), GetXLogSummaryStats(), gin_xlog_cleanup(), ginbuild(), ginbulkdelete(), ginendscan(), gininsert(), ginInsertCleanup(), ginPlaceToPage(), gist_xlog_cleanup(), gistbuild(), gistvacuumscan(), hash_destroy(), inline_function(), inline_set_returning_function(), libpqrcv_processTuples(), load_hba(), load_ident(), load_tzoffsets(), makeArrayResultArr(), makeMdArrayResult(), MemoryContextDeleteChildren(), NIFinishBuild(), pg_backup_stop(), pg_decode_shutdown(), pg_get_wal_block_info(), pgstat_clear_backend_activity_snapshot(), pgstat_clear_snapshot(), plperl_spi_freeplan(), plperl_spi_prepare(), plpgsql_free_function_memory(), pltcl_handler(), pltcl_SPI_prepare(), PLy_cursor_dealloc(), PLy_plan_dealloc(), PLy_pop_execution_context(), PLy_procedure_delete(), PLy_spi_execute_fetch_result(), PortalDrop(), PostgresMain(), printtup_shutdown(), publicationListToArray(), RE_compile_and_cache(), rebuild_database_list(), ReindexMultipleTables(), ReindexPartitions(), ReindexRelationConcurrently(), RelationBuildDesc(), RelationBuildRuleLock(), RelationDestroyRelation(), ReleaseCachedPlan(), ReorderBufferFree(), ResetUnloggedRelations(), RevalidateCachedQuery(), serializeAnalyzeShutdown(), shdepReassignOwned(), shutdown_MultiFuncCall(), spg_xlog_cleanup(), spgbuild(), spgendscan(), spginsert(), SPI_finish(), SPI_freeplan(), SPI_freetuptable(), statext_dependencies_build(), strlist_to_textarray(), SysLoggerMain(), test_pattern(), TidStoreDestroy(), tokenize_auth_file(), tuplesort_end(), union_tuples(), UploadManifest(), and validateForeignKeyConstraint().

◆ MemoryContextDeleteChildren()

void MemoryContextDeleteChildren ( MemoryContext  context)

Definition at line 539 of file mcxt.c.

540 {
542 
543  /*
544  * MemoryContextDelete will delink the child from me, so just iterate as
545  * long as there is a child.
546  */
547  while (context->firstchild != NULL)
548  MemoryContextDelete(context->firstchild);
549 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454

References Assert, context, MemoryContextDelete(), and MemoryContextIsValid.

Referenced by AtAbort_Portals(), AtSubAbort_Portals(), exec_stmt_block(), MemoryContextReset(), PersistHoldablePortal(), PortalRunMulti(), and RelationCloseCleanup().

◆ MemoryContextGetParent()

MemoryContext MemoryContextGetParent ( MemoryContext  context)

◆ MemoryContextInit()

void MemoryContextInit ( void  )

Definition at line 339 of file mcxt.c.

340 {
341  Assert(TopMemoryContext == NULL);
342 
343  /*
344  * First, initialize TopMemoryContext, which is the parent of all others.
345  */
347  "TopMemoryContext",
349 
350  /*
351  * Not having any other place to point CurrentMemoryContext, make it point
352  * to TopMemoryContext. Caller should change this soon!
353  */
355 
356  /*
357  * Initialize ErrorContext as an AllocSetContext with slow growth rate ---
358  * we don't really expect much to be allocated in it. More to the point,
359  * require it to contain at least 8K at all times. This is the only case
360  * where retained memory in a context is *essential* --- we want to be
361  * sure ErrorContext still has some memory even if we've run out
362  * elsewhere! Also, allow allocations in ErrorContext within a critical
363  * section. Otherwise a PANIC will cause an assertion failure in the error
364  * reporting code, before printing out the real cause of the failure.
365  *
366  * This should be the last step in this function, as elog.c assumes memory
367  * management works once ErrorContext is non-null.
368  */
370  "ErrorContext",
371  8 * 1024,
372  8 * 1024,
373  8 * 1024);
375 }
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
MemoryContext ErrorContext
Definition: mcxt.c:150
void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
Definition: mcxt.c:694
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, CurrentMemoryContext, ErrorContext, MemoryContextAllowInCriticalSection(), and TopMemoryContext.

Referenced by main().

◆ MemoryContextIsEmpty()

bool MemoryContextIsEmpty ( MemoryContext  context)

Definition at line 743 of file mcxt.c.

744 {
746 
747  /*
748  * For now, we consider a memory context nonempty if it has any children;
749  * perhaps this should be changed later.
750  */
751  if (context->firstchild != NULL)
752  return false;
753  /* Otherwise use the type-specific inquiry */
754  return context->methods->is_empty(context);
755 }

References Assert, context, and MemoryContextIsValid.

Referenced by AtSubCommit_Memory().

◆ MemoryContextMemAllocated()

Size MemoryContextMemAllocated ( MemoryContext  context,
bool  recurse 
)

Definition at line 762 of file mcxt.c.

763 {
764  Size total = context->mem_allocated;
765 
767 
768  if (recurse)
769  {
770  for (MemoryContext curr = context->firstchild;
771  curr != NULL;
772  curr = MemoryContextTraverseNext(curr, context))
773  {
774  total += curr->mem_allocated;
775  }
776  }
777 
778  return total;
779 }
static MemoryContext MemoryContextTraverseNext(MemoryContext curr, MemoryContext top)
Definition: mcxt.c:257

References Assert, context, MemoryContextIsValid, and MemoryContextTraverseNext().

Referenced by hash_agg_check_limits(), hash_agg_update_metrics(), and RT_MEMORY_USAGE().

◆ MemoryContextMemConsumed()

void MemoryContextMemConsumed ( MemoryContext  context,
MemoryContextCounters consumed 
)

Definition at line 786 of file mcxt.c.

788 {
790 
791  memset(consumed, 0, sizeof(*consumed));
792 
793  /* Examine the context itself */
794  context->methods->stats(context, NULL, NULL, consumed, false);
795 
796  /* Examine children, using iteration not recursion */
797  for (MemoryContext curr = context->firstchild;
798  curr != NULL;
799  curr = MemoryContextTraverseNext(curr, context))
800  {
801  curr->methods->stats(curr, NULL, NULL, consumed, false);
802  }
803 }

References Assert, context, MemoryContextIsValid, and MemoryContextTraverseNext().

Referenced by ExplainExecuteQuery(), and standard_ExplainOneQuery().

◆ MemoryContextReset()

void MemoryContextReset ( MemoryContext  context)

Definition at line 383 of file mcxt.c.

384 {
386 
387  /* save a function call in common case where there are no children */
388  if (context->firstchild != NULL)
390 
391  /* save a function call if no pallocs since startup or last reset */
392  if (!context->isReset)
394 }
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:539
void MemoryContextResetOnly(MemoryContext context)
Definition: mcxt.c:402

References Assert, context, MemoryContextDeleteChildren(), MemoryContextIsValid, and MemoryContextResetOnly().

Referenced by _brin_parallel_merge(), _bt_preprocess_array_keys(), _SPI_end_call(), AfterTriggerExecute(), apply_spooled_messages(), AtCleanup_Memory(), AtEOSubXact_SPI(), AtSubCleanup_Memory(), BackgroundWriterMain(), bloomBuildCallback(), brin_memtuple_initialize(), bringetbitmap(), brininsert(), bt_check_level_from_leftmost(), btree_redo(), btvacuumpage(), BuildEventTriggerCache(), BuildRelationExtStatistics(), buildSubPlanHash(), cache_purge_all(), check_domain_for_new_field(), check_domain_for_new_tuple(), CheckpointerMain(), CloneRowTriggersToPartition(), compute_expr_stats(), compute_index_stats(), CopyOneRowTo(), CreateTriggerFiringOn(), do_analyze_rel(), do_autovacuum(), dumptuples(), each_object_field_end(), each_worker_jsonb(), elements_array_element_end(), elements_worker_jsonb(), errstart(), eval_windowaggregates(), EventTriggerInvoke(), exec_dynquery_with_params(), exec_stmt_block(), exec_stmt_dynexecute(), exec_stmt_forc(), exec_stmt_foreach_a(), exec_stmt_open(), exec_stmt_raise(), exec_stmt_return_query(), ExecFindMatchingSubPlans(), ExecHashTableReset(), ExecMakeTableFunctionResult(), ExecProjectSet(), ExecQualAndReset(), ExecRecursiveUnion(), ExecReScanRecursiveUnion(), ExecReScanSetOp(), execTuplesUnequal(), execute_foreign_modify(), expanded_record_set_field_internal(), expanded_record_set_tuple(), fetch_more_data(), file_acquire_sample_rows(), FlushErrorState(), get_short_term_cxt(), GetWALRecordsInfo(), GetXLogSummaryStats(), gin_redo(), ginBuildCallback(), ginFreeScanKeys(), ginHeapTupleBulkInsert(), ginInsertCleanup(), ginVacuumPostingTreeLeaves(), gist_indexsortbuild(), gist_redo(), gistBuildCallback(), gistgetbitmap(), gistgettuple(), gistinsert(), gistProcessEmptyingQueue(), gistrescan(), gistScanPage(), gistSortedBuildCallback(), HandleParallelApplyMessages(), HandleParallelMessages(), heapam_index_build_range_scan(), heapam_index_validate_scan(), IndexCheckExclusion(), initialize_windowaggregate(), InvalidateEventCacheCallback(), keyGetItem(), libpqrcv_processTuples(), LogicalParallelApplyLoop(), LogicalRepApplyLoop(), lookup_ts_dictionary_cache(), make_tuple_from_result_row(), perform_work_item(), pg_backup_start(), pg_decode_change(), pg_decode_truncate(), pg_get_wal_block_info(), pgarch_archiveXlog(), pgoutput_change(), pgoutput_truncate(), plperl_return_next_internal(), PLy_input_convert(), PLy_input_from_tuple(), PostgresMain(), printtup(), process_ordered_aggregate_single(), release_partition(), ReScanExprContext(), resetSpGistScanOpaque(), RT_FREE(), scanPendingInsert(), sepgsql_avc_reset(), serializeAnalyzeReceive(), spcache_init(), spg_redo(), spginsert(), spgistBuildCallback(), spgWalk(), startScanKey(), statext_dependencies_build(), storeRow(), stream_stop_internal(), tfuncFetchRows(), tfuncLoadRows(), tuplesort_free(), validateForeignKeyConstraint(), WalSummarizerMain(), and WalWriterMain().

◆ MemoryContextResetChildren()

void MemoryContextResetChildren ( MemoryContext  context)

Definition at line 433 of file mcxt.c.

434 {
436 
437  for (MemoryContext curr = context->firstchild;
438  curr != NULL;
439  curr = MemoryContextTraverseNext(curr, context))
440  {
442  }
443 }

References Assert, context, MemoryContextIsValid, MemoryContextResetOnly(), and MemoryContextTraverseNext().

◆ MemoryContextResetOnly()

void MemoryContextResetOnly ( MemoryContext  context)

Definition at line 402 of file mcxt.c.

403 {
405 
406  /* Nothing to do if no pallocs since startup or last reset */
407  if (!context->isReset)
408  {
410 
411  /*
412  * If context->ident points into the context's memory, it will become
413  * a dangling pointer. We could prevent that by setting it to NULL
414  * here, but that would break valid coding patterns that keep the
415  * ident elsewhere, e.g. in a parent context. So for now we assume
416  * the programmer got it right.
417  */
418 
419  context->methods->reset(context);
420  context->isReset = true;
422  VALGRIND_CREATE_MEMPOOL(context, 0, false);
423  }
424 }
static void MemoryContextCallResetCallbacks(MemoryContext context)
Definition: mcxt.c:585
#define VALGRIND_DESTROY_MEMPOOL(context)
Definition: memdebug.h:25
#define VALGRIND_CREATE_MEMPOOL(context, redzones, zeroed)
Definition: memdebug.h:24

References Assert, context, MemoryContextCallResetCallbacks(), MemoryContextIsValid, VALGRIND_CREATE_MEMPOOL, and VALGRIND_DESTROY_MEMPOOL.

Referenced by AllocSetDelete(), JsonTableResetRowPattern(), MemoryContextReset(), MemoryContextResetChildren(), and mergeruns().

◆ MemoryContextSetIdentifier()

◆ MemoryContextSetParent()

void MemoryContextSetParent ( MemoryContext  context,
MemoryContext  new_parent 
)

Definition at line 637 of file mcxt.c.

638 {
640  Assert(context != new_parent);
641 
642  /* Fast path if it's got correct parent already */
643  if (new_parent == context->parent)
644  return;
645 
646  /* Delink from existing parent, if any */
647  if (context->parent)
648  {
649  MemoryContext parent = context->parent;
650 
651  if (context->prevchild != NULL)
652  context->prevchild->nextchild = context->nextchild;
653  else
654  {
655  Assert(parent->firstchild == context);
656  parent->firstchild = context->nextchild;
657  }
658 
659  if (context->nextchild != NULL)
660  context->nextchild->prevchild = context->prevchild;
661  }
662 
663  /* And relink */
664  if (new_parent)
665  {
666  Assert(MemoryContextIsValid(new_parent));
667  context->parent = new_parent;
668  context->prevchild = NULL;
669  context->nextchild = new_parent->firstchild;
670  if (new_parent->firstchild != NULL)
671  new_parent->firstchild->prevchild = context;
672  new_parent->firstchild = context;
673  }
674  else
675  {
676  context->parent = NULL;
677  context->prevchild = NULL;
678  context->nextchild = NULL;
679  }
680 }
MemoryContext prevchild
Definition: memnodes.h:129

References Assert, context, MemoryContextData::firstchild, MemoryContextIsValid, and MemoryContextData::prevchild.

Referenced by _SPI_save_plan(), CachedPlanSetParentContext(), CompleteCachedPlan(), exec_parse_message(), GetCachedExpression(), GetCachedPlan(), load_domaintype_info(), MemoryContextDeleteOnly(), RE_compile_and_cache(), RelationBuildPartitionDesc(), RelationBuildPartitionKey(), RelationBuildRowSecurity(), RelationClearRelation(), RevalidateCachedQuery(), SaveCachedPlan(), SPI_keepplan(), TransferExpandedObject(), and UploadManifest().

◆ MemoryContextStats()

void MemoryContextStats ( MemoryContext  context)

Definition at line 814 of file mcxt.c.

815 {
816  /* Hard-wired limits are usually good enough */
817  MemoryContextStatsDetail(context, 100, 100, true);
818 }
void MemoryContextStatsDetail(MemoryContext context, int max_level, int max_children, bool print_to_stderr)
Definition: mcxt.c:829

References context, and MemoryContextStatsDetail().

Referenced by AllocSetContextCreateInternal(), BumpContextCreate(), finish_xact_command(), GenerationContextCreate(), MemoryContextAllocationFailure(), SlabContextCreate(), and test_pattern().

◆ MemoryContextStatsDetail()

void MemoryContextStatsDetail ( MemoryContext  context,
int  max_level,
int  max_children,
bool  print_to_stderr 
)

Definition at line 829 of file mcxt.c.

832 {
833  MemoryContextCounters grand_totals;
834 
835  memset(&grand_totals, 0, sizeof(grand_totals));
836 
837  MemoryContextStatsInternal(context, 0, max_level, max_children,
838  &grand_totals, print_to_stderr);
839 
840  if (print_to_stderr)
841  fprintf(stderr,
842  "Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used\n",
843  grand_totals.totalspace, grand_totals.nblocks,
844  grand_totals.freespace, grand_totals.freechunks,
845  grand_totals.totalspace - grand_totals.freespace);
846  else
847  {
848  /*
849  * Use LOG_SERVER_ONLY to prevent the memory contexts from being sent
850  * to the connected client.
851  *
852  * We don't buffer the information about all memory contexts in a
853  * backend into StringInfo and log it as one message. That would
854  * require the buffer to be enlarged, risking an OOM as there could be
855  * a large number of memory contexts in a backend. Instead, we log
856  * one message per memory context.
857  */
859  (errhidestmt(true),
860  errhidecontext(true),
861  errmsg_internal("Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used",
862  grand_totals.totalspace, grand_totals.nblocks,
863  grand_totals.freespace, grand_totals.freechunks,
864  grand_totals.totalspace - grand_totals.freespace)));
865  }
866 }
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1159
int errhidestmt(bool hide_stmt)
Definition: elog.c:1413
int errhidecontext(bool hide_ctx)
Definition: elog.c:1432
#define LOG_SERVER_ONLY
Definition: elog.h:32
static void MemoryContextStatsInternal(MemoryContext context, int level, int max_level, int max_children, MemoryContextCounters *totals, bool print_to_stderr)
Definition: mcxt.c:876
#define fprintf
Definition: port.h:242

References context, ereport, errhidecontext(), errhidestmt(), errmsg_internal(), fprintf, MemoryContextCounters::freechunks, MemoryContextCounters::freespace, LOG_SERVER_ONLY, MemoryContextStatsInternal(), MemoryContextCounters::nblocks, and MemoryContextCounters::totalspace.

Referenced by MemoryContextStats(), and ProcessLogMemoryContextInterrupt().

◆ ProcessLogMemoryContextInterrupt()

void ProcessLogMemoryContextInterrupt ( void  )

Definition at line 1288 of file mcxt.c.

1289 {
1290  LogMemoryContextPending = false;
1291 
1292  /*
1293  * Use LOG_SERVER_ONLY to prevent this message from being sent to the
1294  * connected client.
1295  */
1297  (errhidestmt(true),
1298  errhidecontext(true),
1299  errmsg("logging memory contexts of PID %d", MyProcPid)));
1300 
1301  /*
1302  * When a backend process is consuming huge memory, logging all its memory
1303  * contexts might overrun available disk space. To prevent this, we limit
1304  * the depth of the hierarchy, as well as the number of child contexts to
1305  * log per parent to 100.
1306  *
1307  * As with MemoryContextStats(), we suppose that practical cases where the
1308  * dump gets long will typically be huge numbers of siblings under the
1309  * same parent context; while the additional debugging value from seeing
1310  * details about individual siblings beyond 100 will not be large.
1311  */
1312  MemoryContextStatsDetail(TopMemoryContext, 100, 100, false);
1313 }
int MyProcPid
Definition: globals.c:45

References ereport, errhidecontext(), errhidestmt(), errmsg(), LOG_SERVER_ONLY, LogMemoryContextPending, MemoryContextStatsDetail(), MyProcPid, and TopMemoryContext.

Referenced by HandleAutoVacLauncherInterrupts(), HandleCheckpointerInterrupts(), HandleMainLoopInterrupts(), HandlePgArchInterrupts(), HandleStartupProcInterrupts(), HandleWalSummarizerInterrupts(), and ProcessInterrupts().

◆ 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");
335  Assert(blockSize <= MEMORYCHUNK_MAX_BLOCKOFFSET);
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  {
368  ereport(ERROR,
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,
416  MCTX_SLAB_ID,
417  parent,
418  name);
419 
420  return (MemoryContext) slab;
421 }
static void dclist_init(dclist_head *head)
Definition: ilist.h:671
int i
Definition: isn.c:73
@ MCTX_SLAB_ID
elog(ERROR, "unexpected alloc chunk size %zu (expected %u)", size, slab->chunkSize)
#define Slab_BLOCKHDRSZ
Definition: slab.c:77
#define Slab_CHUNKHDRSZ
Definition: slab.c:157
struct SlabContext SlabContext
#define Slab_CONTEXT_HDRSZ(chunksPerBlock)
Definition: slab.c:88
#define SLAB_BLOCKLIST_COUNT
Definition: slab.c:95
dlist_head blocklist[SLAB_BLOCKLIST_COUNT]
Definition: slab.c:129
int32 chunksPerBlock
Definition: slab.c:110
uint32 fullChunkSize
Definition: slab.c:108
uint32 blockSize
Definition: slab.c:109
int32 curBlocklistIndex
Definition: slab.c:111
int32 blocklist_shift
Definition: slab.c:118
uint32 chunkSize
Definition: slab.c:107
dclist_head emptyblocks
Definition: slab.c:120

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(), and ReorderBufferAllocate().

Variable Documentation

◆ CacheMemoryContext

PGDLLIMPORT MemoryContext CacheMemoryContext
extern

Definition at line 152 of file mcxt.c.

Referenced by _SPI_save_plan(), AllocateRelationDesc(), assign_record_type_typmod(), AttrDefaultFetch(), BuildEventTriggerCache(), BuildHardcodedDescriptor(), CatalogCacheCreateEntry(), CatalogCacheInitializeCache(), CheckConstraintFetch(), CreateCacheMemoryContext(), ensure_record_cache_typmod_slot_exists(), FetchTableStates(), generate_partition_qual(), get_attribute_options(), get_rel_sync_entry(), get_tablespace(), GetCachedExpression(), GetCachedPlan(), GetFdwRoutineForRelation(), init_ts_config_cache(), init_tuple_slot(), InitCatCache(), InitializeAttoptCache(), InitializeRelfilenumberMap(), InitializeTableSpaceCache(), load_domaintype_info(), load_enum_cache_data(), load_rangetype_info(), load_relcache_init_file(), logicalrep_partmap_init(), logicalrep_relmap_init(), lookup_ts_config_cache(), lookup_ts_dictionary_cache(), lookup_ts_parser_cache(), lookup_type_cache(), LookupOpclassInfo(), pgoutput_startup(), register_on_commit_action(), RehashCatCache(), RehashCatCacheLists(), RelationBuildLocalRelation(), RelationBuildPartitionDesc(), RelationBuildPartitionKey(), RelationBuildPublicationDesc(), RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationBuildTupleDesc(), RelationCacheInitialize(), RelationCacheInitializePhase2(), RelationCacheInitializePhase3(), RelationGetFKeyList(), RelationGetIdentityKeyBitmap(), RelationGetIndexAttrBitmap(), RelationGetIndexList(), RelationGetStatExtList(), RelationInitIndexAccessInfo(), RelationParseRelOptions(), RememberToFreeTupleDescAtEOX(), SaveCachedPlan(), SearchCatCacheList(), set_schema_sent_in_streamed_txn(), SPI_keepplan(), and UploadManifest().

◆ CurTransactionContext

◆ ErrorContext

◆ MessageContext

◆ PortalContext

◆ PostmasterContext

◆ TopMemoryContext

PGDLLIMPORT MemoryContext TopMemoryContext
extern

Definition at line 149 of file mcxt.c.

Referenced by _PG_init(), add_reloption(), allocate_reloption(), AllocateAttribute(), AllocSetContextCreateInternal(), ApplyLauncherMain(), AtAbort_Memory(), AtCleanup_Memory(), AtCommit_Memory(), AtStart_Memory(), AttachSession(), BackendInitialize(), BackendMain(), BackgroundWorkerMain(), BackgroundWriterMain(), BaseBackupAddTarget(), be_tls_open_server(), build_guc_variables(), BumpContextCreate(), cache_single_string(), check_foreign_key(), check_primary_key(), CheckMyDatabase(), CheckpointerMain(), ClientAuthentication(), compile_plperl_function(), compile_pltcl_function(), CreateCacheMemoryContext(), CreateWaitEventSet(), dblink_connect(), dblink_init(), DCH_cache_getnew(), do_autovacuum(), do_compile(), dsm_create_descriptor(), dsm_impl_sysv(), EnablePortalManager(), EventTriggerBeginCompleteQuery(), Exec_ListenCommit(), executeDateTimeMethod(), find_plan(), finish_xact_command(), GenerationContextCreate(), GetLocalBufferStorage(), GetLockConflicts(), getmissingattr(), GetNamedDSMSegment(), GetSessionDsmHandle(), HandleParallelApplyMessages(), HandleParallelMessages(), hash_create(), init_missing_cache(), init_string_reloption(), InitDeadLockChecking(), initialize_reloptions(), initialize_target_list(), InitializeClientEncoding(), InitializeLogRepWorker(), InitializeParallelDSM(), InitializeSearchPath(), InitializeSession(), InitializeSystemUser(), InitSync(), InitXLogInsert(), llvm_compile_module(), llvm_create_context(), llvm_session_initialize(), LockAcquireExtended(), logicalrep_launcher_attach_dshmem(), LogicalRepApplyLoop(), LWLockRegisterTranche(), make_icu_collator(), mdinit(), MemoryContextAllocationFailure(), MemoryContextDeleteOnly(), MemoryContextInit(), mxid_to_string(), newLOfd(), NUM_cache_getnew(), on_dsm_detach(), PageSetChecksumCopy(), ParallelWorkerMain(), PerformAuthentication(), pg_backup_start(), pg_get_backend_memory_contexts(), pg_newlocale_from_collation(), PgArchiverMain(), pgstat_attach_shmem(), pgstat_prep_pending_entry(), pgstat_prep_snapshot(), pgstat_setup_backend_status_context(), pgstat_setup_memcxt(), plperl_spi_prepare(), plpython3_inline_handler(), plsample_func_handler(), pltcl_SPI_prepare(), PLy_cursor_plan(), PLy_cursor_query(), PLy_procedure_create(), PLy_spi_execute_fetch_result(), PLy_spi_prepare(), populate_typ_list(), PostgresMain(), postmaster_child_launch(), PostmasterMain(), pq_init(), PrepareClientEncoding(), ProcessLogMemoryContextInterrupt(), ProcessStartupPacket(), px_find_cipher(), px_find_digest(), RE_compile_and_cache(), recomputeNamespacePath(), register_label_provider(), RegisterResourceReleaseCallback(), RegisterSubXactCallback(), RegisterXactCallback(), RelationCreateStorage(), RelationDropStorage(), RequestNamedLWLockTranche(), ResourceOwnerCreate(), ResourceOwnerEnlarge(), RestoreClientConnectionInfo(), RestoreReindexState(), ri_HashCompareOp(), roles_is_member_of(), secure_open_gssapi(), sepgsql_avc_init(), sepgsql_xact_callback(), set_authn_id(), SetDatabasePath(), SharedRecordTypmodRegistryAttach(), SharedRecordTypmodRegistryInit(), SlabContextCreate(), SPI_connect_ext(), test_create(), WalSummarizerMain(), WalWriterMain(), and XLOGShmemInit().

◆ TopTransactionContext