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