Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * mcxt.c
4 : * POSTGRES memory context management code.
5 : *
6 : * This module handles context management operations that are independent
7 : * of the particular kind of context being operated on. It calls
8 : * context-type-specific operations via the function pointers in a
9 : * context's MemoryContextMethods struct.
10 : *
11 : * A note about Valgrind support: when USE_VALGRIND is defined, we provide
12 : * support for memory leak tracking at the allocation-unit level. Valgrind
13 : * does leak detection by tracking allocated "chunks", which can be grouped
14 : * into "pools". The "chunk" terminology is overloaded, since we use that
15 : * word for our allocation units, and it's sometimes important to distinguish
16 : * those from the Valgrind objects that describe them. To reduce confusion,
17 : * let's use the terms "vchunk" and "vpool" for the Valgrind objects.
18 : *
19 : * We use a separate vpool for each memory context. The context-type-specific
20 : * code is responsible for creating and deleting the vpools, and also for
21 : * creating vchunks to cover its management data structures such as block
22 : * headers. (There must be a vchunk that includes every pointer we want
23 : * Valgrind to consider for leak-tracking purposes.) This module creates
24 : * and deletes the vchunks that cover the caller-visible allocated chunks.
25 : * However, the context-type-specific code must handle cleaning up those
26 : * vchunks too during memory context reset operations.
27 : *
28 : *
29 : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
30 : * Portions Copyright (c) 1994, Regents of the University of California
31 : *
32 : *
33 : * IDENTIFICATION
34 : * src/backend/utils/mmgr/mcxt.c
35 : *
36 : *-------------------------------------------------------------------------
37 : */
38 :
39 : #include "postgres.h"
40 :
41 : #include "mb/pg_wchar.h"
42 : #include "miscadmin.h"
43 : #include "utils/memdebug.h"
44 : #include "utils/memutils.h"
45 : #include "utils/memutils_internal.h"
46 : #include "utils/memutils_memorychunk.h"
47 :
48 :
49 : static void BogusFree(void *pointer);
50 : static void *BogusRealloc(void *pointer, Size size, int flags);
51 : static MemoryContext BogusGetChunkContext(void *pointer);
52 : static Size BogusGetChunkSpace(void *pointer);
53 :
54 : /*****************************************************************************
55 : * GLOBAL MEMORY *
56 : *****************************************************************************/
57 : #define BOGUS_MCTX(id) \
58 : [id].free_p = BogusFree, \
59 : [id].realloc = BogusRealloc, \
60 : [id].get_chunk_context = BogusGetChunkContext, \
61 : [id].get_chunk_space = BogusGetChunkSpace
62 :
63 : static const MemoryContextMethods mcxt_methods[] = {
64 : /* aset.c */
65 : [MCTX_ASET_ID].alloc = AllocSetAlloc,
66 : [MCTX_ASET_ID].free_p = AllocSetFree,
67 : [MCTX_ASET_ID].realloc = AllocSetRealloc,
68 : [MCTX_ASET_ID].reset = AllocSetReset,
69 : [MCTX_ASET_ID].delete_context = AllocSetDelete,
70 : [MCTX_ASET_ID].get_chunk_context = AllocSetGetChunkContext,
71 : [MCTX_ASET_ID].get_chunk_space = AllocSetGetChunkSpace,
72 : [MCTX_ASET_ID].is_empty = AllocSetIsEmpty,
73 : [MCTX_ASET_ID].stats = AllocSetStats,
74 : #ifdef MEMORY_CONTEXT_CHECKING
75 : [MCTX_ASET_ID].check = AllocSetCheck,
76 : #endif
77 :
78 : /* generation.c */
79 : [MCTX_GENERATION_ID].alloc = GenerationAlloc,
80 : [MCTX_GENERATION_ID].free_p = GenerationFree,
81 : [MCTX_GENERATION_ID].realloc = GenerationRealloc,
82 : [MCTX_GENERATION_ID].reset = GenerationReset,
83 : [MCTX_GENERATION_ID].delete_context = GenerationDelete,
84 : [MCTX_GENERATION_ID].get_chunk_context = GenerationGetChunkContext,
85 : [MCTX_GENERATION_ID].get_chunk_space = GenerationGetChunkSpace,
86 : [MCTX_GENERATION_ID].is_empty = GenerationIsEmpty,
87 : [MCTX_GENERATION_ID].stats = GenerationStats,
88 : #ifdef MEMORY_CONTEXT_CHECKING
89 : [MCTX_GENERATION_ID].check = GenerationCheck,
90 : #endif
91 :
92 : /* slab.c */
93 : [MCTX_SLAB_ID].alloc = SlabAlloc,
94 : [MCTX_SLAB_ID].free_p = SlabFree,
95 : [MCTX_SLAB_ID].realloc = SlabRealloc,
96 : [MCTX_SLAB_ID].reset = SlabReset,
97 : [MCTX_SLAB_ID].delete_context = SlabDelete,
98 : [MCTX_SLAB_ID].get_chunk_context = SlabGetChunkContext,
99 : [MCTX_SLAB_ID].get_chunk_space = SlabGetChunkSpace,
100 : [MCTX_SLAB_ID].is_empty = SlabIsEmpty,
101 : [MCTX_SLAB_ID].stats = SlabStats,
102 : #ifdef MEMORY_CONTEXT_CHECKING
103 : [MCTX_SLAB_ID].check = SlabCheck,
104 : #endif
105 :
106 : /* alignedalloc.c */
107 : [MCTX_ALIGNED_REDIRECT_ID].alloc = NULL, /* not required */
108 : [MCTX_ALIGNED_REDIRECT_ID].free_p = AlignedAllocFree,
109 : [MCTX_ALIGNED_REDIRECT_ID].realloc = AlignedAllocRealloc,
110 : [MCTX_ALIGNED_REDIRECT_ID].reset = NULL, /* not required */
111 : [MCTX_ALIGNED_REDIRECT_ID].delete_context = NULL, /* not required */
112 : [MCTX_ALIGNED_REDIRECT_ID].get_chunk_context = AlignedAllocGetChunkContext,
113 : [MCTX_ALIGNED_REDIRECT_ID].get_chunk_space = AlignedAllocGetChunkSpace,
114 : [MCTX_ALIGNED_REDIRECT_ID].is_empty = NULL, /* not required */
115 : [MCTX_ALIGNED_REDIRECT_ID].stats = NULL, /* not required */
116 : #ifdef MEMORY_CONTEXT_CHECKING
117 : [MCTX_ALIGNED_REDIRECT_ID].check = NULL, /* not required */
118 : #endif
119 :
120 : /* bump.c */
121 : [MCTX_BUMP_ID].alloc = BumpAlloc,
122 : [MCTX_BUMP_ID].free_p = BumpFree,
123 : [MCTX_BUMP_ID].realloc = BumpRealloc,
124 : [MCTX_BUMP_ID].reset = BumpReset,
125 : [MCTX_BUMP_ID].delete_context = BumpDelete,
126 : [MCTX_BUMP_ID].get_chunk_context = BumpGetChunkContext,
127 : [MCTX_BUMP_ID].get_chunk_space = BumpGetChunkSpace,
128 : [MCTX_BUMP_ID].is_empty = BumpIsEmpty,
129 : [MCTX_BUMP_ID].stats = BumpStats,
130 : #ifdef MEMORY_CONTEXT_CHECKING
131 : [MCTX_BUMP_ID].check = BumpCheck,
132 : #endif
133 :
134 :
135 : /*
136 : * Reserved and unused IDs should have dummy entries here. This allows us
137 : * to fail cleanly if a bogus pointer is passed to pfree or the like. It
138 : * seems sufficient to provide routines for the methods that might get
139 : * invoked from inspection of a chunk (see MCXT_METHOD calls below).
140 : */
141 : BOGUS_MCTX(MCTX_1_RESERVED_GLIBC_ID),
142 : BOGUS_MCTX(MCTX_2_RESERVED_GLIBC_ID),
143 : BOGUS_MCTX(MCTX_8_UNUSED_ID),
144 : BOGUS_MCTX(MCTX_9_UNUSED_ID),
145 : BOGUS_MCTX(MCTX_10_UNUSED_ID),
146 : BOGUS_MCTX(MCTX_11_UNUSED_ID),
147 : BOGUS_MCTX(MCTX_12_UNUSED_ID),
148 : BOGUS_MCTX(MCTX_13_UNUSED_ID),
149 : BOGUS_MCTX(MCTX_14_UNUSED_ID),
150 : BOGUS_MCTX(MCTX_0_RESERVED_UNUSEDMEM_ID),
151 : BOGUS_MCTX(MCTX_15_RESERVED_WIPEDMEM_ID)
152 : };
153 :
154 : #undef BOGUS_MCTX
155 :
156 : /*
157 : * CurrentMemoryContext
158 : * Default memory context for allocations.
159 : */
160 : MemoryContext CurrentMemoryContext = NULL;
161 :
162 : /*
163 : * Standard top-level contexts. For a description of the purpose of each
164 : * of these contexts, refer to src/backend/utils/mmgr/README
165 : */
166 : MemoryContext TopMemoryContext = NULL;
167 : MemoryContext ErrorContext = NULL;
168 : MemoryContext PostmasterContext = NULL;
169 : MemoryContext CacheMemoryContext = NULL;
170 : MemoryContext MessageContext = NULL;
171 : MemoryContext TopTransactionContext = NULL;
172 : MemoryContext CurTransactionContext = NULL;
173 :
174 : /* This is a transient link to the active portal's memory context: */
175 : MemoryContext PortalContext = NULL;
176 :
177 : static void MemoryContextDeleteOnly(MemoryContext context);
178 : static void MemoryContextCallResetCallbacks(MemoryContext context);
179 : static void MemoryContextStatsInternal(MemoryContext context, int level,
180 : int max_level, int max_children,
181 : MemoryContextCounters *totals,
182 : bool print_to_stderr);
183 : static void MemoryContextStatsPrint(MemoryContext context, void *passthru,
184 : const char *stats_string,
185 : bool print_to_stderr);
186 :
187 : /*
188 : * You should not do memory allocations within a critical section, because
189 : * an out-of-memory error will be escalated to a PANIC. To enforce that
190 : * rule, the allocation functions Assert that.
191 : */
192 : #define AssertNotInCriticalSection(context) \
193 : Assert(CritSectionCount == 0 || (context)->allowInCritSection)
194 :
195 : /*
196 : * Call the given function in the MemoryContextMethods for the memory context
197 : * type that 'pointer' belongs to.
198 : */
199 : #define MCXT_METHOD(pointer, method) \
200 : mcxt_methods[GetMemoryChunkMethodID(pointer)].method
201 :
202 : /*
203 : * GetMemoryChunkMethodID
204 : * Return the MemoryContextMethodID from the uint64 chunk header which
205 : * directly precedes 'pointer'.
206 : */
207 : static inline MemoryContextMethodID
208 555156618 : GetMemoryChunkMethodID(const void *pointer)
209 : {
210 : uint64 header;
211 :
212 : /*
213 : * Try to detect bogus pointers handed to us, poorly though we can.
214 : * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
215 : * allocated chunk.
216 : */
217 : Assert(pointer == (const void *) MAXALIGN(pointer));
218 :
219 : /* Allow access to the uint64 header */
220 : VALGRIND_MAKE_MEM_DEFINED((char *) pointer - sizeof(uint64), sizeof(uint64));
221 :
222 555156618 : header = *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
223 :
224 : /* Disallow access to the uint64 header */
225 : VALGRIND_MAKE_MEM_NOACCESS((char *) pointer - sizeof(uint64), sizeof(uint64));
226 :
227 555156618 : return (MemoryContextMethodID) (header & MEMORY_CONTEXT_METHODID_MASK);
228 : }
229 :
230 : /*
231 : * GetMemoryChunkHeader
232 : * Return the uint64 chunk header which directly precedes 'pointer'.
233 : *
234 : * This is only used after GetMemoryChunkMethodID, so no need for error checks.
235 : */
236 : static inline uint64
237 0 : GetMemoryChunkHeader(const void *pointer)
238 : {
239 : uint64 header;
240 :
241 : /* Allow access to the uint64 header */
242 : VALGRIND_MAKE_MEM_DEFINED((char *) pointer - sizeof(uint64), sizeof(uint64));
243 :
244 0 : header = *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
245 :
246 : /* Disallow access to the uint64 header */
247 : VALGRIND_MAKE_MEM_NOACCESS((char *) pointer - sizeof(uint64), sizeof(uint64));
248 :
249 0 : return header;
250 : }
251 :
252 : /*
253 : * MemoryContextTraverseNext
254 : * Helper function to traverse all descendants of a memory context
255 : * without recursion.
256 : *
257 : * Recursion could lead to out-of-stack errors with deep context hierarchies,
258 : * which would be unpleasant in error cleanup code paths.
259 : *
260 : * To process 'context' and all its descendants, use a loop like this:
261 : *
262 : * <process 'context'>
263 : * for (MemoryContext curr = context->firstchild;
264 : * curr != NULL;
265 : * curr = MemoryContextTraverseNext(curr, context))
266 : * {
267 : * <process 'curr'>
268 : * }
269 : *
270 : * This visits all the contexts in pre-order, that is a node is visited
271 : * before its children.
272 : */
273 : static MemoryContext
274 1279714 : MemoryContextTraverseNext(MemoryContext curr, MemoryContext top)
275 : {
276 : /* After processing a node, traverse to its first child if any */
277 1279714 : if (curr->firstchild != NULL)
278 0 : return curr->firstchild;
279 :
280 : /*
281 : * After processing a childless node, traverse to its next sibling if
282 : * there is one. If there isn't, traverse back up to the parent (which
283 : * has already been visited, and now so have all its descendants). We're
284 : * done if that is "top", otherwise traverse to its next sibling if any,
285 : * otherwise repeat moving up.
286 : */
287 1279714 : while (curr->nextchild == NULL)
288 : {
289 660912 : curr = curr->parent;
290 660912 : if (curr == top)
291 660912 : return NULL;
292 : }
293 618802 : return curr->nextchild;
294 : }
295 :
296 : /*
297 : * Support routines to trap use of invalid memory context method IDs
298 : * (from calling pfree or the like on a bogus pointer). As a possible
299 : * aid in debugging, we report the header word along with the pointer
300 : * address (if we got here, there must be an accessible header word).
301 : */
302 : static void
303 0 : BogusFree(void *pointer)
304 : {
305 0 : elog(ERROR, "pfree called with invalid pointer %p (header 0x%016" PRIx64 ")",
306 : pointer, GetMemoryChunkHeader(pointer));
307 : }
308 :
309 : static void *
310 0 : BogusRealloc(void *pointer, Size size, int flags)
311 : {
312 0 : elog(ERROR, "repalloc called with invalid pointer %p (header 0x%016" PRIx64 ")",
313 : pointer, GetMemoryChunkHeader(pointer));
314 : return NULL; /* keep compiler quiet */
315 : }
316 :
317 : static MemoryContext
318 0 : BogusGetChunkContext(void *pointer)
319 : {
320 0 : elog(ERROR, "GetMemoryChunkContext called with invalid pointer %p (header 0x%016" PRIx64 ")",
321 : pointer, GetMemoryChunkHeader(pointer));
322 : return NULL; /* keep compiler quiet */
323 : }
324 :
325 : static Size
326 0 : BogusGetChunkSpace(void *pointer)
327 : {
328 0 : elog(ERROR, "GetMemoryChunkSpace called with invalid pointer %p (header 0x%016" PRIx64 ")",
329 : pointer, GetMemoryChunkHeader(pointer));
330 : return 0; /* keep compiler quiet */
331 : }
332 :
333 :
334 : /*****************************************************************************
335 : * EXPORTED ROUTINES *
336 : *****************************************************************************/
337 :
338 :
339 : /*
340 : * MemoryContextInit
341 : * Start up the memory-context subsystem.
342 : *
343 : * This must be called before creating contexts or allocating memory in
344 : * contexts. TopMemoryContext and ErrorContext are initialized here;
345 : * other contexts must be created afterwards.
346 : *
347 : * In normal multi-backend operation, this is called once during
348 : * postmaster startup, and not at all by individual backend startup
349 : * (since the backends inherit an already-initialized context subsystem
350 : * by virtue of being forked off the postmaster). But in an EXEC_BACKEND
351 : * build, each process must do this for itself.
352 : *
353 : * In a standalone backend this must be called during backend startup.
354 : */
355 : void
356 3730 : MemoryContextInit(void)
357 : {
358 : Assert(TopMemoryContext == NULL);
359 :
360 : /*
361 : * First, initialize TopMemoryContext, which is the parent of all others.
362 : */
363 3730 : TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
364 : "TopMemoryContext",
365 : ALLOCSET_DEFAULT_SIZES);
366 :
367 : /*
368 : * Not having any other place to point CurrentMemoryContext, make it point
369 : * to TopMemoryContext. Caller should change this soon!
370 : */
371 3730 : CurrentMemoryContext = TopMemoryContext;
372 :
373 : /*
374 : * Initialize ErrorContext as an AllocSetContext with slow growth rate ---
375 : * we don't really expect much to be allocated in it. More to the point,
376 : * require it to contain at least 8K at all times. This is the only case
377 : * where retained memory in a context is *essential* --- we want to be
378 : * sure ErrorContext still has some memory even if we've run out
379 : * elsewhere! Also, allow allocations in ErrorContext within a critical
380 : * section. Otherwise a PANIC will cause an assertion failure in the error
381 : * reporting code, before printing out the real cause of the failure.
382 : *
383 : * This should be the last step in this function, as elog.c assumes memory
384 : * management works once ErrorContext is non-null.
385 : */
386 3730 : ErrorContext = AllocSetContextCreate(TopMemoryContext,
387 : "ErrorContext",
388 : 8 * 1024,
389 : 8 * 1024,
390 : 8 * 1024);
391 3730 : MemoryContextAllowInCriticalSection(ErrorContext, true);
392 3730 : }
393 :
394 : /*
395 : * MemoryContextReset
396 : * Release all space allocated within a context and delete all its
397 : * descendant contexts (but not the named context itself).
398 : */
399 : void
400 324133936 : MemoryContextReset(MemoryContext context)
401 : {
402 : Assert(MemoryContextIsValid(context));
403 :
404 : /* save a function call in common case where there are no children */
405 324133936 : if (context->firstchild != NULL)
406 745286 : MemoryContextDeleteChildren(context);
407 :
408 : /* save a function call if no pallocs since startup or last reset */
409 324133936 : if (!context->isReset)
410 45591202 : MemoryContextResetOnly(context);
411 324133936 : }
412 :
413 : /*
414 : * MemoryContextResetOnly
415 : * Release all space allocated within a context.
416 : * Nothing is done to the context's descendant contexts.
417 : */
418 : void
419 51468962 : MemoryContextResetOnly(MemoryContext context)
420 : {
421 : Assert(MemoryContextIsValid(context));
422 :
423 : /* Nothing to do if no pallocs since startup or last reset */
424 51468962 : if (!context->isReset)
425 : {
426 51467780 : MemoryContextCallResetCallbacks(context);
427 :
428 : /*
429 : * If context->ident points into the context's memory, it will become
430 : * a dangling pointer. We could prevent that by setting it to NULL
431 : * here, but that would break valid coding patterns that keep the
432 : * ident elsewhere, e.g. in a parent context. So for now we assume
433 : * the programmer got it right.
434 : */
435 :
436 51467780 : context->methods->reset(context);
437 51467780 : context->isReset = true;
438 : }
439 51468962 : }
440 :
441 : /*
442 : * MemoryContextResetChildren
443 : * Release all space allocated within a context's descendants,
444 : * but don't delete the contexts themselves. The named context
445 : * itself is not touched.
446 : */
447 : void
448 0 : MemoryContextResetChildren(MemoryContext context)
449 : {
450 : Assert(MemoryContextIsValid(context));
451 :
452 0 : for (MemoryContext curr = context->firstchild;
453 0 : curr != NULL;
454 0 : curr = MemoryContextTraverseNext(curr, context))
455 : {
456 0 : MemoryContextResetOnly(curr);
457 : }
458 0 : }
459 :
460 : /*
461 : * MemoryContextDelete
462 : * Delete a context and its descendants, and release all space
463 : * allocated therein.
464 : *
465 : * The type-specific delete routine removes all storage for the context,
466 : * but we have to deal with descendant nodes here.
467 : */
468 : void
469 9458004 : MemoryContextDelete(MemoryContext context)
470 : {
471 : MemoryContext curr;
472 :
473 : Assert(MemoryContextIsValid(context));
474 :
475 : /*
476 : * Delete subcontexts from the bottom up.
477 : *
478 : * Note: Do not use recursion here. A "stack depth limit exceeded" error
479 : * would be unpleasant if we're already in the process of cleaning up from
480 : * transaction abort. We also cannot use MemoryContextTraverseNext() here
481 : * because we modify the tree as we go.
482 : */
483 9458004 : curr = context;
484 : for (;;)
485 1923994 : {
486 : MemoryContext parent;
487 :
488 : /* Descend down until we find a leaf context with no children */
489 13305992 : while (curr->firstchild != NULL)
490 1923994 : curr = curr->firstchild;
491 :
492 : /*
493 : * We're now at a leaf with no children. Free it and continue from the
494 : * parent. Or if this was the original node, we're all done.
495 : */
496 11381998 : parent = curr->parent;
497 11381998 : MemoryContextDeleteOnly(curr);
498 :
499 11381998 : if (curr == context)
500 9458004 : break;
501 1923994 : curr = parent;
502 : }
503 9458004 : }
504 :
505 : /*
506 : * Subroutine of MemoryContextDelete,
507 : * to delete a context that has no children.
508 : * We must also delink the context from its parent, if it has one.
509 : */
510 : static void
511 11381998 : MemoryContextDeleteOnly(MemoryContext context)
512 : {
513 : Assert(MemoryContextIsValid(context));
514 : /* We had better not be deleting TopMemoryContext ... */
515 : Assert(context != TopMemoryContext);
516 : /* And not CurrentMemoryContext, either */
517 : Assert(context != CurrentMemoryContext);
518 : /* All the children should've been deleted already */
519 : Assert(context->firstchild == NULL);
520 :
521 : /*
522 : * It's not entirely clear whether 'tis better to do this before or after
523 : * delinking the context; but an error in a callback will likely result in
524 : * leaking the whole context (if it's not a root context) if we do it
525 : * after, so let's do it before.
526 : */
527 11381998 : MemoryContextCallResetCallbacks(context);
528 :
529 : /*
530 : * We delink the context from its parent before deleting it, so that if
531 : * there's an error we won't have deleted/busted contexts still attached
532 : * to the context tree. Better a leak than a crash.
533 : */
534 11381998 : MemoryContextSetParent(context, NULL);
535 :
536 : /*
537 : * Also reset the context's ident pointer, in case it points into the
538 : * context. This would only matter if someone tries to get stats on the
539 : * (already unlinked) context, which is unlikely, but let's be safe.
540 : */
541 11381998 : context->ident = NULL;
542 :
543 11381998 : context->methods->delete_context(context);
544 11381998 : }
545 :
546 : /*
547 : * MemoryContextDeleteChildren
548 : * Delete all the descendants of the named context and release all
549 : * space allocated therein. The named context itself is not touched.
550 : */
551 : void
552 1171738 : MemoryContextDeleteChildren(MemoryContext context)
553 : {
554 : Assert(MemoryContextIsValid(context));
555 :
556 : /*
557 : * MemoryContextDelete will delink the child from me, so just iterate as
558 : * long as there is a child.
559 : */
560 1992842 : while (context->firstchild != NULL)
561 821104 : MemoryContextDelete(context->firstchild);
562 1171738 : }
563 :
564 : /*
565 : * MemoryContextRegisterResetCallback
566 : * Register a function to be called before next context reset/delete.
567 : * Such callbacks will be called in reverse order of registration.
568 : *
569 : * The caller is responsible for allocating a MemoryContextCallback struct
570 : * to hold the info about this callback request, and for filling in the
571 : * "func" and "arg" fields in the struct to show what function to call with
572 : * what argument. Typically the callback struct should be allocated within
573 : * the specified context, since that means it will automatically be freed
574 : * when no longer needed.
575 : *
576 : * Note that callers can assume this cannot fail.
577 : */
578 : void
579 104476 : MemoryContextRegisterResetCallback(MemoryContext context,
580 : MemoryContextCallback *cb)
581 : {
582 : Assert(MemoryContextIsValid(context));
583 :
584 : /* Push onto head so this will be called before older registrants. */
585 104476 : cb->next = context->reset_cbs;
586 104476 : context->reset_cbs = cb;
587 : /* Mark the context as non-reset (it probably is already). */
588 104476 : context->isReset = false;
589 104476 : }
590 :
591 : /*
592 : * MemoryContextUnregisterResetCallback
593 : * Undo the effects of MemoryContextRegisterResetCallback.
594 : *
595 : * This can be used if a callback's effects are no longer required
596 : * at some point before the context has been reset/deleted. It is the
597 : * caller's responsibility to pfree the callback struct (if needed).
598 : *
599 : * An assertion failure occurs if the callback was not registered.
600 : * We could alternatively define that case as a no-op, but that seems too
601 : * likely to mask programming errors such as passing the wrong context.
602 : */
603 : void
604 26040 : MemoryContextUnregisterResetCallback(MemoryContext context,
605 : MemoryContextCallback *cb)
606 : {
607 : MemoryContextCallback *prev,
608 : *cur;
609 :
610 : Assert(MemoryContextIsValid(context));
611 :
612 26070 : for (prev = NULL, cur = context->reset_cbs; cur != NULL;
613 30 : prev = cur, cur = cur->next)
614 : {
615 26070 : if (cur != cb)
616 30 : continue;
617 26040 : if (prev)
618 30 : prev->next = cur->next;
619 : else
620 26010 : context->reset_cbs = cur->next;
621 26040 : return;
622 : }
623 : Assert(false);
624 : }
625 :
626 : /*
627 : * MemoryContextCallResetCallbacks
628 : * Internal function to call all registered callbacks for context.
629 : */
630 : static void
631 62849778 : MemoryContextCallResetCallbacks(MemoryContext context)
632 : {
633 : MemoryContextCallback *cb;
634 :
635 : /*
636 : * We pop each callback from the list before calling. That way, if an
637 : * error occurs inside the callback, we won't try to call it a second time
638 : * in the likely event that we reset or delete the context later.
639 : */
640 62928178 : while ((cb = context->reset_cbs) != NULL)
641 : {
642 78400 : context->reset_cbs = cb->next;
643 78400 : cb->func(cb->arg);
644 : }
645 62849778 : }
646 :
647 : /*
648 : * MemoryContextSetIdentifier
649 : * Set the identifier string for a memory context.
650 : *
651 : * An identifier can be provided to help distinguish among different contexts
652 : * of the same kind in memory context stats dumps. The identifier string
653 : * must live at least as long as the context it is for; typically it is
654 : * allocated inside that context, so that it automatically goes away on
655 : * context deletion. Pass id = NULL to forget any old identifier.
656 : */
657 : void
658 4928878 : MemoryContextSetIdentifier(MemoryContext context, const char *id)
659 : {
660 : Assert(MemoryContextIsValid(context));
661 4928878 : context->ident = id;
662 4928878 : }
663 :
664 : /*
665 : * MemoryContextSetParent
666 : * Change a context to belong to a new parent (or no parent).
667 : *
668 : * We provide this as an API function because it is sometimes useful to
669 : * change a context's lifespan after creation. For example, a context
670 : * might be created underneath a transient context, filled with data,
671 : * and then reparented underneath CacheMemoryContext to make it long-lived.
672 : * In this way no special effort is needed to get rid of the context in case
673 : * a failure occurs before its contents are completely set up.
674 : *
675 : * Callers often assume that this function cannot fail, so don't put any
676 : * elog(ERROR) calls in it.
677 : *
678 : * A possible caller error is to reparent a context under itself, creating
679 : * a loop in the context graph. We assert here that context != new_parent,
680 : * but checking for multi-level loops seems more trouble than it's worth.
681 : */
682 : void
683 11667856 : MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
684 : {
685 : Assert(MemoryContextIsValid(context));
686 : Assert(context != new_parent);
687 :
688 : /* Fast path if it's got correct parent already */
689 11667856 : if (new_parent == context->parent)
690 9408 : return;
691 :
692 : /* Delink from existing parent, if any */
693 11658448 : if (context->parent)
694 : {
695 11658448 : MemoryContext parent = context->parent;
696 :
697 11658448 : if (context->prevchild != NULL)
698 1096898 : context->prevchild->nextchild = context->nextchild;
699 : else
700 : {
701 : Assert(parent->firstchild == context);
702 10561550 : parent->firstchild = context->nextchild;
703 : }
704 :
705 11658448 : if (context->nextchild != NULL)
706 5014186 : context->nextchild->prevchild = context->prevchild;
707 : }
708 :
709 : /* And relink */
710 11658448 : if (new_parent)
711 : {
712 : Assert(MemoryContextIsValid(new_parent));
713 276450 : context->parent = new_parent;
714 276450 : context->prevchild = NULL;
715 276450 : context->nextchild = new_parent->firstchild;
716 276450 : if (new_parent->firstchild != NULL)
717 252588 : new_parent->firstchild->prevchild = context;
718 276450 : new_parent->firstchild = context;
719 : }
720 : else
721 : {
722 11381998 : context->parent = NULL;
723 11381998 : context->prevchild = NULL;
724 11381998 : context->nextchild = NULL;
725 : }
726 : }
727 :
728 : /*
729 : * MemoryContextAllowInCriticalSection
730 : * Allow/disallow allocations in this memory context within a critical
731 : * section.
732 : *
733 : * Normally, memory allocations are not allowed within a critical section,
734 : * because a failure would lead to PANIC. There are a few exceptions to
735 : * that, like allocations related to debugging code that is not supposed to
736 : * be enabled in production. This function can be used to exempt specific
737 : * memory contexts from the assertion in palloc().
738 : */
739 : void
740 4986 : MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
741 : {
742 : Assert(MemoryContextIsValid(context));
743 :
744 4986 : context->allowInCritSection = allow;
745 4986 : }
746 :
747 : /*
748 : * GetMemoryChunkContext
749 : * Given a currently-allocated chunk, determine the MemoryContext that
750 : * the chunk belongs to.
751 : */
752 : MemoryContext
753 3527908 : GetMemoryChunkContext(void *pointer)
754 : {
755 3527908 : return MCXT_METHOD(pointer, get_chunk_context) (pointer);
756 : }
757 :
758 : /*
759 : * GetMemoryChunkSpace
760 : * Given a currently-allocated chunk, determine the total space
761 : * it occupies (including all memory-allocation overhead).
762 : *
763 : * This is useful for measuring the total space occupied by a set of
764 : * allocated chunks.
765 : */
766 : Size
767 40353944 : GetMemoryChunkSpace(void *pointer)
768 : {
769 40353944 : return MCXT_METHOD(pointer, get_chunk_space) (pointer);
770 : }
771 :
772 : /*
773 : * MemoryContextGetParent
774 : * Get the parent context (if any) of the specified context
775 : */
776 : MemoryContext
777 17464 : MemoryContextGetParent(MemoryContext context)
778 : {
779 : Assert(MemoryContextIsValid(context));
780 :
781 17464 : return context->parent;
782 : }
783 :
784 : /*
785 : * MemoryContextIsEmpty
786 : * Is a memory context empty of any allocated space?
787 : */
788 : bool
789 10724 : MemoryContextIsEmpty(MemoryContext context)
790 : {
791 : Assert(MemoryContextIsValid(context));
792 :
793 : /*
794 : * For now, we consider a memory context nonempty if it has any children;
795 : * perhaps this should be changed later.
796 : */
797 10724 : if (context->firstchild != NULL)
798 4 : return false;
799 : /* Otherwise use the type-specific inquiry */
800 10720 : return context->methods->is_empty(context);
801 : }
802 :
803 : /*
804 : * Find the memory allocated to blocks for this memory context. If recurse is
805 : * true, also include children.
806 : */
807 : Size
808 1828476 : MemoryContextMemAllocated(MemoryContext context, bool recurse)
809 : {
810 1828476 : Size total = context->mem_allocated;
811 :
812 : Assert(MemoryContextIsValid(context));
813 :
814 1828476 : if (recurse)
815 : {
816 1828476 : for (MemoryContext curr = context->firstchild;
817 3108190 : curr != NULL;
818 1279714 : curr = MemoryContextTraverseNext(curr, context))
819 : {
820 1279714 : total += curr->mem_allocated;
821 : }
822 : }
823 :
824 1828476 : return total;
825 : }
826 :
827 : /*
828 : * Return the memory consumption statistics about the given context and its
829 : * children.
830 : */
831 : void
832 30 : MemoryContextMemConsumed(MemoryContext context,
833 : MemoryContextCounters *consumed)
834 : {
835 : Assert(MemoryContextIsValid(context));
836 :
837 30 : memset(consumed, 0, sizeof(*consumed));
838 :
839 : /* Examine the context itself */
840 30 : context->methods->stats(context, NULL, NULL, consumed, false);
841 :
842 : /* Examine children, using iteration not recursion */
843 30 : for (MemoryContext curr = context->firstchild;
844 30 : curr != NULL;
845 0 : curr = MemoryContextTraverseNext(curr, context))
846 : {
847 0 : curr->methods->stats(curr, NULL, NULL, consumed, false);
848 : }
849 30 : }
850 :
851 : /*
852 : * MemoryContextStats
853 : * Print statistics about the named context and all its descendants.
854 : *
855 : * This is just a debugging utility, so it's not very fancy. However, we do
856 : * make some effort to summarize when the output would otherwise be very long.
857 : * The statistics are sent to stderr.
858 : */
859 : void
860 0 : MemoryContextStats(MemoryContext context)
861 : {
862 : /* Hard-wired limits are usually good enough */
863 0 : MemoryContextStatsDetail(context, 100, 100, true);
864 0 : }
865 :
866 : /*
867 : * MemoryContextStatsDetail
868 : *
869 : * Entry point for use if you want to vary the number of child contexts shown.
870 : *
871 : * If print_to_stderr is true, print statistics about the memory contexts
872 : * with fprintf(stderr), otherwise use ereport().
873 : */
874 : void
875 18 : MemoryContextStatsDetail(MemoryContext context,
876 : int max_level, int max_children,
877 : bool print_to_stderr)
878 : {
879 : MemoryContextCounters grand_totals;
880 :
881 18 : memset(&grand_totals, 0, sizeof(grand_totals));
882 :
883 18 : MemoryContextStatsInternal(context, 1, max_level, max_children,
884 : &grand_totals, print_to_stderr);
885 :
886 18 : if (print_to_stderr)
887 0 : fprintf(stderr,
888 : "Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used\n",
889 : grand_totals.totalspace, grand_totals.nblocks,
890 : grand_totals.freespace, grand_totals.freechunks,
891 0 : grand_totals.totalspace - grand_totals.freespace);
892 : else
893 : {
894 : /*
895 : * Use LOG_SERVER_ONLY to prevent the memory contexts from being sent
896 : * to the connected client.
897 : *
898 : * We don't buffer the information about all memory contexts in a
899 : * backend into StringInfo and log it as one message. That would
900 : * require the buffer to be enlarged, risking an OOM as there could be
901 : * a large number of memory contexts in a backend. Instead, we log
902 : * one message per memory context.
903 : */
904 18 : ereport(LOG_SERVER_ONLY,
905 : (errhidestmt(true),
906 : errhidecontext(true),
907 : errmsg_internal("Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used",
908 : grand_totals.totalspace, grand_totals.nblocks,
909 : grand_totals.freespace, grand_totals.freechunks,
910 : grand_totals.totalspace - grand_totals.freespace)));
911 : }
912 18 : }
913 :
914 : /*
915 : * MemoryContextStatsInternal
916 : * One recursion level for MemoryContextStats
917 : *
918 : * Print stats for this context if possible, but in any case accumulate counts
919 : * into *totals (if not NULL).
920 : */
921 : static void
922 1620 : MemoryContextStatsInternal(MemoryContext context, int level,
923 : int max_level, int max_children,
924 : MemoryContextCounters *totals,
925 : bool print_to_stderr)
926 : {
927 : MemoryContext child;
928 : int ichild;
929 :
930 : Assert(MemoryContextIsValid(context));
931 :
932 : /* Examine the context itself */
933 1620 : context->methods->stats(context,
934 : MemoryContextStatsPrint,
935 : &level,
936 : totals, print_to_stderr);
937 :
938 : /*
939 : * Examine children.
940 : *
941 : * If we are past the recursion depth limit or already running low on
942 : * stack, do not print them explicitly but just summarize them. Similarly,
943 : * if there are more than max_children of them, we do not print the rest
944 : * explicitly, but just summarize them.
945 : */
946 1620 : child = context->firstchild;
947 1620 : ichild = 0;
948 1620 : if (level <= max_level && !stack_is_too_deep())
949 : {
950 3222 : for (; child != NULL && ichild < max_children;
951 1602 : child = child->nextchild, ichild++)
952 : {
953 1602 : MemoryContextStatsInternal(child, level + 1,
954 : max_level, max_children,
955 : totals,
956 : print_to_stderr);
957 : }
958 : }
959 :
960 1620 : if (child != NULL)
961 : {
962 : /* Summarize the rest of the children, avoiding recursion. */
963 : MemoryContextCounters local_totals;
964 :
965 0 : memset(&local_totals, 0, sizeof(local_totals));
966 :
967 0 : ichild = 0;
968 0 : while (child != NULL)
969 : {
970 0 : child->methods->stats(child, NULL, NULL, &local_totals, false);
971 0 : ichild++;
972 0 : child = MemoryContextTraverseNext(child, context);
973 : }
974 :
975 0 : if (print_to_stderr)
976 : {
977 0 : for (int i = 0; i < level; i++)
978 0 : fprintf(stderr, " ");
979 0 : fprintf(stderr,
980 : "%d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used\n",
981 : ichild,
982 : local_totals.totalspace,
983 : local_totals.nblocks,
984 : local_totals.freespace,
985 : local_totals.freechunks,
986 0 : local_totals.totalspace - local_totals.freespace);
987 : }
988 : else
989 0 : ereport(LOG_SERVER_ONLY,
990 : (errhidestmt(true),
991 : errhidecontext(true),
992 : errmsg_internal("level: %d; %d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used",
993 : level,
994 : ichild,
995 : local_totals.totalspace,
996 : local_totals.nblocks,
997 : local_totals.freespace,
998 : local_totals.freechunks,
999 : local_totals.totalspace - local_totals.freespace)));
1000 :
1001 0 : if (totals)
1002 : {
1003 0 : totals->nblocks += local_totals.nblocks;
1004 0 : totals->freechunks += local_totals.freechunks;
1005 0 : totals->totalspace += local_totals.totalspace;
1006 0 : totals->freespace += local_totals.freespace;
1007 : }
1008 : }
1009 1620 : }
1010 :
1011 : /*
1012 : * MemoryContextStatsPrint
1013 : * Print callback used by MemoryContextStatsInternal
1014 : *
1015 : * For now, the passthru pointer just points to "int level"; later we might
1016 : * make that more complicated.
1017 : */
1018 : static void
1019 1620 : MemoryContextStatsPrint(MemoryContext context, void *passthru,
1020 : const char *stats_string,
1021 : bool print_to_stderr)
1022 : {
1023 1620 : int level = *(int *) passthru;
1024 1620 : const char *name = context->name;
1025 1620 : const char *ident = context->ident;
1026 : char truncated_ident[110];
1027 : int i;
1028 :
1029 : /*
1030 : * It seems preferable to label dynahash contexts with just the hash table
1031 : * name. Those are already unique enough, so the "dynahash" part isn't
1032 : * very helpful, and this way is more consistent with pre-v11 practice.
1033 : */
1034 1620 : if (ident && strcmp(name, "dynahash") == 0)
1035 : {
1036 210 : name = ident;
1037 210 : ident = NULL;
1038 : }
1039 :
1040 1620 : truncated_ident[0] = '\0';
1041 :
1042 1620 : if (ident)
1043 : {
1044 : /*
1045 : * Some contexts may have very long identifiers (e.g., SQL queries).
1046 : * Arbitrarily truncate at 100 bytes, but be careful not to break
1047 : * multibyte characters. Also, replace ASCII control characters, such
1048 : * as newlines, with spaces.
1049 : */
1050 1140 : int idlen = strlen(ident);
1051 1140 : bool truncated = false;
1052 :
1053 1140 : strcpy(truncated_ident, ": ");
1054 1140 : i = strlen(truncated_ident);
1055 :
1056 1140 : if (idlen > 100)
1057 : {
1058 0 : idlen = pg_mbcliplen(ident, idlen, 100);
1059 0 : truncated = true;
1060 : }
1061 :
1062 31866 : while (idlen-- > 0)
1063 : {
1064 30726 : unsigned char c = *ident++;
1065 :
1066 30726 : if (c < ' ')
1067 0 : c = ' ';
1068 30726 : truncated_ident[i++] = c;
1069 : }
1070 1140 : truncated_ident[i] = '\0';
1071 :
1072 1140 : if (truncated)
1073 0 : strcat(truncated_ident, "...");
1074 : }
1075 :
1076 1620 : if (print_to_stderr)
1077 : {
1078 0 : for (i = 1; i < level; i++)
1079 0 : fprintf(stderr, " ");
1080 0 : fprintf(stderr, "%s: %s%s\n", name, stats_string, truncated_ident);
1081 : }
1082 : else
1083 1620 : ereport(LOG_SERVER_ONLY,
1084 : (errhidestmt(true),
1085 : errhidecontext(true),
1086 : errmsg_internal("level: %d; %s: %s%s",
1087 : level, name, stats_string, truncated_ident)));
1088 1620 : }
1089 :
1090 : /*
1091 : * MemoryContextCheck
1092 : * Check all chunks in the named context and its children.
1093 : *
1094 : * This is just a debugging utility, so it's not fancy.
1095 : */
1096 : #ifdef MEMORY_CONTEXT_CHECKING
1097 : void
1098 : MemoryContextCheck(MemoryContext context)
1099 : {
1100 : Assert(MemoryContextIsValid(context));
1101 : context->methods->check(context);
1102 :
1103 : for (MemoryContext curr = context->firstchild;
1104 : curr != NULL;
1105 : curr = MemoryContextTraverseNext(curr, context))
1106 : {
1107 : Assert(MemoryContextIsValid(curr));
1108 : curr->methods->check(curr);
1109 : }
1110 : }
1111 : #endif
1112 :
1113 : /*
1114 : * MemoryContextCreate
1115 : * Context-type-independent part of context creation.
1116 : *
1117 : * This is only intended to be called by context-type-specific
1118 : * context creation routines, not by the unwashed masses.
1119 : *
1120 : * The memory context creation procedure goes like this:
1121 : * 1. Context-type-specific routine makes some initial space allocation,
1122 : * including enough space for the context header. If it fails,
1123 : * it can ereport() with no damage done.
1124 : * 2. Context-type-specific routine sets up all type-specific fields of
1125 : * the header (those beyond MemoryContextData proper), as well as any
1126 : * other management fields it needs to have a fully valid context.
1127 : * Usually, failure in this step is impossible, but if it's possible
1128 : * the initial space allocation should be freed before ereport'ing.
1129 : * 3. Context-type-specific routine calls MemoryContextCreate() to fill in
1130 : * the generic header fields and link the context into the context tree.
1131 : * 4. We return to the context-type-specific routine, which finishes
1132 : * up type-specific initialization. This routine can now do things
1133 : * that might fail (like allocate more memory), so long as it's
1134 : * sure the node is left in a state that delete will handle.
1135 : *
1136 : * node: the as-yet-uninitialized common part of the context header node.
1137 : * tag: NodeTag code identifying the memory context type.
1138 : * method_id: MemoryContextMethodID of the context-type being created.
1139 : * parent: parent context, or NULL if this will be a top-level context.
1140 : * name: name of context (must be statically allocated).
1141 : *
1142 : * Context routines generally assume that MemoryContextCreate can't fail,
1143 : * so this can contain Assert but not elog/ereport.
1144 : */
1145 : void
1146 15080958 : MemoryContextCreate(MemoryContext node,
1147 : NodeTag tag,
1148 : MemoryContextMethodID method_id,
1149 : MemoryContext parent,
1150 : const char *name)
1151 : {
1152 : /* Creating new memory contexts is not allowed in a critical section */
1153 : Assert(CritSectionCount == 0);
1154 :
1155 : /* Validate parent, to help prevent crazy context linkages */
1156 : Assert(parent == NULL || MemoryContextIsValid(parent));
1157 : Assert(node != parent);
1158 :
1159 : /* Initialize all standard fields of memory context header */
1160 15080958 : node->type = tag;
1161 15080958 : node->isReset = true;
1162 15080958 : node->methods = &mcxt_methods[method_id];
1163 15080958 : node->parent = parent;
1164 15080958 : node->firstchild = NULL;
1165 15080958 : node->mem_allocated = 0;
1166 15080958 : node->prevchild = NULL;
1167 15080958 : node->name = name;
1168 15080958 : node->ident = NULL;
1169 15080958 : node->reset_cbs = NULL;
1170 :
1171 : /* OK to link node into context tree */
1172 15080958 : if (parent)
1173 : {
1174 15077128 : node->nextchild = parent->firstchild;
1175 15077128 : if (parent->firstchild != NULL)
1176 8556178 : parent->firstchild->prevchild = node;
1177 15077128 : parent->firstchild = node;
1178 : /* inherit allowInCritSection flag from parent */
1179 15077128 : node->allowInCritSection = parent->allowInCritSection;
1180 : }
1181 : else
1182 : {
1183 3830 : node->nextchild = NULL;
1184 3830 : node->allowInCritSection = false;
1185 : }
1186 15080958 : }
1187 :
1188 : /*
1189 : * MemoryContextAllocationFailure
1190 : * For use by MemoryContextMethods implementations to handle when malloc
1191 : * returns NULL. The behavior is specific to whether MCXT_ALLOC_NO_OOM
1192 : * is in 'flags'.
1193 : */
1194 : void *
1195 0 : MemoryContextAllocationFailure(MemoryContext context, Size size, int flags)
1196 : {
1197 0 : if ((flags & MCXT_ALLOC_NO_OOM) == 0)
1198 : {
1199 0 : if (TopMemoryContext)
1200 0 : MemoryContextStats(TopMemoryContext);
1201 0 : ereport(ERROR,
1202 : (errcode(ERRCODE_OUT_OF_MEMORY),
1203 : errmsg("out of memory"),
1204 : errdetail("Failed on request of size %zu in memory context \"%s\".",
1205 : size, context->name)));
1206 : }
1207 0 : return NULL;
1208 : }
1209 :
1210 : /*
1211 : * MemoryContextSizeFailure
1212 : * For use by MemoryContextMethods implementations to handle invalid
1213 : * memory allocation request sizes.
1214 : */
1215 : void
1216 0 : MemoryContextSizeFailure(MemoryContext context, Size size, int flags)
1217 : {
1218 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
1219 : }
1220 :
1221 : /*
1222 : * MemoryContextAlloc
1223 : * Allocate space within the specified context.
1224 : *
1225 : * This could be turned into a macro, but we'd have to import
1226 : * nodes/memnodes.h into postgres.h which seems a bad idea.
1227 : */
1228 : void *
1229 186639524 : MemoryContextAlloc(MemoryContext context, Size size)
1230 : {
1231 : void *ret;
1232 :
1233 : Assert(MemoryContextIsValid(context));
1234 : AssertNotInCriticalSection(context);
1235 :
1236 186639524 : context->isReset = false;
1237 :
1238 : /*
1239 : * For efficiency reasons, we purposefully offload the handling of
1240 : * allocation failures to the MemoryContextMethods implementation as this
1241 : * allows these checks to be performed only when an actual malloc needs to
1242 : * be done to request more memory from the OS. Additionally, not having
1243 : * to execute any instructions after this call allows the compiler to use
1244 : * the sibling call optimization. If you're considering adding code after
1245 : * this call, consider making it the responsibility of the 'alloc'
1246 : * function instead.
1247 : */
1248 186639524 : ret = context->methods->alloc(context, size, 0);
1249 :
1250 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1251 :
1252 186639524 : return ret;
1253 : }
1254 :
1255 : /*
1256 : * MemoryContextAllocZero
1257 : * Like MemoryContextAlloc, but clears allocated memory
1258 : *
1259 : * We could just call MemoryContextAlloc then clear the memory, but this
1260 : * is a very common combination, so we provide the combined operation.
1261 : */
1262 : void *
1263 44541948 : MemoryContextAllocZero(MemoryContext context, Size size)
1264 : {
1265 : void *ret;
1266 :
1267 : Assert(MemoryContextIsValid(context));
1268 : AssertNotInCriticalSection(context);
1269 :
1270 44541948 : context->isReset = false;
1271 :
1272 44541948 : ret = context->methods->alloc(context, size, 0);
1273 :
1274 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1275 :
1276 560812664 : MemSetAligned(ret, 0, size);
1277 :
1278 44541948 : return ret;
1279 : }
1280 :
1281 : /*
1282 : * MemoryContextAllocExtended
1283 : * Allocate space within the specified context using the given flags.
1284 : */
1285 : void *
1286 8252124 : MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
1287 : {
1288 : void *ret;
1289 :
1290 : Assert(MemoryContextIsValid(context));
1291 : AssertNotInCriticalSection(context);
1292 :
1293 8252124 : if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) :
1294 : AllocSizeIsValid(size)))
1295 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
1296 :
1297 8252124 : context->isReset = false;
1298 :
1299 8252124 : ret = context->methods->alloc(context, size, flags);
1300 8252124 : if (unlikely(ret == NULL))
1301 0 : return NULL;
1302 :
1303 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1304 :
1305 8252124 : if ((flags & MCXT_ALLOC_ZERO) != 0)
1306 669038 : MemSetAligned(ret, 0, size);
1307 :
1308 8252124 : return ret;
1309 : }
1310 :
1311 : /*
1312 : * HandleLogMemoryContextInterrupt
1313 : * Handle receipt of an interrupt indicating logging of memory
1314 : * contexts.
1315 : *
1316 : * All the actual work is deferred to ProcessLogMemoryContextInterrupt(),
1317 : * because we cannot safely emit a log message inside the signal handler.
1318 : */
1319 : void
1320 18 : HandleLogMemoryContextInterrupt(void)
1321 : {
1322 18 : InterruptPending = true;
1323 18 : LogMemoryContextPending = true;
1324 : /* latch will be set by procsignal_sigusr1_handler */
1325 18 : }
1326 :
1327 : /*
1328 : * ProcessLogMemoryContextInterrupt
1329 : * Perform logging of memory contexts of this backend process.
1330 : *
1331 : * Any backend that participates in ProcSignal signaling must arrange
1332 : * to call this function if we see LogMemoryContextPending set.
1333 : * It is called from CHECK_FOR_INTERRUPTS(), which is enough because
1334 : * the target process for logging of memory contexts is a backend.
1335 : */
1336 : void
1337 18 : ProcessLogMemoryContextInterrupt(void)
1338 : {
1339 18 : LogMemoryContextPending = false;
1340 :
1341 : /*
1342 : * Use LOG_SERVER_ONLY to prevent this message from being sent to the
1343 : * connected client.
1344 : */
1345 18 : ereport(LOG_SERVER_ONLY,
1346 : (errhidestmt(true),
1347 : errhidecontext(true),
1348 : errmsg("logging memory contexts of PID %d", MyProcPid)));
1349 :
1350 : /*
1351 : * When a backend process is consuming huge memory, logging all its memory
1352 : * contexts might overrun available disk space. To prevent this, we limit
1353 : * the depth of the hierarchy, as well as the number of child contexts to
1354 : * log per parent to 100.
1355 : *
1356 : * As with MemoryContextStats(), we suppose that practical cases where the
1357 : * dump gets long will typically be huge numbers of siblings under the
1358 : * same parent context; while the additional debugging value from seeing
1359 : * details about individual siblings beyond 100 will not be large.
1360 : */
1361 18 : MemoryContextStatsDetail(TopMemoryContext, 100, 100, false);
1362 18 : }
1363 :
1364 : void *
1365 646244616 : palloc(Size size)
1366 : {
1367 : /* duplicates MemoryContextAlloc to avoid increased overhead */
1368 : void *ret;
1369 646244616 : MemoryContext context = CurrentMemoryContext;
1370 :
1371 : Assert(MemoryContextIsValid(context));
1372 : AssertNotInCriticalSection(context);
1373 :
1374 646244616 : context->isReset = false;
1375 :
1376 : /*
1377 : * For efficiency reasons, we purposefully offload the handling of
1378 : * allocation failures to the MemoryContextMethods implementation as this
1379 : * allows these checks to be performed only when an actual malloc needs to
1380 : * be done to request more memory from the OS. Additionally, not having
1381 : * to execute any instructions after this call allows the compiler to use
1382 : * the sibling call optimization. If you're considering adding code after
1383 : * this call, consider making it the responsibility of the 'alloc'
1384 : * function instead.
1385 : */
1386 646244616 : ret = context->methods->alloc(context, size, 0);
1387 : /* We expect OOM to be handled by the alloc function */
1388 : Assert(ret != NULL);
1389 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1390 :
1391 646244616 : return ret;
1392 : }
1393 :
1394 : void *
1395 470192866 : palloc0(Size size)
1396 : {
1397 : /* duplicates MemoryContextAllocZero to avoid increased overhead */
1398 : void *ret;
1399 470192866 : MemoryContext context = CurrentMemoryContext;
1400 :
1401 : Assert(MemoryContextIsValid(context));
1402 : AssertNotInCriticalSection(context);
1403 :
1404 470192866 : context->isReset = false;
1405 :
1406 470192866 : ret = context->methods->alloc(context, size, 0);
1407 : /* We expect OOM to be handled by the alloc function */
1408 : Assert(ret != NULL);
1409 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1410 :
1411 4332939082 : MemSetAligned(ret, 0, size);
1412 :
1413 470192866 : return ret;
1414 : }
1415 :
1416 : void *
1417 23171346 : palloc_extended(Size size, int flags)
1418 : {
1419 : /* duplicates MemoryContextAllocExtended to avoid increased overhead */
1420 : void *ret;
1421 23171346 : MemoryContext context = CurrentMemoryContext;
1422 :
1423 : Assert(MemoryContextIsValid(context));
1424 : AssertNotInCriticalSection(context);
1425 :
1426 23171346 : context->isReset = false;
1427 :
1428 23171346 : ret = context->methods->alloc(context, size, flags);
1429 23171346 : if (unlikely(ret == NULL))
1430 : {
1431 : /* NULL can be returned only when using MCXT_ALLOC_NO_OOM */
1432 : Assert(flags & MCXT_ALLOC_NO_OOM);
1433 0 : return NULL;
1434 : }
1435 :
1436 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1437 :
1438 23171346 : if ((flags & MCXT_ALLOC_ZERO) != 0)
1439 5326 : MemSetAligned(ret, 0, size);
1440 :
1441 23171346 : return ret;
1442 : }
1443 :
1444 : /*
1445 : * MemoryContextAllocAligned
1446 : * Allocate 'size' bytes of memory in 'context' aligned to 'alignto'
1447 : * bytes.
1448 : *
1449 : * Currently, we align addresses by requesting additional bytes from the
1450 : * MemoryContext's standard allocator function and then aligning the returned
1451 : * address by the required alignment. This means that the given MemoryContext
1452 : * must support providing us with a chunk of memory that's larger than 'size'.
1453 : * For allocators such as Slab, that's not going to work, as slab only allows
1454 : * chunks of the size that's specified when the context is created.
1455 : *
1456 : * 'alignto' must be a power of 2.
1457 : * 'flags' may be 0 or set the same as MemoryContextAllocExtended().
1458 : */
1459 : void *
1460 3333294 : MemoryContextAllocAligned(MemoryContext context,
1461 : Size size, Size alignto, int flags)
1462 : {
1463 : MemoryChunk *alignedchunk;
1464 : Size alloc_size;
1465 : void *unaligned;
1466 : void *aligned;
1467 :
1468 : /*
1469 : * Restrict alignto to ensure that it can fit into the "value" field of
1470 : * the redirection MemoryChunk, and that the distance back to the start of
1471 : * the unaligned chunk will fit into the space available for that. This
1472 : * isn't a limitation in practice, since it wouldn't make much sense to
1473 : * waste that much space.
1474 : */
1475 : Assert(alignto < (128 * 1024 * 1024));
1476 :
1477 : /* ensure alignto is a power of 2 */
1478 : Assert((alignto & (alignto - 1)) == 0);
1479 :
1480 : /*
1481 : * If the alignment requirements are less than what we already guarantee
1482 : * then just use the standard allocation function.
1483 : */
1484 3333294 : if (unlikely(alignto <= MAXIMUM_ALIGNOF))
1485 0 : return MemoryContextAllocExtended(context, size, flags);
1486 :
1487 : /*
1488 : * We implement aligned pointers by simply allocating enough memory for
1489 : * the requested size plus the alignment and an additional "redirection"
1490 : * MemoryChunk. This additional MemoryChunk is required for operations
1491 : * such as pfree when used on the pointer returned by this function. We
1492 : * use this redirection MemoryChunk in order to find the pointer to the
1493 : * memory that was returned by the MemoryContextAllocExtended call below.
1494 : * We do that by "borrowing" the block offset field and instead of using
1495 : * that to find the offset into the owning block, we use it to find the
1496 : * original allocated address.
1497 : *
1498 : * Here we must allocate enough extra memory so that we can still align
1499 : * the pointer returned by MemoryContextAllocExtended and also have enough
1500 : * space for the redirection MemoryChunk. Since allocations will already
1501 : * be at least aligned by MAXIMUM_ALIGNOF, we can subtract that amount
1502 : * from the allocation size to save a little memory.
1503 : */
1504 3333294 : alloc_size = size + PallocAlignedExtraBytes(alignto);
1505 :
1506 : #ifdef MEMORY_CONTEXT_CHECKING
1507 : /* ensure there's space for a sentinel byte */
1508 : alloc_size += 1;
1509 : #endif
1510 :
1511 : /*
1512 : * Perform the actual allocation, but do not pass down MCXT_ALLOC_ZERO.
1513 : * This ensures that wasted bytes beyond the aligned chunk do not become
1514 : * DEFINED.
1515 : */
1516 3333294 : unaligned = MemoryContextAllocExtended(context, alloc_size,
1517 : flags & ~MCXT_ALLOC_ZERO);
1518 :
1519 : /* compute the aligned pointer */
1520 3333294 : aligned = (void *) TYPEALIGN(alignto, (char *) unaligned +
1521 : sizeof(MemoryChunk));
1522 :
1523 3333294 : alignedchunk = PointerGetMemoryChunk(aligned);
1524 :
1525 : /*
1526 : * We set the redirect MemoryChunk so that the block offset calculation is
1527 : * used to point back to the 'unaligned' allocated chunk. This allows us
1528 : * to use MemoryChunkGetBlock() to find the unaligned chunk when we need
1529 : * to perform operations such as pfree() and repalloc().
1530 : *
1531 : * We store 'alignto' in the MemoryChunk's 'value' so that we know what
1532 : * the alignment was set to should we ever be asked to realloc this
1533 : * pointer.
1534 : */
1535 3333294 : MemoryChunkSetHdrMask(alignedchunk, unaligned, alignto,
1536 : MCTX_ALIGNED_REDIRECT_ID);
1537 :
1538 : /* double check we produced a correctly aligned pointer */
1539 : Assert((void *) TYPEALIGN(alignto, aligned) == aligned);
1540 :
1541 : #ifdef MEMORY_CONTEXT_CHECKING
1542 : alignedchunk->requested_size = size;
1543 : /* set mark to catch clobber of "unused" space */
1544 : set_sentinel(aligned, size);
1545 : #endif
1546 :
1547 : /*
1548 : * MemoryContextAllocExtended marked the whole unaligned chunk as a
1549 : * vchunk. Undo that, instead making just the aligned chunk be a vchunk.
1550 : * This prevents Valgrind from complaining that the vchunk is possibly
1551 : * leaked, since only pointers to the aligned chunk will exist.
1552 : *
1553 : * After these calls, the aligned chunk will be marked UNDEFINED, and all
1554 : * the rest of the unaligned chunk (the redirection chunk header, the
1555 : * padding bytes before it, and any wasted trailing bytes) will be marked
1556 : * NOACCESS, which is what we want.
1557 : */
1558 : VALGRIND_MEMPOOL_FREE(context, unaligned);
1559 : VALGRIND_MEMPOOL_ALLOC(context, aligned, size);
1560 :
1561 : /* Now zero (and make DEFINED) just the aligned chunk, if requested */
1562 3333294 : if ((flags & MCXT_ALLOC_ZERO) != 0)
1563 170815320 : MemSetAligned(aligned, 0, size);
1564 :
1565 3333294 : return aligned;
1566 : }
1567 :
1568 : /*
1569 : * palloc_aligned
1570 : * Allocate 'size' bytes returning a pointer that's aligned to the
1571 : * 'alignto' boundary.
1572 : *
1573 : * Currently, we align addresses by requesting additional bytes from the
1574 : * MemoryContext's standard allocator function and then aligning the returned
1575 : * address by the required alignment. This means that the given MemoryContext
1576 : * must support providing us with a chunk of memory that's larger than 'size'.
1577 : * For allocators such as Slab, that's not going to work, as slab only allows
1578 : * chunks of the size that's specified when the context is created.
1579 : *
1580 : * 'alignto' must be a power of 2.
1581 : * 'flags' may be 0 or set the same as MemoryContextAllocExtended().
1582 : */
1583 : void *
1584 3207854 : palloc_aligned(Size size, Size alignto, int flags)
1585 : {
1586 3207854 : return MemoryContextAllocAligned(CurrentMemoryContext, size, alignto, flags);
1587 : }
1588 :
1589 : /*
1590 : * pfree
1591 : * Release an allocated chunk.
1592 : */
1593 : void
1594 502231030 : pfree(void *pointer)
1595 : {
1596 : #ifdef USE_VALGRIND
1597 : MemoryContext context = GetMemoryChunkContext(pointer);
1598 : #endif
1599 :
1600 502231030 : MCXT_METHOD(pointer, free_p) (pointer);
1601 :
1602 : VALGRIND_MEMPOOL_FREE(context, pointer);
1603 502231030 : }
1604 :
1605 : /*
1606 : * repalloc
1607 : * Adjust the size of a previously allocated chunk.
1608 : */
1609 : void *
1610 8944034 : repalloc(void *pointer, Size size)
1611 : {
1612 : #if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
1613 : MemoryContext context = GetMemoryChunkContext(pointer);
1614 : #endif
1615 : void *ret;
1616 :
1617 : AssertNotInCriticalSection(context);
1618 :
1619 : /* isReset must be false already */
1620 : Assert(!context->isReset);
1621 :
1622 : /*
1623 : * For efficiency reasons, we purposefully offload the handling of
1624 : * allocation failures to the MemoryContextMethods implementation as this
1625 : * allows these checks to be performed only when an actual malloc needs to
1626 : * be done to request more memory from the OS. Additionally, not having
1627 : * to execute any instructions after this call allows the compiler to use
1628 : * the sibling call optimization. If you're considering adding code after
1629 : * this call, consider making it the responsibility of the 'realloc'
1630 : * function instead.
1631 : */
1632 8944034 : ret = MCXT_METHOD(pointer, realloc) (pointer, size, 0);
1633 :
1634 : VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1635 :
1636 8944034 : return ret;
1637 : }
1638 :
1639 : /*
1640 : * repalloc_extended
1641 : * Adjust the size of a previously allocated chunk,
1642 : * with HUGE and NO_OOM options.
1643 : */
1644 : void *
1645 99702 : repalloc_extended(void *pointer, Size size, int flags)
1646 : {
1647 : #if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
1648 : MemoryContext context = GetMemoryChunkContext(pointer);
1649 : #endif
1650 : void *ret;
1651 :
1652 : AssertNotInCriticalSection(context);
1653 :
1654 : /* isReset must be false already */
1655 : Assert(!context->isReset);
1656 :
1657 : /*
1658 : * For efficiency reasons, we purposefully offload the handling of
1659 : * allocation failures to the MemoryContextMethods implementation as this
1660 : * allows these checks to be performed only when an actual malloc needs to
1661 : * be done to request more memory from the OS. Additionally, not having
1662 : * to execute any instructions after this call allows the compiler to use
1663 : * the sibling call optimization. If you're considering adding code after
1664 : * this call, consider making it the responsibility of the 'realloc'
1665 : * function instead.
1666 : */
1667 99702 : ret = MCXT_METHOD(pointer, realloc) (pointer, size, flags);
1668 99702 : if (unlikely(ret == NULL))
1669 0 : return NULL;
1670 :
1671 : VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1672 :
1673 99702 : return ret;
1674 : }
1675 :
1676 : /*
1677 : * repalloc0
1678 : * Adjust the size of a previously allocated chunk and zero out the added
1679 : * space.
1680 : */
1681 : void *
1682 49666 : repalloc0(void *pointer, Size oldsize, Size size)
1683 : {
1684 : void *ret;
1685 :
1686 : /* catch wrong argument order */
1687 49666 : if (unlikely(oldsize > size))
1688 0 : elog(ERROR, "invalid repalloc0 call: oldsize %zu, new size %zu",
1689 : oldsize, size);
1690 :
1691 49666 : ret = repalloc(pointer, size);
1692 49666 : memset((char *) ret + oldsize, 0, (size - oldsize));
1693 49666 : return ret;
1694 : }
1695 :
1696 : /*
1697 : * MemoryContextAllocHuge
1698 : * Allocate (possibly-expansive) space within the specified context.
1699 : *
1700 : * See considerations in comment at MaxAllocHugeSize.
1701 : */
1702 : void *
1703 3102 : MemoryContextAllocHuge(MemoryContext context, Size size)
1704 : {
1705 : void *ret;
1706 :
1707 : Assert(MemoryContextIsValid(context));
1708 : AssertNotInCriticalSection(context);
1709 :
1710 3102 : context->isReset = false;
1711 :
1712 : /*
1713 : * For efficiency reasons, we purposefully offload the handling of
1714 : * allocation failures to the MemoryContextMethods implementation as this
1715 : * allows these checks to be performed only when an actual malloc needs to
1716 : * be done to request more memory from the OS. Additionally, not having
1717 : * to execute any instructions after this call allows the compiler to use
1718 : * the sibling call optimization. If you're considering adding code after
1719 : * this call, consider making it the responsibility of the 'alloc'
1720 : * function instead.
1721 : */
1722 3102 : ret = context->methods->alloc(context, size, MCXT_ALLOC_HUGE);
1723 :
1724 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1725 :
1726 3102 : return ret;
1727 : }
1728 :
1729 : /*
1730 : * repalloc_huge
1731 : * Adjust the size of a previously allocated chunk, permitting a large
1732 : * value. The previous allocation need not have been "huge".
1733 : */
1734 : void *
1735 98822 : repalloc_huge(void *pointer, Size size)
1736 : {
1737 : /* this one seems not worth its own implementation */
1738 98822 : return repalloc_extended(pointer, size, MCXT_ALLOC_HUGE);
1739 : }
1740 :
1741 : /*
1742 : * MemoryContextStrdup
1743 : * Like strdup(), but allocate from the specified context
1744 : */
1745 : char *
1746 88773394 : MemoryContextStrdup(MemoryContext context, const char *string)
1747 : {
1748 : char *nstr;
1749 88773394 : Size len = strlen(string) + 1;
1750 :
1751 88773394 : nstr = (char *) MemoryContextAlloc(context, len);
1752 :
1753 88773394 : memcpy(nstr, string, len);
1754 :
1755 88773394 : return nstr;
1756 : }
1757 :
1758 : char *
1759 85012442 : pstrdup(const char *in)
1760 : {
1761 85012442 : return MemoryContextStrdup(CurrentMemoryContext, in);
1762 : }
1763 :
1764 : /*
1765 : * pnstrdup
1766 : * Like pstrdup(), but append null byte to a
1767 : * not-necessarily-null-terminated input string.
1768 : */
1769 : char *
1770 1210354 : pnstrdup(const char *in, Size len)
1771 : {
1772 : char *out;
1773 :
1774 1210354 : len = strnlen(in, len);
1775 :
1776 1210354 : out = palloc(len + 1);
1777 1210354 : memcpy(out, in, len);
1778 1210354 : out[len] = '\0';
1779 :
1780 1210354 : return out;
1781 : }
1782 :
1783 : /*
1784 : * Make copy of string with all trailing newline characters removed.
1785 : */
1786 : char *
1787 424 : pchomp(const char *in)
1788 : {
1789 : size_t n;
1790 :
1791 424 : n = strlen(in);
1792 848 : while (n > 0 && in[n - 1] == '\n')
1793 424 : n--;
1794 424 : return pnstrdup(in, n);
1795 : }
|