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