Line data Source code
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-2024, 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"
21 :
22 :
23 : /*
24 : * MaxAllocSize, MaxAllocHugeSize
25 : * Quasi-arbitrary limits on size of allocations.
26 : *
27 : * Note:
28 : * There is no guarantee that smaller allocations will succeed, but
29 : * larger requests will be summarily denied.
30 : *
31 : * palloc() enforces MaxAllocSize, chosen to correspond to the limiting size
32 : * of varlena objects under TOAST. See VARSIZE_4B() and related macros in
33 : * postgres.h. Many datatypes assume that any allocatable size can be
34 : * represented in a varlena header. This limit also permits a caller to use
35 : * an "int" variable for an index into or length of an allocation. Callers
36 : * careful to avoid these hazards can access the higher limit with
37 : * MemoryContextAllocHuge(). Both limits permit code to assume that it may
38 : * compute twice an allocation's size without overflow.
39 : */
40 : #define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
41 :
42 : #define AllocSizeIsValid(size) ((Size) (size) <= MaxAllocSize)
43 :
44 : /* Must be less than SIZE_MAX */
45 : #define MaxAllocHugeSize (SIZE_MAX / 2)
46 :
47 : #define InvalidAllocSize SIZE_MAX
48 :
49 : #define AllocHugeSizeIsValid(size) ((Size) (size) <= MaxAllocHugeSize)
50 :
51 :
52 : /*
53 : * Standard top-level memory contexts.
54 : *
55 : * Only TopMemoryContext and ErrorContext are initialized by
56 : * MemoryContextInit() itself.
57 : */
58 : extern PGDLLIMPORT MemoryContext TopMemoryContext;
59 : extern PGDLLIMPORT MemoryContext ErrorContext;
60 : extern PGDLLIMPORT MemoryContext PostmasterContext;
61 : extern PGDLLIMPORT MemoryContext CacheMemoryContext;
62 : extern PGDLLIMPORT MemoryContext MessageContext;
63 : extern PGDLLIMPORT MemoryContext TopTransactionContext;
64 : extern PGDLLIMPORT MemoryContext CurTransactionContext;
65 :
66 : /* This is a transient link to the active portal's memory context: */
67 : extern PGDLLIMPORT MemoryContext PortalContext;
68 :
69 :
70 : /*
71 : * Memory-context-type-independent functions in mcxt.c
72 : */
73 : extern void MemoryContextInit(void);
74 : extern void MemoryContextReset(MemoryContext context);
75 : extern void MemoryContextDelete(MemoryContext context);
76 : extern void MemoryContextResetOnly(MemoryContext context);
77 : extern void MemoryContextResetChildren(MemoryContext context);
78 : extern void MemoryContextDeleteChildren(MemoryContext context);
79 : extern void MemoryContextSetIdentifier(MemoryContext context, const char *id);
80 : extern void MemoryContextSetParent(MemoryContext context,
81 : MemoryContext new_parent);
82 : extern MemoryContext GetMemoryChunkContext(void *pointer);
83 : extern Size GetMemoryChunkSpace(void *pointer);
84 : extern MemoryContext MemoryContextGetParent(MemoryContext context);
85 : extern bool MemoryContextIsEmpty(MemoryContext context);
86 : extern Size MemoryContextMemAllocated(MemoryContext context, bool recurse);
87 : extern void MemoryContextMemConsumed(MemoryContext context,
88 : MemoryContextCounters *consumed);
89 : extern void MemoryContextStats(MemoryContext context);
90 : extern void MemoryContextStatsDetail(MemoryContext context,
91 : int max_level, int max_children,
92 : bool print_to_stderr);
93 : extern void MemoryContextAllowInCriticalSection(MemoryContext context,
94 : bool allow);
95 :
96 : #ifdef MEMORY_CONTEXT_CHECKING
97 : extern void MemoryContextCheck(MemoryContext context);
98 : #endif
99 :
100 : /* Handy macro for copying and assigning context ID ... but note double eval */
101 : #define MemoryContextCopyAndSetIdentifier(cxt, id) \
102 : MemoryContextSetIdentifier(cxt, MemoryContextStrdup(cxt, id))
103 :
104 : extern void HandleLogMemoryContextInterrupt(void);
105 : extern void ProcessLogMemoryContextInterrupt(void);
106 :
107 : /*
108 : * Memory-context-type-specific functions
109 : */
110 :
111 : /* aset.c */
112 : extern MemoryContext AllocSetContextCreateInternal(MemoryContext parent,
113 : const char *name,
114 : Size minContextSize,
115 : Size initBlockSize,
116 : Size maxBlockSize);
117 :
118 : /*
119 : * This wrapper macro exists to check for non-constant strings used as context
120 : * names; that's no longer supported. (Use MemoryContextSetIdentifier if you
121 : * want to provide a variable identifier.)
122 : */
123 : #ifdef HAVE__BUILTIN_CONSTANT_P
124 : #define AllocSetContextCreate(parent, name, ...) \
125 : (StaticAssertExpr(__builtin_constant_p(name), \
126 : "memory context names must be constant strings"), \
127 : AllocSetContextCreateInternal(parent, name, __VA_ARGS__))
128 : #else
129 : #define AllocSetContextCreate \
130 : AllocSetContextCreateInternal
131 : #endif
132 :
133 : /* slab.c */
134 : extern MemoryContext SlabContextCreate(MemoryContext parent,
135 : const char *name,
136 : Size blockSize,
137 : Size chunkSize);
138 :
139 : /* generation.c */
140 : extern MemoryContext GenerationContextCreate(MemoryContext parent,
141 : const char *name,
142 : Size minContextSize,
143 : Size initBlockSize,
144 : Size maxBlockSize);
145 :
146 : /* bump.c */
147 : extern MemoryContext BumpContextCreate(MemoryContext parent,
148 : const char *name,
149 : Size minContextSize,
150 : Size initBlockSize,
151 : Size maxBlockSize);
152 :
153 : /*
154 : * Recommended default alloc parameters, suitable for "ordinary" contexts
155 : * that might hold quite a lot of data.
156 : */
157 : #define ALLOCSET_DEFAULT_MINSIZE 0
158 : #define ALLOCSET_DEFAULT_INITSIZE (8 * 1024)
159 : #define ALLOCSET_DEFAULT_MAXSIZE (8 * 1024 * 1024)
160 : #define ALLOCSET_DEFAULT_SIZES \
161 : ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE
162 :
163 : /*
164 : * Recommended alloc parameters for "small" contexts that are never expected
165 : * to contain much data (for example, a context to contain a query plan).
166 : */
167 : #define ALLOCSET_SMALL_MINSIZE 0
168 : #define ALLOCSET_SMALL_INITSIZE (1 * 1024)
169 : #define ALLOCSET_SMALL_MAXSIZE (8 * 1024)
170 : #define ALLOCSET_SMALL_SIZES \
171 : ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MAXSIZE
172 :
173 : /*
174 : * Recommended alloc parameters for contexts that should start out small,
175 : * but might sometimes grow big.
176 : */
177 : #define ALLOCSET_START_SMALL_SIZES \
178 : ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE
179 :
180 :
181 : /*
182 : * Threshold above which a request in an AllocSet context is certain to be
183 : * allocated separately (and thereby have constant allocation overhead).
184 : * Few callers should be interested in this, but tuplesort/tuplestore need
185 : * to know it.
186 : */
187 : #define ALLOCSET_SEPARATE_THRESHOLD 8192
188 :
189 : #define SLAB_DEFAULT_BLOCK_SIZE (8 * 1024)
190 : #define SLAB_LARGE_BLOCK_SIZE (8 * 1024 * 1024)
191 :
192 : /*
193 : * pg_memory_is_all_zeros
194 : *
195 : * Test if a memory region starting at "ptr" and of size "len" is full of
196 : * zeroes.
197 : *
198 : * The test is divided into multiple cases for safety reason and multiple
199 : * phases for efficiency.
200 : *
201 : * Case 1: len < sizeof(size_t) bytes, then byte-by-byte comparison.
202 : * Case 2: len < (sizeof(size_t) * 8 - 1) bytes:
203 : * - Phase 1: byte-by-byte comparison, until the pointer is aligned.
204 : * - Phase 2: size_t comparisons, with aligned pointers, up to the last
205 : * location possible.
206 : * - Phase 3: byte-by-byte comparison, until the end location.
207 : * Case 3: len >= (sizeof(size_t) * 8) bytes, same as case 2 except that an
208 : * additional phase is placed between Phase 1 and Phase 2, with
209 : * (8 * sizeof(size_t)) comparisons using bitwise OR to encourage
210 : * compilers to use SIMD instructions if available, up to the last
211 : * aligned location possible.
212 : *
213 : * Case 1 and Case 2 are mandatory to ensure that we won't read beyond the
214 : * memory area. This is portable for 32-bit and 64-bit architectures.
215 : *
216 : * Caller must ensure that "ptr" is not NULL.
217 : */
218 : static inline bool
219 1629920 : pg_memory_is_all_zeros(const void *ptr, size_t len)
220 : {
221 1629920 : const unsigned char *p = (const unsigned char *) ptr;
222 1629920 : const unsigned char *end = &p[len];
223 1629920 : const unsigned char *aligned_end = (const unsigned char *)
224 1629920 : ((uintptr_t) end & (~(sizeof(size_t) - 1)));
225 :
226 1629920 : if (len < sizeof(size_t))
227 : {
228 0 : while (p < end)
229 : {
230 0 : if (*p++ != 0)
231 0 : return false;
232 : }
233 0 : return true;
234 : }
235 :
236 : /* "len" in the [sizeof(size_t), sizeof(size_t) * 8 - 1] range */
237 1629920 : if (len < sizeof(size_t) * 8)
238 : {
239 : /* Compare bytes until the pointer "p" is aligned */
240 17426 : while (((uintptr_t) p & (sizeof(size_t) - 1)) != 0)
241 : {
242 0 : if (p == end)
243 0 : return true;
244 0 : if (*p++ != 0)
245 0 : return false;
246 : }
247 :
248 : /*
249 : * Compare remaining size_t-aligned chunks.
250 : *
251 : * There is no risk to read beyond the memory area, as "aligned_end"
252 : * cannot be higher than "end".
253 : */
254 62322 : for (; p < aligned_end; p += sizeof(size_t))
255 : {
256 54746 : if (*(size_t *) p != 0)
257 9850 : return false;
258 : }
259 :
260 : /* Compare remaining bytes until the end */
261 7576 : while (p < end)
262 : {
263 0 : if (*p++ != 0)
264 0 : return false;
265 : }
266 7576 : return true;
267 : }
268 :
269 : /* "len" in the [sizeof(size_t) * 8, inf) range */
270 :
271 : /* Compare bytes until the pointer "p" is aligned */
272 1612494 : while (((uintptr_t) p & (sizeof(size_t) - 1)) != 0)
273 : {
274 0 : if (p == end)
275 0 : return true;
276 :
277 0 : if (*p++ != 0)
278 0 : return false;
279 : }
280 :
281 : /*
282 : * Compare 8 * sizeof(size_t) chunks at once.
283 : *
284 : * For performance reasons, we manually unroll this loop and purposefully
285 : * use bitwise-ORs to combine each comparison. This prevents boolean
286 : * short-circuiting and lets the compiler know that it's safe to access
287 : * all 8 elements regardless of the result of the other comparisons. This
288 : * seems to be enough to coax a few compilers into using SIMD
289 : * instructions.
290 : */
291 3201680 : for (; p < aligned_end - (sizeof(size_t) * 7); p += sizeof(size_t) * 8)
292 : {
293 2545944 : if ((((size_t *) p)[0] != 0) | (((size_t *) p)[1] != 0) |
294 2545944 : (((size_t *) p)[2] != 0) | (((size_t *) p)[3] != 0) |
295 2545944 : (((size_t *) p)[4] != 0) | (((size_t *) p)[5] != 0) |
296 2545944 : (((size_t *) p)[6] != 0) | (((size_t *) p)[7] != 0))
297 956758 : return false;
298 : }
299 :
300 : /*
301 : * Compare remaining size_t-aligned chunks.
302 : *
303 : * There is no risk to read beyond the memory area, as "aligned_end"
304 : * cannot be higher than "end".
305 : */
306 3221942 : for (; p < aligned_end; p += sizeof(size_t))
307 : {
308 3199470 : if (*(size_t *) p != 0)
309 633264 : return false;
310 : }
311 :
312 : /* Compare remaining bytes until the end */
313 22472 : while (p < end)
314 : {
315 0 : if (*p++ != 0)
316 0 : return false;
317 : }
318 :
319 22472 : return true;
320 : }
321 :
322 : #endif /* MEMUTILS_H */
|