PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
memutils.h File Reference
#include "nodes/memnodes.h"
#include "storage/condition_variable.h"
#include "storage/lmgr.h"
#include "utils/dsa.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.

Data Structures

struct  MemoryStatsEntry
 
struct  MemoryStatsCtl
 
struct  MemoryStatsBackendState
 
struct  MemoryStatsContextId
 

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 MEMORY_CONTEXT_IDENT_SHMEM_SIZE   64
 
#define MEMORY_CONTEXT_REPORT_MAX_PER_BACKEND   ((size_t) (1 * 1024 * 1024))
 
#define MAX_MEMORY_CONTEXT_STATS_SIZE
 
#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)
 

Typedefs

typedef struct MemoryStatsEntry MemoryStatsEntry
 
typedef struct MemoryStatsCtl MemoryStatsCtl
 
typedef struct MemoryStatsBackendState MemoryStatsBackendState
 
typedef struct MemoryStatsContextId MemoryStatsContextId
 

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)
 
static bool pg_memory_is_all_zeros (const void *ptr, size_t len)
 
void ProcessGetMemoryContextInterrupt (void)
 
const char * ContextTypeToString (NodeTag type)
 
void HandleGetMemoryContextInterrupt (void)
 
Size MemoryContextReportingShmemSize (void)
 
void MemoryContextReportingShmemInit (void)
 
void AtProcExit_memstats_cleanup (int code, Datum arg)
 

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
 
PGDLLIMPORT MemoryStatsBackendStatememCxtState
 
PGDLLIMPORT MemoryStatsCtlmemCxtArea
 
PGDLLIMPORT dsa_areaMemoryStatsDsaArea
 

Macro Definition Documentation

◆ AllocHugeSizeIsValid

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

Definition at line 52 of file memutils.h.

◆ ALLOCSET_DEFAULT_INITSIZE

#define ALLOCSET_DEFAULT_INITSIZE   (8 * 1024)

Definition at line 178 of file memutils.h.

◆ ALLOCSET_DEFAULT_MAXSIZE

#define ALLOCSET_DEFAULT_MAXSIZE   (8 * 1024 * 1024)

Definition at line 179 of file memutils.h.

◆ ALLOCSET_DEFAULT_MINSIZE

#define ALLOCSET_DEFAULT_MINSIZE   0

Definition at line 177 of file memutils.h.

◆ ALLOCSET_DEFAULT_SIZES

Definition at line 180 of file memutils.h.

◆ ALLOCSET_SEPARATE_THRESHOLD

#define ALLOCSET_SEPARATE_THRESHOLD   8192

Definition at line 207 of file memutils.h.

◆ ALLOCSET_SMALL_INITSIZE

#define ALLOCSET_SMALL_INITSIZE   (1 * 1024)

Definition at line 188 of file memutils.h.

◆ ALLOCSET_SMALL_MAXSIZE

#define ALLOCSET_SMALL_MAXSIZE   (8 * 1024)

Definition at line 189 of file memutils.h.

◆ ALLOCSET_SMALL_MINSIZE

#define ALLOCSET_SMALL_MINSIZE   0

Definition at line 187 of file memutils.h.

◆ ALLOCSET_SMALL_SIZES

Definition at line 190 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 197 of file memutils.h.

◆ AllocSetContextCreate

#define AllocSetContextCreate    AllocSetContextCreateInternal

Definition at line 149 of file memutils.h.

◆ AllocSizeIsValid

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

Definition at line 45 of file memutils.h.

◆ InvalidAllocSize

#define InvalidAllocSize   SIZE_MAX

Definition at line 50 of file memutils.h.

◆ MAX_MEMORY_CONTEXT_STATS_SIZE

#define MAX_MEMORY_CONTEXT_STATS_SIZE
Value:
(sizeof(MemoryStatsEntry) + \
(100 * sizeof(int)) + (2 * MEMORY_CONTEXT_IDENT_SHMEM_SIZE))
#define MEMORY_CONTEXT_IDENT_SHMEM_SIZE
Definition: memutils.h:59
struct MemoryStatsEntry MemoryStatsEntry

Definition at line 69 of file memutils.h.

◆ MaxAllocHugeSize

#define MaxAllocHugeSize   (SIZE_MAX / 2)

Definition at line 48 of file memutils.h.

◆ MaxAllocSize

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

Definition at line 43 of file memutils.h.

◆ MEMORY_CONTEXT_IDENT_SHMEM_SIZE

#define MEMORY_CONTEXT_IDENT_SHMEM_SIZE   64

Definition at line 59 of file memutils.h.

◆ MEMORY_CONTEXT_REPORT_MAX_PER_BACKEND

#define MEMORY_CONTEXT_REPORT_MAX_PER_BACKEND   ((size_t) (1 * 1024 * 1024))

Definition at line 61 of file memutils.h.

◆ MemoryContextCopyAndSetIdentifier

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

Definition at line 121 of file memutils.h.

◆ SLAB_DEFAULT_BLOCK_SIZE

#define SLAB_DEFAULT_BLOCK_SIZE   (8 * 1024)

Definition at line 209 of file memutils.h.

◆ SLAB_LARGE_BLOCK_SIZE

#define SLAB_LARGE_BLOCK_SIZE   (8 * 1024 * 1024)

Definition at line 210 of file memutils.h.

Typedef Documentation

◆ MemoryStatsBackendState

◆ MemoryStatsContextId

◆ MemoryStatsCtl

◆ MemoryStatsEntry

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,
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 {
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,
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
#define MAXALIGN(LEN)
Definition: c.h:782
#define Max(x, y)
Definition: c.h:969
#define MemSetAligned(start, val, len)
Definition: c.h:1021
uint32_t uint32
Definition: c.h:502
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:907
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:909
size_t Size
Definition: c.h:576
int errdetail(const char *fmt,...)
Definition: elog.c:1204
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
Assert(PointerIsAligned(start, uint64))
#define malloc(a)
Definition: header.h:50
void MemoryContextCreate(MemoryContext node, NodeTag tag, MemoryContextMethodID method_id, MemoryContext parent, const char *name)
Definition: mcxt.c:1175
MemoryContext TopMemoryContext
Definition: mcxt.c:165
void MemoryContextStats(MemoryContext context)
Definition: mcxt.c:845
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
Definition: memdebug.h:27
#define ALLOCSET_SMALL_MINSIZE
Definition: memutils.h:187
#define ALLOCSET_DEFAULT_MINSIZE
Definition: memutils.h:177
#define AllocHugeSizeIsValid(size)
Definition: memutils.h:52
#define ALLOCSET_SEPARATE_THRESHOLD
Definition: memutils.h:207
#define ALLOCSET_SMALL_INITSIZE
Definition: memutils.h:188
#define ALLOCSET_DEFAULT_INITSIZE
Definition: memutils.h:178
@ 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.

◆ AtProcExit_memstats_cleanup()

void AtProcExit_memstats_cleanup ( int  code,
Datum  arg 
)

Definition at line 1908 of file mcxt.c.

1909{
1910 int idx = MyProcNumber;
1911
1913 return;
1914
1916
1917 if (!DsaPointerIsValid(memCxtState[idx].memstats_dsa_pointer))
1918 {
1919 LWLockRelease(&memCxtState[idx].lw_lock);
1920 return;
1921 }
1922
1923 /* If the dsa mapping could not be found, attach to the area */
1924 if (MemoryStatsDsaArea == NULL)
1926
1927 /*
1928 * Free the memory context statistics, free the name, ident and path
1929 * pointers before freeing the pointer that contains these pointers and
1930 * integer statistics.
1931 */
1933 memCxtState[idx].memstats_dsa_pointer);
1934
1936 LWLockRelease(&memCxtState[idx].lw_lock);
1937}
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:262
dsa_area * dsa_attach(dsa_handle handle)
Definition: dsa.c:510
void dsa_detach(dsa_area *area)
Definition: dsa.c:1952
#define DSA_HANDLE_INVALID
Definition: dsa.h:139
#define DsaPointerIsValid(x)
Definition: dsa.h:106
ProcNumber MyProcNumber
Definition: globals.c:91
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1182
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1902
@ LW_EXCLUSIVE
Definition: lwlock.h:114
static void free_memorycontextstate_dsa(dsa_area *area, int total_stats, dsa_pointer prev_dsa_pointer)
Definition: mcxt.c:1880
dsa_area * MemoryStatsDsaArea
Definition: mcxt.c:175
struct MemoryStatsBackendState * memCxtState
Definition: mcxtfuncs.c:37
struct MemoryStatsCtl * memCxtArea
Definition: mcxtfuncs.c:38
dsa_handle memstats_dsa_handle
Definition: memutils.h:366

References dsa_attach(), dsa_detach(), DSA_HANDLE_INVALID, DsaPointerIsValid, free_memorycontextstate_dsa(), idx(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), memCxtArea, memCxtState, MemoryStatsDsaArea, MemoryStatsCtl::memstats_dsa_handle, and MyProcNumber.

Referenced by BaseInit().

◆ 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 {
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:975
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 hash_create_memory(), TidStoreCreateLocal(), and tuplesort_begin_batch().

◆ ContextTypeToString()

const char * ContextTypeToString ( NodeTag  type)

Definition at line 165 of file mcxtfuncs.c.

166{
167 const char *context_type;
168
169 switch (type)
170 {
171 case T_AllocSetContext:
172 context_type = "AllocSet";
173 break;
174 case T_GenerationContext:
175 context_type = "Generation";
176 break;
177 case T_SlabContext:
178 context_type = "Slab";
179 break;
180 case T_BumpContext:
181 context_type = "Bump";
182 break;
183 default:
184 context_type = "???";
185 break;
186 }
187 return context_type;
188}
const char * type

References type.

Referenced by pg_get_process_memory_contexts(), and PutMemoryContextsStatsTupleStore().

◆ 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;
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 {
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) >
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(), ReorderBufferAllocate(), and tuplestore_begin_common().

◆ GetMemoryChunkContext()

MemoryContext GetMemoryChunkContext ( void *  pointer)

◆ GetMemoryChunkSpace()

◆ HandleGetMemoryContextInterrupt()

void HandleGetMemoryContextInterrupt ( void  )

Definition at line 1363 of file mcxt.c.

1364{
1365 InterruptPending = true;
1367 /* latch will be set by procsignal_sigusr1_handler */
1368}
volatile sig_atomic_t InterruptPending
Definition: globals.c:32
volatile sig_atomic_t PublishMemoryContextPending
Definition: globals.c:42

References InterruptPending, and PublishMemoryContextPending.

Referenced by procsignal_sigusr1_handler().

◆ HandleLogMemoryContextInterrupt()

void HandleLogMemoryContextInterrupt ( void  )

Definition at line 1347 of file mcxt.c.

1348{
1349 InterruptPending = true;
1351 /* latch will be set by procsignal_sigusr1_handler */
1352}
volatile sig_atomic_t LogMemoryContextPending
Definition: globals.c:41

References InterruptPending, and LogMemoryContextPending.

Referenced by procsignal_sigusr1_handler().

◆ MemoryContextAllowInCriticalSection()

void MemoryContextAllowInCriticalSection ( MemoryContext  context,
bool  allow 
)

Definition at line 725 of file mcxt.c.

726{
728
729 context->allowInCritSection = allow;
730}
#define MemoryContextIsValid(context)
Definition: memnodes.h:145
bool allowInCritSection
Definition: memnodes.h:124

References MemoryContextData::allowInCritSection, Assert(), and MemoryContextIsValid.

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

◆ MemoryContextDelete()

void MemoryContextDelete ( MemoryContext  context)

Definition at line 485 of file mcxt.c.

486{
487 MemoryContext curr;
488
490
491 /*
492 * Delete subcontexts from the bottom up.
493 *
494 * Note: Do not use recursion here. A "stack depth limit exceeded" error
495 * would be unpleasant if we're already in the process of cleaning up from
496 * transaction abort. We also cannot use MemoryContextTraverseNext() here
497 * because we modify the tree as we go.
498 */
499 curr = context;
500 for (;;)
501 {
502 MemoryContext parent;
503
504 /* Descend down until we find a leaf context with no children */
505 while (curr->firstchild != NULL)
506 curr = curr->firstchild;
507
508 /*
509 * We're now at a leaf with no children. Free it and continue from the
510 * parent. Or if this was the original node, we're all done.
511 */
512 parent = curr->parent;
514
515 if (curr == context)
516 break;
517 curr = parent;
518 }
519}
static void MemoryContextDeleteOnly(MemoryContext context)
Definition: mcxt.c:527
MemoryContext firstchild
Definition: memnodes.h:128
MemoryContext parent
Definition: memnodes.h:127

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

Referenced by _brin_parallel_merge(), AfterTriggerEndXact(), afterTriggerInvokeEvents(), ApplyLauncherMain(), AtEOSubXact_SPI(), AtEOXact_LargeObject(), AtSubCleanup_Memory(), AtSubCommit_Memory(), AttachPartitionEnsureIndexes(), AutoVacLauncherMain(), 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(), 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_check_parent_keys_consistency(), gin_check_posting_tree_parent_keys_consistency(), 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_cursor_plan(), PLy_plan_dealloc(), PLy_pop_execution_context(), PLy_procedure_delete(), PLy_spi_execute_fetch_result(), PLy_spi_execute_plan(), PortalDrop(), PostgresMain(), postquel_end(), prepare_next_query(), printtup_shutdown(), ProcessConfigFile(), 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(), sql_delete_callback(), statext_dependencies_build(), strlist_to_textarray(), SysLoggerMain(), test_pattern(), TidStoreDestroy(), tokenize_auth_file(), tuplesort_end(), tuplestore_end(), union_tuples(), UploadManifest(), and validateForeignKeyConstraint().

◆ MemoryContextDeleteChildren()

void MemoryContextDeleteChildren ( MemoryContext  context)

Definition at line 570 of file mcxt.c.

571{
573
574 /*
575 * MemoryContextDelete will delink the child from me, so just iterate as
576 * long as there is a child.
577 */
578 while (context->firstchild != NULL)
580}
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:485

References Assert(), MemoryContextData::firstchild, 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 370 of file mcxt.c.

371{
372 Assert(TopMemoryContext == NULL);
373
374 /*
375 * First, initialize TopMemoryContext, which is the parent of all others.
376 */
378 "TopMemoryContext",
380
381 /*
382 * Not having any other place to point CurrentMemoryContext, make it point
383 * to TopMemoryContext. Caller should change this soon!
384 */
386
387 /*
388 * Initialize ErrorContext as an AllocSetContext with slow growth rate ---
389 * we don't really expect much to be allocated in it. More to the point,
390 * require it to contain at least 8K at all times. This is the only case
391 * where retained memory in a context is *essential* --- we want to be
392 * sure ErrorContext still has some memory even if we've run out
393 * elsewhere! Also, allow allocations in ErrorContext within a critical
394 * section. Otherwise a PANIC will cause an assertion failure in the error
395 * reporting code, before printing out the real cause of the failure.
396 *
397 * This should be the last step in this function, as elog.c assumes memory
398 * management works once ErrorContext is non-null.
399 */
401 "ErrorContext",
402 8 * 1024,
403 8 * 1024,
404 8 * 1024);
406}
MemoryContext CurrentMemoryContext
Definition: mcxt.c:159
MemoryContext ErrorContext
Definition: mcxt.c:166
void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
Definition: mcxt.c:725
#define AllocSetContextCreate
Definition: memutils.h:149
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:180

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

Referenced by main().

◆ MemoryContextIsEmpty()

bool MemoryContextIsEmpty ( MemoryContext  context)

Definition at line 774 of file mcxt.c.

775{
777
778 /*
779 * For now, we consider a memory context nonempty if it has any children;
780 * perhaps this should be changed later.
781 */
782 if (context->firstchild != NULL)
783 return false;
784 /* Otherwise use the type-specific inquiry */
785 return context->methods->is_empty(context);
786}
const MemoryContextMethods * methods
Definition: memnodes.h:126
bool(* is_empty)(MemoryContext context)
Definition: memnodes.h:101

References Assert(), MemoryContextData::firstchild, MemoryContextMethods::is_empty, MemoryContextIsValid, and MemoryContextData::methods.

Referenced by AtSubCommit_Memory().

◆ MemoryContextMemAllocated()

Size MemoryContextMemAllocated ( MemoryContext  context,
bool  recurse 
)

Definition at line 793 of file mcxt.c.

794{
795 Size total = context->mem_allocated;
796
798
799 if (recurse)
800 {
801 for (MemoryContext curr = context->firstchild;
802 curr != NULL;
803 curr = MemoryContextTraverseNext(curr, context))
804 {
805 total += curr->mem_allocated;
806 }
807 }
808
809 return total;
810}
static MemoryContext MemoryContextTraverseNext(MemoryContext curr, MemoryContext top)
Definition: mcxt.c:288

References Assert(), MemoryContextData::firstchild, MemoryContextData::mem_allocated, 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 817 of file mcxt.c.

819{
821
822 memset(consumed, 0, sizeof(*consumed));
823
824 /* Examine the context itself */
825 context->methods->stats(context, NULL, NULL, consumed, false);
826
827 /* Examine children, using iteration not recursion */
828 for (MemoryContext curr = context->firstchild;
829 curr != NULL;
830 curr = MemoryContextTraverseNext(curr, context))
831 {
832 curr->methods->stats(curr, NULL, NULL, consumed, false);
833 }
834}
void(* stats)(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
Definition: memnodes.h:102

References Assert(), MemoryContextData::firstchild, MemoryContextIsValid, MemoryContextTraverseNext(), MemoryContextData::methods, and MemoryContextMethods::stats.

Referenced by ExplainExecuteQuery(), and standard_ExplainOneQuery().

◆ MemoryContextReportingShmemInit()

void MemoryContextReportingShmemInit ( void  )

Definition at line 637 of file mcxtfuncs.c.

638{
639 bool found;
640
642 ShmemInitStruct("MemoryStatsCtl",
643 sizeof(MemoryStatsCtl), &found);
644
645 if (!found)
646 {
649 }
650
652 ShmemInitStruct("MemoryStatsBackendState",
654 &found);
655
656 if (found)
657 return;
658
659 for (int i = 0; i < (MaxBackends + NUM_AUXILIARY_PROCS); i++)
660 {
664 }
665}
void ConditionVariableInit(ConditionVariable *cv)
#define InvalidDsaPointer
Definition: dsa.h:78
int MaxBackends
Definition: globals.c:147
int i
Definition: isn.c:77
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:721
@ LWTRANCHE_MEMORY_CONTEXT_REPORTING_PROC
Definition: lwlock.h:225
@ LWTRANCHE_MEMORY_CONTEXT_REPORTING_STATE
Definition: lwlock.h:224
#define NUM_AUXILIARY_PROCS
Definition: proc.h:447
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
dsa_pointer memstats_dsa_pointer
Definition: memutils.h:381
LWLock lw_lock
Definition: memutils.h:367

References ConditionVariableInit(), DSA_HANDLE_INVALID, i, InvalidDsaPointer, MemoryStatsCtl::lw_lock, LWLockInitialize(), LWTRANCHE_MEMORY_CONTEXT_REPORTING_PROC, LWTRANCHE_MEMORY_CONTEXT_REPORTING_STATE, MaxBackends, memCxtArea, memCxtState, MemoryStatsCtl::memstats_dsa_handle, MemoryStatsBackendState::memstats_dsa_pointer, NUM_AUXILIARY_PROCS, and ShmemInitStruct().

Referenced by CreateOrAttachShmemStructs().

◆ MemoryContextReportingShmemSize()

Size MemoryContextReportingShmemSize ( void  )

Definition at line 619 of file mcxtfuncs.c.

620{
621 Size sz = 0;
622 Size TotalProcs = 0;
623
624 TotalProcs = add_size(TotalProcs, NUM_AUXILIARY_PROCS);
625 TotalProcs = add_size(TotalProcs, MaxBackends);
626 sz = add_size(sz, mul_size(TotalProcs, sizeof(MemoryStatsBackendState)));
627
628 sz = add_size(sz, sizeof(MemoryStatsCtl));
629
630 return sz;
631}
Size add_size(Size s1, Size s2)
Definition: shmem.c:493
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510

References add_size(), MaxBackends, mul_size(), and NUM_AUXILIARY_PROCS.

Referenced by CalculateShmemSize().

◆ MemoryContextReset()

void MemoryContextReset ( MemoryContext  context)

Definition at line 414 of file mcxt.c.

415{
417
418 /* save a function call in common case where there are no children */
419 if (context->firstchild != NULL)
421
422 /* save a function call if no pallocs since startup or last reset */
423 if (!context->isReset)
424 MemoryContextResetOnly(context);
425}
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:570
void MemoryContextResetOnly(MemoryContext context)
Definition: mcxt.c:433

References Assert(), MemoryContextData::firstchild, MemoryContextData::isReset, MemoryContextDeleteChildren(), MemoryContextIsValid, and MemoryContextResetOnly().

Referenced by _brin_parallel_merge(), _bt_preprocess_array_keys(), _SPI_end_call(), AfterTriggerExecute(), agg_refill_hash_table(), apply_spooled_messages(), AtCleanup_Memory(), AtCommit_Memory(), AtEOSubXact_SPI(), AtSubCleanup_Memory(), AutoVacLauncherMain(), 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(), ExecReScanAgg(), ExecReScanRecursiveUnion(), ExecReScanSetOp(), execTuplesUnequal(), execute_foreign_modify(), expanded_record_set_field_internal(), expanded_record_set_tuple(), fetch_more_data(), file_acquire_sample_rows(), FlushErrorState(), get_rel_sync_entry(), get_short_term_cxt(), GetWALRecordsInfo(), GetXLogSummaryStats(), gin_redo(), ginBuildCallback(), ginFlushBuildState(), ginFreeScanKeys(), ginHeapTupleBulkInsert(), ginInsertCleanup(), ginVacuumPostingTreeLeaves(), gist_indexsortbuild(), gist_redo(), gistBuildCallback(), gistgetbitmap(), gistgettuple(), gistinsert(), gistProcessEmptyingQueue(), gistrescan(), gistScanPage(), gistSortedBuildCallback(), heapam_index_build_range_scan(), heapam_index_validate_scan(), IndexCheckExclusion(), init_execution_state(), 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(), ProcessParallelApplyMessages(), ProcessParallelMessages(), 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(), tuplestore_clear(), UpdateCachedPlan(), validateForeignKeyConstraint(), WalSummarizerMain(), and WalWriterMain().

◆ MemoryContextResetChildren()

void MemoryContextResetChildren ( MemoryContext  context)

Definition at line 464 of file mcxt.c.

465{
467
468 for (MemoryContext curr = context->firstchild;
469 curr != NULL;
470 curr = MemoryContextTraverseNext(curr, context))
471 {
473 }
474}

References Assert(), MemoryContextData::firstchild, MemoryContextIsValid, MemoryContextResetOnly(), and MemoryContextTraverseNext().

◆ MemoryContextResetOnly()

void MemoryContextResetOnly ( MemoryContext  context)

Definition at line 433 of file mcxt.c.

434{
436
437 /* Nothing to do if no pallocs since startup or last reset */
438 if (!context->isReset)
439 {
441
442 /*
443 * If context->ident points into the context's memory, it will become
444 * a dangling pointer. We could prevent that by setting it to NULL
445 * here, but that would break valid coding patterns that keep the
446 * ident elsewhere, e.g. in a parent context. So for now we assume
447 * the programmer got it right.
448 */
449
450 context->methods->reset(context);
451 context->isReset = true;
453 VALGRIND_CREATE_MEMPOOL(context, 0, false);
454 }
455}
static void MemoryContextCallResetCallbacks(MemoryContext context)
Definition: mcxt.c:616
#define VALGRIND_DESTROY_MEMPOOL(context)
Definition: memdebug.h:25
#define VALGRIND_CREATE_MEMPOOL(context, redzones, zeroed)
Definition: memdebug.h:24
void(* reset)(MemoryContext context)
Definition: memnodes.h:83

References Assert(), MemoryContextData::isReset, MemoryContextCallResetCallbacks(), MemoryContextIsValid, MemoryContextData::methods, MemoryContextMethods::reset, 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 668 of file mcxt.c.

669{
671 Assert(context != new_parent);
672
673 /* Fast path if it's got correct parent already */
674 if (new_parent == context->parent)
675 return;
676
677 /* Delink from existing parent, if any */
678 if (context->parent)
679 {
680 MemoryContext parent = context->parent;
681
682 if (context->prevchild != NULL)
683 context->prevchild->nextchild = context->nextchild;
684 else
685 {
686 Assert(parent->firstchild == context);
687 parent->firstchild = context->nextchild;
688 }
689
690 if (context->nextchild != NULL)
691 context->nextchild->prevchild = context->prevchild;
692 }
693
694 /* And relink */
695 if (new_parent)
696 {
697 Assert(MemoryContextIsValid(new_parent));
698 context->parent = new_parent;
699 context->prevchild = NULL;
700 context->nextchild = new_parent->firstchild;
701 if (new_parent->firstchild != NULL)
702 new_parent->firstchild->prevchild = context;
703 new_parent->firstchild = context;
704 }
705 else
706 {
707 context->parent = NULL;
708 context->prevchild = NULL;
709 context->nextchild = NULL;
710 }
711}
MemoryContext prevchild
Definition: memnodes.h:129

References Assert(), MemoryContextData::firstchild, MemoryContextIsValid, MemoryContextData::nextchild, MemoryContextData::parent, and MemoryContextData::prevchild.

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

◆ MemoryContextStats()

void MemoryContextStats ( MemoryContext  context)

Definition at line 845 of file mcxt.c.

846{
847 /* Hard-wired limits are usually good enough */
848 MemoryContextStatsDetail(context, 100, 100, true);
849}
void MemoryContextStatsDetail(MemoryContext context, int max_level, int max_children, bool print_to_stderr)
Definition: mcxt.c:860

References 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 860 of file mcxt.c.

863{
864 MemoryContextCounters grand_totals;
865 int num_contexts;
866 PrintDestination print_location;
867
868 memset(&grand_totals, 0, sizeof(grand_totals));
869
870 if (print_to_stderr)
871 print_location = PRINT_STATS_TO_STDERR;
872 else
873 print_location = PRINT_STATS_TO_LOGS;
874
875 /* num_contexts report number of contexts aggregated in the output */
876 MemoryContextStatsInternal(context, 0, max_level, max_children,
877 &grand_totals, print_location, &num_contexts);
878
879 if (print_to_stderr)
880 fprintf(stderr,
881 "Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used\n",
882 grand_totals.totalspace, grand_totals.nblocks,
883 grand_totals.freespace, grand_totals.freechunks,
884 grand_totals.totalspace - grand_totals.freespace);
885 else
886 {
887 /*
888 * Use LOG_SERVER_ONLY to prevent the memory contexts from being sent
889 * to the connected client.
890 *
891 * We don't buffer the information about all memory contexts in a
892 * backend into StringInfo and log it as one message. That would
893 * require the buffer to be enlarged, risking an OOM as there could be
894 * a large number of memory contexts in a backend. Instead, we log
895 * one message per memory context.
896 */
898 (errhidestmt(true),
899 errhidecontext(true),
900 errmsg_internal("Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used",
901 grand_totals.totalspace, grand_totals.nblocks,
902 grand_totals.freespace, grand_totals.freechunks,
903 grand_totals.totalspace - grand_totals.freespace)));
904 }
905}
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1158
int errhidestmt(bool hide_stmt)
Definition: elog.c:1433
int errhidecontext(bool hide_ctx)
Definition: elog.c:1452
#define LOG_SERVER_ONLY
Definition: elog.h:32
PrintDestination
Definition: mcxt.c:149
@ PRINT_STATS_TO_LOGS
Definition: mcxt.c:151
@ PRINT_STATS_TO_STDERR
Definition: mcxt.c:150
static void MemoryContextStatsInternal(MemoryContext context, int level, int max_level, int max_children, MemoryContextCounters *totals, PrintDestination print_location, int *num_contexts)
Definition: mcxt.c:916

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

Referenced by MemoryContextStats(), and ProcessLogMemoryContextInterrupt().

◆ pg_memory_is_all_zeros()

static bool pg_memory_is_all_zeros ( const void *  ptr,
size_t  len 
)
inlinestatic

Definition at line 239 of file memutils.h.

240{
241 const unsigned char *p = (const unsigned char *) ptr;
242 const unsigned char *end = &p[len];
243 const unsigned char *aligned_end = (const unsigned char *)
244 ((uintptr_t) end & (~(sizeof(size_t) - 1)));
245
246 if (len < sizeof(size_t))
247 {
248 while (p < end)
249 {
250 if (*p++ != 0)
251 return false;
252 }
253 return true;
254 }
255
256 /* "len" in the [sizeof(size_t), sizeof(size_t) * 8 - 1] range */
257 if (len < sizeof(size_t) * 8)
258 {
259 /* Compare bytes until the pointer "p" is aligned */
260 while (((uintptr_t) p & (sizeof(size_t) - 1)) != 0)
261 {
262 if (p == end)
263 return true;
264 if (*p++ != 0)
265 return false;
266 }
267
268 /*
269 * Compare remaining size_t-aligned chunks.
270 *
271 * There is no risk to read beyond the memory area, as "aligned_end"
272 * cannot be higher than "end".
273 */
274 for (; p < aligned_end; p += sizeof(size_t))
275 {
276 if (*(size_t *) p != 0)
277 return false;
278 }
279
280 /* Compare remaining bytes until the end */
281 while (p < end)
282 {
283 if (*p++ != 0)
284 return false;
285 }
286 return true;
287 }
288
289 /* "len" in the [sizeof(size_t) * 8, inf) range */
290
291 /* Compare bytes until the pointer "p" is aligned */
292 while (((uintptr_t) p & (sizeof(size_t) - 1)) != 0)
293 {
294 if (p == end)
295 return true;
296
297 if (*p++ != 0)
298 return false;
299 }
300
301 /*
302 * Compare 8 * sizeof(size_t) chunks at once.
303 *
304 * For performance reasons, we manually unroll this loop and purposefully
305 * use bitwise-ORs to combine each comparison. This prevents boolean
306 * short-circuiting and lets the compiler know that it's safe to access
307 * all 8 elements regardless of the result of the other comparisons. This
308 * seems to be enough to coax a few compilers into using SIMD
309 * instructions.
310 */
311 for (; p < aligned_end - (sizeof(size_t) * 7); p += sizeof(size_t) * 8)
312 {
313 if ((((size_t *) p)[0] != 0) | (((size_t *) p)[1] != 0) |
314 (((size_t *) p)[2] != 0) | (((size_t *) p)[3] != 0) |
315 (((size_t *) p)[4] != 0) | (((size_t *) p)[5] != 0) |
316 (((size_t *) p)[6] != 0) | (((size_t *) p)[7] != 0))
317 return false;
318 }
319
320 /*
321 * Compare remaining size_t-aligned chunks.
322 *
323 * There is no risk to read beyond the memory area, as "aligned_end"
324 * cannot be higher than "end".
325 */
326 for (; p < aligned_end; p += sizeof(size_t))
327 {
328 if (*(size_t *) p != 0)
329 return false;
330 }
331
332 /* Compare remaining bytes until the end */
333 while (p < end)
334 {
335 if (*p++ != 0)
336 return false;
337 }
338
339 return true;
340}
const void size_t len

References len.

Referenced by PageIsVerified(), pg_stat_get_activity(), pg_stat_get_backend_client_addr(), pg_stat_get_backend_client_port(), pgstat_relation_flush_cb(), pgstat_report_bgwriter(), and pgstat_report_checkpointer().

◆ ProcessGetMemoryContextInterrupt()

void ProcessGetMemoryContextInterrupt ( void  )

Definition at line 1432 of file mcxt.c.

1433{
1434 List *contexts;
1435 HASHCTL ctl;
1436 HTAB *context_id_lookup;
1437 int context_id = 0;
1438 MemoryStatsEntry *meminfo;
1439 bool summary = false;
1440 int max_stats;
1441 int idx = MyProcNumber;
1442 int stats_count = 0;
1443 int stats_num = 0;
1445 int num_individual_stats = 0;
1446
1448
1449 /*
1450 * The hash table is used for constructing "path" column of the view,
1451 * similar to its local backend counterpart.
1452 */
1453 ctl.keysize = sizeof(MemoryContext);
1454 ctl.entrysize = sizeof(MemoryStatsContextId);
1456
1457 context_id_lookup = hash_create("pg_get_remote_backend_memory_contexts",
1458 256,
1459 &ctl,
1461
1462 /* List of contexts to process in the next round - start at the top. */
1463 contexts = list_make1(TopMemoryContext);
1464
1465 /* Compute the number of stats that can fit in the defined limit */
1466 max_stats =
1469 summary = memCxtState[idx].summary;
1470 LWLockRelease(&memCxtState[idx].lw_lock);
1471
1472 /*
1473 * Traverse the memory context tree to find total number of contexts. If
1474 * summary is requested report the total number of contexts at level 1 and
1475 * 2 from the top. Also, populate the hash table of context ids.
1476 */
1477 compute_contexts_count_and_ids(contexts, context_id_lookup, &stats_count,
1478 summary);
1479
1480 /*
1481 * Allocate memory in this process's DSA for storing statistics of the the
1482 * memory contexts upto max_stats, for contexts that don't fit within a
1483 * limit, a cumulative total is written as the last record in the DSA
1484 * segment.
1485 */
1486 stats_num = Min(stats_count, max_stats);
1487
1489
1490 /*
1491 * Create a DSA and send handle to the the client process after storing
1492 * the context statistics. If number of contexts exceed a predefined
1493 * limit(8MB), a cumulative total is stored for such contexts.
1494 */
1496 {
1498 dsa_handle handle;
1499
1501
1503
1505 MemoryContextSwitchTo(oldcontext);
1506
1508
1509 /*
1510 * Pin the DSA area, this is to make sure the area remains attachable
1511 * even if current backend exits. This is done so that the statistics
1512 * are published even if the process exits while a client is waiting.
1513 */
1515
1516 /* Set the handle in shared memory */
1518 }
1519
1520 /*
1521 * If DSA exists, created by another process publishing statistics, attach
1522 * to it.
1523 */
1524 else if (MemoryStatsDsaArea == NULL)
1525 {
1527
1530 MemoryContextSwitchTo(oldcontext);
1532 }
1534
1535 /*
1536 * Hold the process lock to protect writes to process specific memory. Two
1537 * processes publishing statistics do not block each other.
1538 */
1541
1542 if (DsaPointerIsValid(memCxtState[idx].memstats_dsa_pointer))
1543 {
1544 /*
1545 * Free any previous allocations, free the name, ident and path
1546 * pointers before freeing the pointer that contains them.
1547 */
1549 memCxtState[idx].memstats_dsa_pointer);
1550 }
1551
1552 /*
1553 * Assigning total stats before allocating memory so that memory cleanup
1554 * can run if any subsequent dsa_allocate call to allocate name/ident/path
1555 * fails.
1556 */
1557 memCxtState[idx].total_stats = stats_num;
1560
1561 meminfo = (MemoryStatsEntry *)
1562 dsa_get_address(MemoryStatsDsaArea, memCxtState[idx].memstats_dsa_pointer);
1563
1564 if (summary)
1565 {
1566 int cxt_id = 0;
1567 List *path = NIL;
1568
1569 /* Copy TopMemoryContext statistics to DSA */
1570 memset(&stat, 0, sizeof(stat));
1572 &stat, true);
1573 path = lcons_int(1, path);
1574 PublishMemoryContext(meminfo, cxt_id, TopMemoryContext, path, stat,
1575 1, MemoryStatsDsaArea, 100);
1576 cxt_id = cxt_id + 1;
1577
1578 /*
1579 * Copy statistics for each of TopMemoryContexts children. This
1580 * includes statistics of at most 100 children per node, with each
1581 * child node limited to a depth of 100 in its subtree.
1582 */
1583 for (MemoryContext c = TopMemoryContext->firstchild; c != NULL;
1584 c = c->nextchild)
1585 {
1586 MemoryContextCounters grand_totals;
1587 int num_contexts = 0;
1588 int level = 0;
1589
1590 path = NIL;
1591 memset(&grand_totals, 0, sizeof(grand_totals));
1592
1593 MemoryContextStatsInternal(c, level, 100, 100, &grand_totals,
1594 PRINT_STATS_NONE, &num_contexts);
1595
1596 path = compute_context_path(c, context_id_lookup);
1597
1598 /*
1599 * Register the stats entry first, that way the cleanup handler
1600 * can reach it in case of allocation failures of one or more
1601 * members.
1602 */
1603 memCxtState[idx].total_stats = cxt_id++;
1604 PublishMemoryContext(meminfo, cxt_id, c, path,
1605 grand_totals, num_contexts, MemoryStatsDsaArea, 100);
1606 }
1607 memCxtState[idx].total_stats = cxt_id;
1608
1610
1611 /* Notify waiting backends and return */
1612 hash_destroy(context_id_lookup);
1613
1614 return;
1615 }
1616
1618 {
1619 List *path = NIL;
1620
1621 /*
1622 * Figure out the transient context_id of this context and each of its
1623 * ancestors, to compute a path for this context.
1624 */
1625 path = compute_context_path(cur, context_id_lookup);
1626
1627 /* Examine the context stats */
1628 memset(&stat, 0, sizeof(stat));
1629 (*cur->methods->stats) (cur, NULL, NULL, &stat, true);
1630
1631 /* Account for saving one statistics slot for cumulative reporting */
1632 if (context_id < (max_stats - 1) || stats_count <= max_stats)
1633 {
1634 /* Copy statistics to DSA memory */
1635 PublishMemoryContext(meminfo, context_id, cur, path, stat, 1, MemoryStatsDsaArea, 100);
1636 }
1637 else
1638 {
1639 meminfo[max_stats - 1].totalspace += stat.totalspace;
1640 meminfo[max_stats - 1].nblocks += stat.nblocks;
1641 meminfo[max_stats - 1].freespace += stat.freespace;
1642 meminfo[max_stats - 1].freechunks += stat.freechunks;
1643 }
1644
1645 /*
1646 * DSA max limit per process is reached, write aggregate of the
1647 * remaining statistics.
1648 *
1649 * We can store contexts from 0 to max_stats - 1. When stats_count is
1650 * greater than max_stats, we stop reporting individual statistics
1651 * when context_id equals max_stats - 2. As we use max_stats - 1 array
1652 * slot for reporting cumulative statistics or "Remaining Totals".
1653 */
1654 if (stats_count > max_stats && context_id == (max_stats - 2))
1655 {
1656 char *nameptr;
1657 int namelen = strlen("Remaining Totals");
1658
1659 num_individual_stats = context_id + 1;
1660 meminfo[max_stats - 1].name = dsa_allocate(MemoryStatsDsaArea, namelen + 1);
1661 nameptr = dsa_get_address(MemoryStatsDsaArea, meminfo[max_stats - 1].name);
1662 strncpy(nameptr, "Remaining Totals", namelen);
1663 meminfo[max_stats - 1].ident = InvalidDsaPointer;
1664 meminfo[max_stats - 1].path = InvalidDsaPointer;
1665 meminfo[max_stats - 1].type = 0;
1666 }
1667 context_id++;
1668 }
1669
1670 /*
1671 * Statistics are not aggregated, i.e individual statistics reported when
1672 * stats_count <= max_stats.
1673 */
1674 if (stats_count <= max_stats)
1675 {
1676 memCxtState[idx].total_stats = context_id;
1677 }
1678 /* Report number of aggregated memory contexts */
1679 else
1680 {
1681 meminfo[max_stats - 1].num_agg_stats = context_id -
1682 num_individual_stats;
1683
1684 /*
1685 * Total stats equals num_individual_stats + 1 record for cumulative
1686 * statistics.
1687 */
1688 memCxtState[idx].total_stats = num_individual_stats + 1;
1689 }
1690
1691 /* Notify waiting backends and return */
1693
1694 hash_destroy(context_id_lookup);
1695}
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
Definition: dsa.c:942
void dsa_pin_mapping(dsa_area *area)
Definition: dsa.c:635
dsa_handle dsa_get_handle(dsa_area *area)
Definition: dsa.c:498
void dsa_pin(dsa_area *area)
Definition: dsa.c:975
#define dsa_allocate0(area, size)
Definition: dsa.h:113
#define dsa_allocate(area, size)
Definition: dsa.h:109
dsm_handle dsa_handle
Definition: dsa.h:136
#define dsa_create(tranch_id)
Definition: dsa.h:117
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:865
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
struct cursor * cur
Definition: ecpg.c:29
int MyProcPid
Definition: globals.c:48
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
List * lcons_int(int datum, List *list)
Definition: list.c:513
static void compute_contexts_count_and_ids(List *contexts, HTAB *context_id_lookup, int *stats_count, bool summary)
Definition: mcxt.c:1742
@ PRINT_STATS_NONE
Definition: mcxt.c:152
static void PublishMemoryContext(MemoryStatsEntry *memcxt_info, int curr_id, MemoryContext context, List *path, MemoryContextCounters stat, int num_contexts, dsa_area *area, int max_levels)
Definition: mcxt.c:1790
static void end_memorycontext_reporting(void)
Definition: mcxt.c:1702
static List * compute_context_path(MemoryContext c, HTAB *context_id_lookup)
Definition: mcxt.c:1716
#define MEMORY_CONTEXT_REPORT_MAX_PER_BACKEND
Definition: memutils.h:61
struct MemoryStatsContextId MemoryStatsContextId
#define MAX_MEMORY_CONTEXT_STATS_SIZE
Definition: memutils.h:69
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
#define NIL
Definition: pg_list.h:68
#define list_make1(x1)
Definition: pg_list.h:212
#define foreach_ptr(type, var, lst)
Definition: pg_list.h:469
char * c
tree ctl
Definition: radixtree.h:1838
Definition: dynahash.c:220
uint16 tranche
Definition: lwlock.h:43
Definition: pg_list.h:54
int64 totalspace
Definition: memutils.h:351
dsa_pointer ident
Definition: memutils.h:346
dsa_pointer name
Definition: memutils.h:345
int64 freechunks
Definition: memutils.h:354
dsa_pointer path
Definition: memutils.h:347
NodeTag type
Definition: memutils.h:348
#define stat
Definition: win32_port.h:274

References compute_context_path(), compute_contexts_count_and_ids(), ctl, cur, CurrentMemoryContext, dsa_allocate, dsa_allocate0, dsa_attach(), dsa_create, dsa_get_address(), dsa_get_handle(), DSA_HANDLE_INVALID, dsa_pin(), dsa_pin_mapping(), DsaPointerIsValid, end_memorycontext_reporting(), MemoryContextData::firstchild, foreach_ptr, free_memorycontextstate_dsa(), MemoryStatsEntry::freechunks, MemoryStatsEntry::freespace, HASH_BLOBS, HASH_CONTEXT, hash_create(), hash_destroy(), HASH_ELEM, MemoryStatsEntry::ident, idx(), InvalidDsaPointer, lcons_int(), list_make1, LW_EXCLUSIVE, MemoryStatsCtl::lw_lock, LWLockAcquire(), LWLockRelease(), MAX_MEMORY_CONTEXT_STATS_SIZE, memCxtArea, memCxtState, MEMORY_CONTEXT_REPORT_MAX_PER_BACKEND, MemoryContextStatsInternal(), MemoryContextSwitchTo(), MemoryStatsDsaArea, MemoryStatsCtl::memstats_dsa_handle, MemoryStatsBackendState::memstats_dsa_pointer, MemoryContextData::methods, Min, MyProcNumber, MyProcPid, name, MemoryStatsEntry::name, MemoryStatsEntry::nblocks, MemoryContextData::nextchild, NIL, MemoryStatsEntry::num_agg_stats, MemoryStatsEntry::path, PRINT_STATS_NONE, MemoryStatsBackendState::proc_id, PublishMemoryContext(), PublishMemoryContextPending, stat, MemoryContextMethods::stats, MemoryStatsBackendState::summary, TopMemoryContext, MemoryStatsBackendState::total_stats, MemoryStatsEntry::totalspace, LWLock::tranche, and MemoryStatsEntry::type.

Referenced by ProcessAutoVacLauncherInterrupts(), ProcessCheckpointerInterrupts(), ProcessInterrupts(), ProcessMainLoopInterrupts(), ProcessPgArchInterrupts(), ProcessStartupProcInterrupts(), and ProcessWalSummarizerInterrupts().

◆ ProcessLogMemoryContextInterrupt()

void ProcessLogMemoryContextInterrupt ( void  )

Definition at line 1380 of file mcxt.c.

1381{
1383
1384 /*
1385 * Use LOG_SERVER_ONLY to prevent this message from being sent to the
1386 * connected client.
1387 */
1389 (errhidestmt(true),
1390 errhidecontext(true),
1391 errmsg("logging memory contexts of PID %d", MyProcPid)));
1392
1393 /*
1394 * When a backend process is consuming huge memory, logging all its memory
1395 * contexts might overrun available disk space. To prevent this, we limit
1396 * the depth of the hierarchy, as well as the number of child contexts to
1397 * log per parent to 100.
1398 *
1399 * As with MemoryContextStats(), we suppose that practical cases where the
1400 * dump gets long will typically be huge numbers of siblings under the
1401 * same parent context; while the additional debugging value from seeing
1402 * details about individual siblings beyond 100 will not be large.
1403 */
1405}

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

Referenced by ProcessAutoVacLauncherInterrupts(), ProcessCheckpointerInterrupts(), ProcessInterrupts(), ProcessMainLoopInterrupts(), ProcessPgArchInterrupts(), ProcessStartupProcInterrupts(), and ProcessWalSummarizerInterrupts().

◆ 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}
#define elog(elevel,...)
Definition: elog.h:226
static void dclist_init(dclist_head *head)
Definition: ilist.h:671
@ MCTX_SLAB_ID
#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(), ReorderBufferAllocate(), and test_random().

Variable Documentation

◆ CacheMemoryContext

PGDLLIMPORT MemoryContext CacheMemoryContext
extern

Definition at line 168 of file mcxt.c.

Referenced by _SPI_save_plan(), AllocateRelationDesc(), assign_record_type_typmod(), AttrDefaultFetch(), BuildEventTriggerCache(), BuildHardcodedDescriptor(), CatalogCacheCreateEntry(), CatalogCacheInitializeCache(), CheckNNConstraintFetch(), CreateCacheMemoryContext(), ensure_record_cache_typmod_slot_exists(), FetchTableStates(), generate_partition_qual(), get_attribute_options(), get_tablespace(), GetCachedExpression(), GetCachedPlan(), GetFdwRoutineForRelation(), init_ts_config_cache(), 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(), sql_compile_callback(), and UploadManifest().

◆ CurTransactionContext

◆ ErrorContext

◆ memCxtArea

◆ memCxtState

◆ MemoryStatsDsaArea

PGDLLIMPORT dsa_area* MemoryStatsDsaArea
extern

◆ MessageContext

◆ PortalContext

◆ PostmasterContext

◆ TopMemoryContext

PGDLLIMPORT MemoryContext TopMemoryContext
extern

Definition at line 165 of file mcxt.c.

Referenced by _PG_init(), AbortOutOfAnyTransaction(), add_reloption(), allocate_reloption(), AllocateAttribute(), AllocSetContextCreateInternal(), ApplyLauncherMain(), AtAbort_Memory(), AtStart_Memory(), AttachSession(), AutoVacLauncherMain(), BackendInitialize(), BackendMain(), BackgroundWorkerMain(), BackgroundWriterMain(), BaseBackupAddTarget(), be_tls_open_server(), build_guc_variables(), BumpContextCreate(), cache_single_string(), cached_function_compile(), cfunc_hashtable_insert(), check_foreign_key(), check_primary_key(), CheckpointerMain(), ClientAuthentication(), compile_plperl_function(), compile_pltcl_function(), CreateCacheMemoryContext(), CreateWaitEventSet(), dblink_connect(), dblink_init(), DCH_cache_getnew(), do_autovacuum(), dsm_create_descriptor(), dsm_impl_sysv(), EnablePortalManager(), EventTriggerBeginCompleteQuery(), Exec_ListenCommit(), executeDateTimeMethod(), find_plan(), finish_xact_command(), GenerationContextCreate(), GetExplainExtensionId(), GetLocalBufferStorage(), GetLockConflicts(), getmissingattr(), GetNamedDSMSegment(), GetSessionDsmHandle(), hash_create(), init_database_collation(), init_missing_cache(), init_string_reloption(), InitDeadLockChecking(), initialize_reloptions(), initialize_target_list(), InitializeClientEncoding(), InitializeLogRepWorker(), InitializeParallelDSM(), InitializeSearchPath(), InitializeSession(), InitializeSystemUser(), InitSync(), InitWalSender(), InitXLogInsert(), injection_points_attach(), injection_points_detach(), llvm_compile_module(), llvm_create_context(), llvm_session_initialize(), LockAcquireExtended(), logicalrep_launcher_attach_dshmem(), LogicalRepApplyLoop(), LWLockRegisterTranche(), 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_get_process_memory_contexts(), pg_newlocale_from_collation(), PgArchiverMain(), pgstat_attach_shmem(), pgstat_init_snapshot_fixed(), pgstat_prep_pending_entry(), pgstat_prep_snapshot(), pgstat_register_kind(), pgstat_setup_backend_status_context(), pgstat_setup_memcxt(), plperl_spi_prepare(), plpgsql_compile_callback(), 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(), ProcessGetMemoryContextInterrupt(), ProcessLogMemoryContextInterrupt(), ProcessParallelApplyMessages(), ProcessParallelMessages(), ProcessStartupPacket(), px_find_cipher(), px_find_digest(), RE_compile_and_cache(), recomputeNamespacePath(), register_label_provider(), RegisterExtensionExplainOption(), 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(), spcache_init(), SPI_connect_ext(), test_create(), WalSummarizerMain(), WalWriterMain(), and XLOGShmemInit().

◆ TopTransactionContext