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