PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
memutils.h
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * memutils.h
4 * This file contains declarations for memory allocation utility
5 * functions. These are functions that are not quite widely used
6 * enough to justify going in utils/palloc.h, but are still part
7 * of the API of the memory management subsystem.
8 *
9 *
10 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
11 * Portions Copyright (c) 1994, Regents of the University of California
12 *
13 * src/include/utils/memutils.h
14 *
15 *-------------------------------------------------------------------------
16 */
17#ifndef MEMUTILS_H
18#define MEMUTILS_H
19
20#include "nodes/memnodes.h"
22#include "storage/lmgr.h"
23#include "utils/dsa.h"
24
25
26/*
27 * MaxAllocSize, MaxAllocHugeSize
28 * Quasi-arbitrary limits on size of allocations.
29 *
30 * Note:
31 * There is no guarantee that smaller allocations will succeed, but
32 * larger requests will be summarily denied.
33 *
34 * palloc() enforces MaxAllocSize, chosen to correspond to the limiting size
35 * of varlena objects under TOAST. See VARSIZE_4B() and related macros in
36 * postgres.h. Many datatypes assume that any allocatable size can be
37 * represented in a varlena header. This limit also permits a caller to use
38 * an "int" variable for an index into or length of an allocation. Callers
39 * careful to avoid these hazards can access the higher limit with
40 * MemoryContextAllocHuge(). Both limits permit code to assume that it may
41 * compute twice an allocation's size without overflow.
42 */
43#define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
44
45#define AllocSizeIsValid(size) ((Size) (size) <= MaxAllocSize)
46
47/* Must be less than SIZE_MAX */
48#define MaxAllocHugeSize (SIZE_MAX / 2)
49
50#define InvalidAllocSize SIZE_MAX
51
52#define AllocHugeSizeIsValid(size) ((Size) (size) <= MaxAllocHugeSize)
53
54/*
55 * Memory Context reporting size limits.
56 */
57
58/* Max length of context name and ident */
59#define MEMORY_CONTEXT_IDENT_SHMEM_SIZE 64
60/* Maximum size (in bytes) of DSA area per process */
61#define MEMORY_CONTEXT_REPORT_MAX_PER_BACKEND ((size_t) (1 * 1024 * 1024))
62
63/*
64 * Maximum size per context. Actual size may be lower as this assumes the worst
65 * case of deepest path and longest identifiers (name and ident, thus the
66 * multiplication by 2). The path depth is limited to 100 like for memory
67 * context logging.
68 */
69#define MAX_MEMORY_CONTEXT_STATS_SIZE (sizeof(MemoryStatsEntry) + \
70 (100 * sizeof(int)) + (2 * MEMORY_CONTEXT_IDENT_SHMEM_SIZE))
71
72/*
73 * Standard top-level memory contexts.
74 *
75 * Only TopMemoryContext and ErrorContext are initialized by
76 * MemoryContextInit() itself.
77 */
85
86/* This is a transient link to the active portal's memory context: */
88
89
90/*
91 * Memory-context-type-independent functions in mcxt.c
92 */
93extern void MemoryContextInit(void);
94extern void MemoryContextReset(MemoryContext context);
95extern void MemoryContextDelete(MemoryContext context);
96extern void MemoryContextResetOnly(MemoryContext context);
97extern void MemoryContextResetChildren(MemoryContext context);
99extern void MemoryContextSetIdentifier(MemoryContext context, const char *id);
100extern void MemoryContextSetParent(MemoryContext context,
101 MemoryContext new_parent);
102extern MemoryContext GetMemoryChunkContext(void *pointer);
103extern Size GetMemoryChunkSpace(void *pointer);
105extern bool MemoryContextIsEmpty(MemoryContext context);
106extern Size MemoryContextMemAllocated(MemoryContext context, bool recurse);
107extern void MemoryContextMemConsumed(MemoryContext context,
108 MemoryContextCounters *consumed);
109extern void MemoryContextStats(MemoryContext context);
110extern void MemoryContextStatsDetail(MemoryContext context,
111 int max_level, int max_children,
112 bool print_to_stderr);
114 bool allow);
115
116#ifdef MEMORY_CONTEXT_CHECKING
117extern void MemoryContextCheck(MemoryContext context);
118#endif
119
120/* Handy macro for copying and assigning context ID ... but note double eval */
121#define MemoryContextCopyAndSetIdentifier(cxt, id) \
122 MemoryContextSetIdentifier(cxt, MemoryContextStrdup(cxt, id))
123
124extern void HandleLogMemoryContextInterrupt(void);
125extern void ProcessLogMemoryContextInterrupt(void);
126
127/*
128 * Memory-context-type-specific functions
129 */
130
131/* aset.c */
133 const char *name,
134 Size minContextSize,
135 Size initBlockSize,
136 Size maxBlockSize);
137
138/*
139 * This wrapper macro exists to check for non-constant strings used as context
140 * names; that's no longer supported. (Use MemoryContextSetIdentifier if you
141 * want to provide a variable identifier.)
142 */
143#ifdef HAVE__BUILTIN_CONSTANT_P
144#define AllocSetContextCreate(parent, name, ...) \
145 (StaticAssertExpr(__builtin_constant_p(name), \
146 "memory context names must be constant strings"), \
147 AllocSetContextCreateInternal(parent, name, __VA_ARGS__))
148#else
149#define AllocSetContextCreate \
150 AllocSetContextCreateInternal
151#endif
152
153/* slab.c */
155 const char *name,
156 Size blockSize,
157 Size chunkSize);
158
159/* generation.c */
161 const char *name,
162 Size minContextSize,
163 Size initBlockSize,
164 Size maxBlockSize);
165
166/* bump.c */
168 const char *name,
169 Size minContextSize,
170 Size initBlockSize,
171 Size maxBlockSize);
172
173/*
174 * Recommended default alloc parameters, suitable for "ordinary" contexts
175 * that might hold quite a lot of data.
176 */
177#define ALLOCSET_DEFAULT_MINSIZE 0
178#define ALLOCSET_DEFAULT_INITSIZE (8 * 1024)
179#define ALLOCSET_DEFAULT_MAXSIZE (8 * 1024 * 1024)
180#define ALLOCSET_DEFAULT_SIZES \
181 ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE
182
183/*
184 * Recommended alloc parameters for "small" contexts that are never expected
185 * to contain much data (for example, a context to contain a query plan).
186 */
187#define ALLOCSET_SMALL_MINSIZE 0
188#define ALLOCSET_SMALL_INITSIZE (1 * 1024)
189#define ALLOCSET_SMALL_MAXSIZE (8 * 1024)
190#define ALLOCSET_SMALL_SIZES \
191 ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MAXSIZE
192
193/*
194 * Recommended alloc parameters for contexts that should start out small,
195 * but might sometimes grow big.
196 */
197#define ALLOCSET_START_SMALL_SIZES \
198 ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE
199
200
201/*
202 * Threshold above which a request in an AllocSet context is certain to be
203 * allocated separately (and thereby have constant allocation overhead).
204 * Few callers should be interested in this, but tuplesort/tuplestore need
205 * to know it.
206 */
207#define ALLOCSET_SEPARATE_THRESHOLD 8192
208
209#define SLAB_DEFAULT_BLOCK_SIZE (8 * 1024)
210#define SLAB_LARGE_BLOCK_SIZE (8 * 1024 * 1024)
211
212/*
213 * pg_memory_is_all_zeros
214 *
215 * Test if a memory region starting at "ptr" and of size "len" is full of
216 * zeroes.
217 *
218 * The test is divided into multiple cases for safety reason and multiple
219 * phases for efficiency.
220 *
221 * Case 1: len < sizeof(size_t) bytes, then byte-by-byte comparison.
222 * Case 2: len < (sizeof(size_t) * 8 - 1) bytes:
223 * - Phase 1: byte-by-byte comparison, until the pointer is aligned.
224 * - Phase 2: size_t comparisons, with aligned pointers, up to the last
225 * location possible.
226 * - Phase 3: byte-by-byte comparison, until the end location.
227 * Case 3: len >= (sizeof(size_t) * 8) bytes, same as case 2 except that an
228 * additional phase is placed between Phase 1 and Phase 2, with
229 * (8 * sizeof(size_t)) comparisons using bitwise OR to encourage
230 * compilers to use SIMD instructions if available, up to the last
231 * aligned location possible.
232 *
233 * Case 1 and Case 2 are mandatory to ensure that we won't read beyond the
234 * memory area. This is portable for 32-bit and 64-bit architectures.
235 *
236 * Caller must ensure that "ptr" is not NULL.
237 */
238static inline bool
239pg_memory_is_all_zeros(const void *ptr, size_t len)
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}
341
342/* Dynamic shared memory state for statistics per context */
343typedef struct MemoryStatsEntry
344{
357
358/*
359 * Static shared memory state representing the DSA area created for memory
360 * context statistics reporting. A single DSA area is created and used by all
361 * the processes, each having its specific DSA allocations for sharing memory
362 * statistics, tracked by per backend static shared memory state.
363 */
364typedef struct MemoryStatsCtl
365{
369
370/*
371 * Per backend static shared memory state for memory context statistics
372 * reporting.
373 */
375{
384
385
386/*
387 * Used for storage of transient identifiers for pg_get_backend_memory_contexts
388 */
390{
394
398extern void ProcessGetMemoryContextInterrupt(void);
399extern const char *ContextTypeToString(NodeTag type);
400extern void HandleGetMemoryContextInterrupt(void);
402extern void MemoryContextReportingShmemInit(void);
403extern void AtProcExit_memstats_cleanup(int code, Datum arg);
404#endif /* MEMUTILS_H */
#define PGDLLIMPORT
Definition: c.h:1291
int64_t int64
Definition: c.h:499
size_t Size
Definition: c.h:576
int64 TimestampTz
Definition: timestamp.h:39
uint64 dsa_pointer
Definition: dsa.h:62
dsm_handle dsa_handle
Definition: dsa.h:136
void HandleGetMemoryContextInterrupt(void)
Definition: mcxt.c:1363
PGDLLIMPORT MemoryContext CurTransactionContext
Definition: mcxt.c:171
bool MemoryContextIsEmpty(MemoryContext context)
Definition: mcxt.c:774
void MemoryContextMemConsumed(MemoryContext context, MemoryContextCounters *consumed)
Definition: mcxt.c:817
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:414
PGDLLIMPORT MemoryContext MessageContext
Definition: mcxt.c:169
struct MemoryStatsBackendState MemoryStatsBackendState
Size MemoryContextReportingShmemSize(void)
Definition: mcxtfuncs.c:619
PGDLLIMPORT MemoryContext TopMemoryContext
Definition: mcxt.c:165
PGDLLIMPORT MemoryContext TopTransactionContext
Definition: mcxt.c:170
PGDLLIMPORT dsa_area * MemoryStatsDsaArea
Definition: mcxt.c:175
void HandleLogMemoryContextInterrupt(void)
Definition: mcxt.c:1347
const char * ContextTypeToString(NodeTag type)
Definition: mcxtfuncs.c:165
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:668
void AtProcExit_memstats_cleanup(int code, Datum arg)
Definition: mcxt.c:1908
Size GetMemoryChunkSpace(void *pointer)
Definition: mcxt.c:752
void ProcessGetMemoryContextInterrupt(void)
Definition: mcxt.c:1432
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:570
MemoryContext GetMemoryChunkContext(void *pointer)
Definition: mcxt.c:738
PGDLLIMPORT MemoryContext PostmasterContext
Definition: mcxt.c:167
void MemoryContextStatsDetail(MemoryContext context, int max_level, int max_children, bool print_to_stderr)
Definition: mcxt.c:860
Size MemoryContextMemAllocated(MemoryContext context, bool recurse)
Definition: mcxt.c:793
void MemoryContextStats(MemoryContext context)
Definition: mcxt.c:845
MemoryContext SlabContextCreate(MemoryContext parent, const char *name, Size blockSize, Size chunkSize)
Definition: slab.c:322
void MemoryContextInit(void)
Definition: mcxt.c:370
MemoryContext BumpContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: bump.c:131
PGDLLIMPORT MemoryContext CacheMemoryContext
Definition: mcxt.c:168
PGDLLIMPORT MemoryStatsBackendState * memCxtState
Definition: mcxtfuncs.c:37
struct MemoryStatsContextId MemoryStatsContextId
struct MemoryStatsCtl MemoryStatsCtl
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:762
void ProcessLogMemoryContextInterrupt(void)
Definition: mcxt.c:1380
void MemoryContextReportingShmemInit(void)
Definition: mcxtfuncs.c:637
struct MemoryStatsEntry MemoryStatsEntry
PGDLLIMPORT MemoryContext PortalContext
Definition: mcxt.c:174
MemoryContext GenerationContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: generation.c:160
static bool pg_memory_is_all_zeros(const void *ptr, size_t len)
Definition: memutils.h:239
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:485
void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
Definition: mcxt.c:725
PGDLLIMPORT MemoryStatsCtl * memCxtArea
Definition: mcxtfuncs.c:38
void MemoryContextResetChildren(MemoryContext context)
Definition: mcxt.c:464
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:643
void MemoryContextResetOnly(MemoryContext context)
Definition: mcxt.c:433
PGDLLIMPORT MemoryContext ErrorContext
Definition: mcxt.c:166
MemoryContext AllocSetContextCreateInternal(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:347
NodeTag
Definition: nodes.h:27
void * arg
const void size_t len
uintptr_t Datum
Definition: postgres.h:69
Definition: lwlock.h:42
TimestampTz stats_timestamp
Definition: memutils.h:382
ConditionVariable memcxt_cv
Definition: memutils.h:376
dsa_pointer memstats_dsa_pointer
Definition: memutils.h:381
MemoryContext context
Definition: memutils.h:391
dsa_handle memstats_dsa_handle
Definition: memutils.h:366
LWLock lw_lock
Definition: memutils.h:367
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
Definition: dsa.c:348
const char * type
const char * name