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