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  /* 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  * MemoryContextStats
692  * Print statistics about the named context and all its descendants.
693  *
694  * This is just a debugging utility, so it's not very fancy. However, we do
695  * make some effort to summarize when the output would otherwise be very long.
696  * The statistics are sent to stderr.
697  */
698 void
700 {
701  /* A hard-wired limit on the number of children is usually good enough */
702  MemoryContextStatsDetail(context, 100, true);
703 }
704 
705 /*
706  * MemoryContextStatsDetail
707  *
708  * Entry point for use if you want to vary the number of child contexts shown.
709  *
710  * If print_to_stderr is true, print statistics about the memory contexts
711  * with fprintf(stderr), otherwise use ereport().
712  */
713 void
714 MemoryContextStatsDetail(MemoryContext context, int max_children,
715  bool print_to_stderr)
716 {
717  MemoryContextCounters grand_totals;
718 
719  memset(&grand_totals, 0, sizeof(grand_totals));
720 
721  MemoryContextStatsInternal(context, 0, true, max_children, &grand_totals, print_to_stderr);
722 
723  if (print_to_stderr)
724  fprintf(stderr,
725  "Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used\n",
726  grand_totals.totalspace, grand_totals.nblocks,
727  grand_totals.freespace, grand_totals.freechunks,
728  grand_totals.totalspace - grand_totals.freespace);
729  else
730 
731  /*
732  * Use LOG_SERVER_ONLY to prevent the memory contexts from being sent
733  * to the connected client.
734  *
735  * We don't buffer the information about all memory contexts in a
736  * backend into StringInfo and log it as one message. That would
737  * require the buffer to be enlarged, risking an OOM as there could be
738  * a large number of memory contexts in a backend. Instead, we log
739  * one message per memory context.
740  */
742  (errhidestmt(true),
743  errhidecontext(true),
744  errmsg_internal("Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used",
745  grand_totals.totalspace, grand_totals.nblocks,
746  grand_totals.freespace, grand_totals.freechunks,
747  grand_totals.totalspace - grand_totals.freespace)));
748 }
749 
750 /*
751  * MemoryContextStatsInternal
752  * One recursion level for MemoryContextStats
753  *
754  * Print this context if print is true, but in any case accumulate counts into
755  * *totals (if given).
756  */
757 static void
759  bool print, int max_children,
760  MemoryContextCounters *totals,
761  bool print_to_stderr)
762 {
763  MemoryContextCounters local_totals;
764  MemoryContext child;
765  int ichild;
766 
767  Assert(MemoryContextIsValid(context));
768 
769  /* Examine the context itself */
770  context->methods->stats(context,
772  (void *) &level,
773  totals, print_to_stderr);
774 
775  /*
776  * Examine children. If there are more than max_children of them, we do
777  * not print the rest explicitly, but just summarize them.
778  */
779  memset(&local_totals, 0, sizeof(local_totals));
780 
781  for (child = context->firstchild, ichild = 0;
782  child != NULL;
783  child = child->nextchild, ichild++)
784  {
785  if (ichild < max_children)
786  MemoryContextStatsInternal(child, level + 1,
787  print, max_children,
788  totals,
789  print_to_stderr);
790  else
791  MemoryContextStatsInternal(child, level + 1,
792  false, max_children,
793  &local_totals,
794  print_to_stderr);
795  }
796 
797  /* Deal with excess children */
798  if (ichild > max_children)
799  {
800  if (print)
801  {
802  if (print_to_stderr)
803  {
804  int i;
805 
806  for (i = 0; i <= level; i++)
807  fprintf(stderr, " ");
808  fprintf(stderr,
809  "%d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used\n",
810  ichild - max_children,
811  local_totals.totalspace,
812  local_totals.nblocks,
813  local_totals.freespace,
814  local_totals.freechunks,
815  local_totals.totalspace - local_totals.freespace);
816  }
817  else
819  (errhidestmt(true),
820  errhidecontext(true),
821  errmsg_internal("level: %d; %d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used",
822  level,
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 
831  if (totals)
832  {
833  totals->nblocks += local_totals.nblocks;
834  totals->freechunks += local_totals.freechunks;
835  totals->totalspace += local_totals.totalspace;
836  totals->freespace += local_totals.freespace;
837  }
838  }
839 }
840 
841 /*
842  * MemoryContextStatsPrint
843  * Print callback used by MemoryContextStatsInternal
844  *
845  * For now, the passthru pointer just points to "int level"; later we might
846  * make that more complicated.
847  */
848 static void
849 MemoryContextStatsPrint(MemoryContext context, void *passthru,
850  const char *stats_string,
851  bool print_to_stderr)
852 {
853  int level = *(int *) passthru;
854  const char *name = context->name;
855  const char *ident = context->ident;
856  char truncated_ident[110];
857  int i;
858 
859  /*
860  * It seems preferable to label dynahash contexts with just the hash table
861  * name. Those are already unique enough, so the "dynahash" part isn't
862  * very helpful, and this way is more consistent with pre-v11 practice.
863  */
864  if (ident && strcmp(name, "dynahash") == 0)
865  {
866  name = ident;
867  ident = NULL;
868  }
869 
870  truncated_ident[0] = '\0';
871 
872  if (ident)
873  {
874  /*
875  * Some contexts may have very long identifiers (e.g., SQL queries).
876  * Arbitrarily truncate at 100 bytes, but be careful not to break
877  * multibyte characters. Also, replace ASCII control characters, such
878  * as newlines, with spaces.
879  */
880  int idlen = strlen(ident);
881  bool truncated = false;
882 
883  strcpy(truncated_ident, ": ");
884  i = strlen(truncated_ident);
885 
886  if (idlen > 100)
887  {
888  idlen = pg_mbcliplen(ident, idlen, 100);
889  truncated = true;
890  }
891 
892  while (idlen-- > 0)
893  {
894  unsigned char c = *ident++;
895 
896  if (c < ' ')
897  c = ' ';
898  truncated_ident[i++] = c;
899  }
900  truncated_ident[i] = '\0';
901 
902  if (truncated)
903  strcat(truncated_ident, "...");
904  }
905 
906  if (print_to_stderr)
907  {
908  for (i = 0; i < level; i++)
909  fprintf(stderr, " ");
910  fprintf(stderr, "%s: %s%s\n", name, stats_string, truncated_ident);
911  }
912  else
914  (errhidestmt(true),
915  errhidecontext(true),
916  errmsg_internal("level: %d; %s: %s%s",
917  level, name, stats_string, truncated_ident)));
918 }
919 
920 /*
921  * MemoryContextCheck
922  * Check all chunks in the named context.
923  *
924  * This is just a debugging utility, so it's not fancy.
925  */
926 #ifdef MEMORY_CONTEXT_CHECKING
927 void
928 MemoryContextCheck(MemoryContext context)
929 {
930  MemoryContext child;
931 
932  Assert(MemoryContextIsValid(context));
933 
934  context->methods->check(context);
935  for (child = context->firstchild; child != NULL; child = child->nextchild)
936  MemoryContextCheck(child);
937 }
938 #endif
939 
940 /*
941  * MemoryContextCreate
942  * Context-type-independent part of context creation.
943  *
944  * This is only intended to be called by context-type-specific
945  * context creation routines, not by the unwashed masses.
946  *
947  * The memory context creation procedure goes like this:
948  * 1. Context-type-specific routine makes some initial space allocation,
949  * including enough space for the context header. If it fails,
950  * it can ereport() with no damage done.
951  * 2. Context-type-specific routine sets up all type-specific fields of
952  * the header (those beyond MemoryContextData proper), as well as any
953  * other management fields it needs to have a fully valid context.
954  * Usually, failure in this step is impossible, but if it's possible
955  * the initial space allocation should be freed before ereport'ing.
956  * 3. Context-type-specific routine calls MemoryContextCreate() to fill in
957  * the generic header fields and link the context into the context tree.
958  * 4. We return to the context-type-specific routine, which finishes
959  * up type-specific initialization. This routine can now do things
960  * that might fail (like allocate more memory), so long as it's
961  * sure the node is left in a state that delete will handle.
962  *
963  * node: the as-yet-uninitialized common part of the context header node.
964  * tag: NodeTag code identifying the memory context type.
965  * method_id: MemoryContextMethodID of the context-type being created.
966  * parent: parent context, or NULL if this will be a top-level context.
967  * name: name of context (must be statically allocated).
968  *
969  * Context routines generally assume that MemoryContextCreate can't fail,
970  * so this can contain Assert but not elog/ereport.
971  */
972 void
974  NodeTag tag,
975  MemoryContextMethodID method_id,
976  MemoryContext parent,
977  const char *name)
978 {
979  /* Creating new memory contexts is not allowed in a critical section */
980  Assert(CritSectionCount == 0);
981 
982  /* Initialize all standard fields of memory context header */
983  node->type = tag;
984  node->isReset = true;
985  node->methods = &mcxt_methods[method_id];
986  node->parent = parent;
987  node->firstchild = NULL;
988  node->mem_allocated = 0;
989  node->prevchild = NULL;
990  node->name = name;
991  node->ident = NULL;
992  node->reset_cbs = NULL;
993 
994  /* OK to link node into context tree */
995  if (parent)
996  {
997  node->nextchild = parent->firstchild;
998  if (parent->firstchild != NULL)
999  parent->firstchild->prevchild = node;
1000  parent->firstchild = node;
1001  /* inherit allowInCritSection flag from parent */
1002  node->allowInCritSection = parent->allowInCritSection;
1003  }
1004  else
1005  {
1006  node->nextchild = NULL;
1007  node->allowInCritSection = false;
1008  }
1009 
1010  VALGRIND_CREATE_MEMPOOL(node, 0, false);
1011 }
1012 
1013 /*
1014  * MemoryContextAlloc
1015  * Allocate space within the specified context.
1016  *
1017  * This could be turned into a macro, but we'd have to import
1018  * nodes/memnodes.h into postgres.h which seems a bad idea.
1019  */
1020 void *
1022 {
1023  void *ret;
1024 
1025  Assert(MemoryContextIsValid(context));
1026  AssertNotInCriticalSection(context);
1027 
1028  if (!AllocSizeIsValid(size))
1029  elog(ERROR, "invalid memory alloc request size %zu", size);
1030 
1031  context->isReset = false;
1032 
1033  ret = context->methods->alloc(context, size);
1034  if (unlikely(ret == NULL))
1035  {
1037 
1038  /*
1039  * Here, and elsewhere in this module, we show the target context's
1040  * "name" but not its "ident" (if any) in user-visible error messages.
1041  * The "ident" string might contain security-sensitive data, such as
1042  * values in SQL commands.
1043  */
1044  ereport(ERROR,
1045  (errcode(ERRCODE_OUT_OF_MEMORY),
1046  errmsg("out of memory"),
1047  errdetail("Failed on request of size %zu in memory context \"%s\".",
1048  size, context->name)));
1049  }
1050 
1051  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1052 
1053  return ret;
1054 }
1055 
1056 /*
1057  * MemoryContextAllocZero
1058  * Like MemoryContextAlloc, but clears allocated memory
1059  *
1060  * We could just call MemoryContextAlloc then clear the memory, but this
1061  * is a very common combination, so we provide the combined operation.
1062  */
1063 void *
1065 {
1066  void *ret;
1067 
1068  Assert(MemoryContextIsValid(context));
1069  AssertNotInCriticalSection(context);
1070 
1071  if (!AllocSizeIsValid(size))
1072  elog(ERROR, "invalid memory alloc request size %zu", size);
1073 
1074  context->isReset = false;
1075 
1076  ret = context->methods->alloc(context, size);
1077  if (unlikely(ret == NULL))
1078  {
1080  ereport(ERROR,
1081  (errcode(ERRCODE_OUT_OF_MEMORY),
1082  errmsg("out of memory"),
1083  errdetail("Failed on request of size %zu in memory context \"%s\".",
1084  size, context->name)));
1085  }
1086 
1087  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1088 
1089  MemSetAligned(ret, 0, size);
1090 
1091  return ret;
1092 }
1093 
1094 /*
1095  * MemoryContextAllocZeroAligned
1096  * MemoryContextAllocZero where length is suitable for MemSetLoop
1097  *
1098  * This might seem overly specialized, but it's not because newNode()
1099  * is so often called with compile-time-constant sizes.
1100  */
1101 void *
1103 {
1104  void *ret;
1105 
1106  Assert(MemoryContextIsValid(context));
1107  AssertNotInCriticalSection(context);
1108 
1109  if (!AllocSizeIsValid(size))
1110  elog(ERROR, "invalid memory alloc request size %zu", size);
1111 
1112  context->isReset = false;
1113 
1114  ret = context->methods->alloc(context, size);
1115  if (unlikely(ret == NULL))
1116  {
1118  ereport(ERROR,
1119  (errcode(ERRCODE_OUT_OF_MEMORY),
1120  errmsg("out of memory"),
1121  errdetail("Failed on request of size %zu in memory context \"%s\".",
1122  size, context->name)));
1123  }
1124 
1125  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1126 
1127  MemSetLoop(ret, 0, size);
1128 
1129  return ret;
1130 }
1131 
1132 /*
1133  * MemoryContextAllocExtended
1134  * Allocate space within the specified context using the given flags.
1135  */
1136 void *
1138 {
1139  void *ret;
1140 
1141  Assert(MemoryContextIsValid(context));
1142  AssertNotInCriticalSection(context);
1143 
1144  if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) :
1145  AllocSizeIsValid(size)))
1146  elog(ERROR, "invalid memory alloc request size %zu", size);
1147 
1148  context->isReset = false;
1149 
1150  ret = context->methods->alloc(context, size);
1151  if (unlikely(ret == NULL))
1152  {
1153  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
1154  {
1156  ereport(ERROR,
1157  (errcode(ERRCODE_OUT_OF_MEMORY),
1158  errmsg("out of memory"),
1159  errdetail("Failed on request of size %zu in memory context \"%s\".",
1160  size, context->name)));
1161  }
1162  return NULL;
1163  }
1164 
1165  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1166 
1167  if ((flags & MCXT_ALLOC_ZERO) != 0)
1168  MemSetAligned(ret, 0, size);
1169 
1170  return ret;
1171 }
1172 
1173 /*
1174  * HandleLogMemoryContextInterrupt
1175  * Handle receipt of an interrupt indicating logging of memory
1176  * contexts.
1177  *
1178  * All the actual work is deferred to ProcessLogMemoryContextInterrupt(),
1179  * because we cannot safely emit a log message inside the signal handler.
1180  */
1181 void
1183 {
1184  InterruptPending = true;
1185  LogMemoryContextPending = true;
1186  /* latch will be set by procsignal_sigusr1_handler */
1187 }
1188 
1189 /*
1190  * ProcessLogMemoryContextInterrupt
1191  * Perform logging of memory contexts of this backend process.
1192  *
1193  * Any backend that participates in ProcSignal signaling must arrange
1194  * to call this function if we see LogMemoryContextPending set.
1195  * It is called from CHECK_FOR_INTERRUPTS(), which is enough because
1196  * the target process for logging of memory contexts is a backend.
1197  */
1198 void
1200 {
1201  LogMemoryContextPending = false;
1202 
1203  /*
1204  * Use LOG_SERVER_ONLY to prevent this message from being sent to the
1205  * connected client.
1206  */
1208  (errhidestmt(true),
1209  errhidecontext(true),
1210  errmsg("logging memory contexts of PID %d", MyProcPid)));
1211 
1212  /*
1213  * When a backend process is consuming huge memory, logging all its memory
1214  * contexts might overrun available disk space. To prevent this, we limit
1215  * the number of child contexts to log per parent to 100.
1216  *
1217  * As with MemoryContextStats(), we suppose that practical cases where the
1218  * dump gets long will typically be huge numbers of siblings under the
1219  * same parent context; while the additional debugging value from seeing
1220  * details about individual siblings beyond 100 will not be large.
1221  */
1223 }
1224 
1225 void *
1227 {
1228  /* duplicates MemoryContextAlloc to avoid increased overhead */
1229  void *ret;
1231 
1232  Assert(MemoryContextIsValid(context));
1233  AssertNotInCriticalSection(context);
1234 
1235  if (!AllocSizeIsValid(size))
1236  elog(ERROR, "invalid memory alloc request size %zu", size);
1237 
1238  context->isReset = false;
1239 
1240  ret = context->methods->alloc(context, size);
1241  if (unlikely(ret == NULL))
1242  {
1244  ereport(ERROR,
1245  (errcode(ERRCODE_OUT_OF_MEMORY),
1246  errmsg("out of memory"),
1247  errdetail("Failed on request of size %zu in memory context \"%s\".",
1248  size, context->name)));
1249  }
1250 
1251  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1252 
1253  return ret;
1254 }
1255 
1256 void *
1258 {
1259  /* duplicates MemoryContextAllocZero to avoid increased overhead */
1260  void *ret;
1262 
1263  Assert(MemoryContextIsValid(context));
1264  AssertNotInCriticalSection(context);
1265 
1266  if (!AllocSizeIsValid(size))
1267  elog(ERROR, "invalid memory alloc request size %zu", size);
1268 
1269  context->isReset = false;
1270 
1271  ret = context->methods->alloc(context, size);
1272  if (unlikely(ret == NULL))
1273  {
1275  ereport(ERROR,
1276  (errcode(ERRCODE_OUT_OF_MEMORY),
1277  errmsg("out of memory"),
1278  errdetail("Failed on request of size %zu in memory context \"%s\".",
1279  size, context->name)));
1280  }
1281 
1282  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1283 
1284  MemSetAligned(ret, 0, size);
1285 
1286  return ret;
1287 }
1288 
1289 void *
1290 palloc_extended(Size size, int flags)
1291 {
1292  /* duplicates MemoryContextAllocExtended to avoid increased overhead */
1293  void *ret;
1295 
1296  Assert(MemoryContextIsValid(context));
1297  AssertNotInCriticalSection(context);
1298 
1299  if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) :
1300  AllocSizeIsValid(size)))
1301  elog(ERROR, "invalid memory alloc request size %zu", size);
1302 
1303  context->isReset = false;
1304 
1305  ret = context->methods->alloc(context, size);
1306  if (unlikely(ret == NULL))
1307  {
1308  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
1309  {
1311  ereport(ERROR,
1312  (errcode(ERRCODE_OUT_OF_MEMORY),
1313  errmsg("out of memory"),
1314  errdetail("Failed on request of size %zu in memory context \"%s\".",
1315  size, context->name)));
1316  }
1317  return NULL;
1318  }
1319 
1320  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1321 
1322  if ((flags & MCXT_ALLOC_ZERO) != 0)
1323  MemSetAligned(ret, 0, size);
1324 
1325  return ret;
1326 }
1327 
1328 /*
1329  * MemoryContextAllocAligned
1330  * Allocate 'size' bytes of memory in 'context' aligned to 'alignto'
1331  * bytes.
1332  *
1333  * Currently, we align addresses by requesting additional bytes from the
1334  * MemoryContext's standard allocator function and then aligning the returned
1335  * address by the required alignment. This means that the given MemoryContext
1336  * must support providing us with a chunk of memory that's larger than 'size'.
1337  * For allocators such as Slab, that's not going to work, as slab only allows
1338  * chunks of the size that's specified when the context is created.
1339  *
1340  * 'alignto' must be a power of 2.
1341  * 'flags' may be 0 or set the same as MemoryContextAllocExtended().
1342  */
1343 void *
1345  Size size, Size alignto, int flags)
1346 {
1347  MemoryChunk *alignedchunk;
1348  Size alloc_size;
1349  void *unaligned;
1350  void *aligned;
1351 
1352  /* wouldn't make much sense to waste that much space */
1353  Assert(alignto < (128 * 1024 * 1024));
1354 
1355  /* ensure alignto is a power of 2 */
1356  Assert((alignto & (alignto - 1)) == 0);
1357 
1358  /*
1359  * If the alignment requirements are less than what we already guarantee
1360  * then just use the standard allocation function.
1361  */
1362  if (unlikely(alignto <= MAXIMUM_ALIGNOF))
1363  return MemoryContextAllocExtended(context, size, flags);
1364 
1365  /*
1366  * We implement aligned pointers by simply allocating enough memory for
1367  * the requested size plus the alignment and an additional "redirection"
1368  * MemoryChunk. This additional MemoryChunk is required for operations
1369  * such as pfree when used on the pointer returned by this function. We
1370  * use this redirection MemoryChunk in order to find the pointer to the
1371  * memory that was returned by the MemoryContextAllocExtended call below.
1372  * We do that by "borrowing" the block offset field and instead of using
1373  * that to find the offset into the owning block, we use it to find the
1374  * original allocated address.
1375  *
1376  * Here we must allocate enough extra memory so that we can still align
1377  * the pointer returned by MemoryContextAllocExtended and also have enough
1378  * space for the redirection MemoryChunk. Since allocations will already
1379  * be at least aligned by MAXIMUM_ALIGNOF, we can subtract that amount
1380  * from the allocation size to save a little memory.
1381  */
1382  alloc_size = size + PallocAlignedExtraBytes(alignto);
1383 
1384 #ifdef MEMORY_CONTEXT_CHECKING
1385  /* ensure there's space for a sentinel byte */
1386  alloc_size += 1;
1387 #endif
1388 
1389  /* perform the actual allocation */
1390  unaligned = MemoryContextAllocExtended(context, alloc_size, flags);
1391 
1392  /* set the aligned pointer */
1393  aligned = (void *) TYPEALIGN(alignto, (char *) unaligned +
1394  sizeof(MemoryChunk));
1395 
1396  alignedchunk = PointerGetMemoryChunk(aligned);
1397 
1398  /*
1399  * We set the redirect MemoryChunk so that the block offset calculation is
1400  * used to point back to the 'unaligned' allocated chunk. This allows us
1401  * to use MemoryChunkGetBlock() to find the unaligned chunk when we need
1402  * to perform operations such as pfree() and repalloc().
1403  *
1404  * We store 'alignto' in the MemoryChunk's 'value' so that we know what
1405  * the alignment was set to should we ever be asked to realloc this
1406  * pointer.
1407  */
1408  MemoryChunkSetHdrMask(alignedchunk, unaligned, alignto,
1410 
1411  /* double check we produced a correctly aligned pointer */
1412  Assert((void *) TYPEALIGN(alignto, aligned) == aligned);
1413 
1414 #ifdef MEMORY_CONTEXT_CHECKING
1415  alignedchunk->requested_size = size;
1416  /* set mark to catch clobber of "unused" space */
1417  set_sentinel(aligned, size);
1418 #endif
1419 
1420  /* Mark the bytes before the redirection header as noaccess */
1421  VALGRIND_MAKE_MEM_NOACCESS(unaligned,
1422  (char *) alignedchunk - (char *) unaligned);
1423 
1424  /* Disallow access to the redirection chunk header. */
1425  VALGRIND_MAKE_MEM_NOACCESS(alignedchunk, sizeof(MemoryChunk));
1426 
1427  return aligned;
1428 }
1429 
1430 /*
1431  * palloc_aligned
1432  * Allocate 'size' bytes returning a pointer that's aligned to the
1433  * 'alignto' boundary.
1434  *
1435  * Currently, we align addresses by requesting additional bytes from the
1436  * MemoryContext's standard allocator function and then aligning the returned
1437  * address by the required alignment. This means that the given MemoryContext
1438  * must support providing us with a chunk of memory that's larger than 'size'.
1439  * For allocators such as Slab, that's not going to work, as slab only allows
1440  * chunks of the size that's specified when the context is created.
1441  *
1442  * 'alignto' must be a power of 2.
1443  * 'flags' may be 0 or set the same as MemoryContextAllocExtended().
1444  */
1445 void *
1446 palloc_aligned(Size size, Size alignto, int flags)
1447 {
1448  return MemoryContextAllocAligned(CurrentMemoryContext, size, alignto, flags);
1449 }
1450 
1451 /*
1452  * pfree
1453  * Release an allocated chunk.
1454  */
1455 void
1456 pfree(void *pointer)
1457 {
1458 #ifdef USE_VALGRIND
1460  MemoryContext context = GetMemoryChunkContext(pointer);
1461 #endif
1462 
1463  MCXT_METHOD(pointer, free_p) (pointer);
1464 
1465 #ifdef USE_VALGRIND
1466  if (method != MCTX_ALIGNED_REDIRECT_ID)
1467  VALGRIND_MEMPOOL_FREE(context, pointer);
1468 #endif
1469 }
1470 
1471 /*
1472  * repalloc
1473  * Adjust the size of a previously allocated chunk.
1474  */
1475 void *
1476 repalloc(void *pointer, Size size)
1477 {
1478 #ifdef USE_VALGRIND
1480 #endif
1481 #if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
1482  MemoryContext context = GetMemoryChunkContext(pointer);
1483 #endif
1484  void *ret;
1485 
1486  if (!AllocSizeIsValid(size))
1487  elog(ERROR, "invalid memory alloc request size %zu", size);
1488 
1489  AssertNotInCriticalSection(context);
1490 
1491  /* isReset must be false already */
1492  Assert(!context->isReset);
1493 
1494  ret = MCXT_METHOD(pointer, realloc) (pointer, size);
1495  if (unlikely(ret == NULL))
1496  {
1497  MemoryContext cxt = GetMemoryChunkContext(pointer);
1498 
1500  ereport(ERROR,
1501  (errcode(ERRCODE_OUT_OF_MEMORY),
1502  errmsg("out of memory"),
1503  errdetail("Failed on request of size %zu in memory context \"%s\".",
1504  size, cxt->name)));
1505  }
1506 
1507 #ifdef USE_VALGRIND
1508  if (method != MCTX_ALIGNED_REDIRECT_ID)
1509  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1510 #endif
1511 
1512  return ret;
1513 }
1514 
1515 /*
1516  * repalloc_extended
1517  * Adjust the size of a previously allocated chunk,
1518  * with HUGE and NO_OOM options.
1519  */
1520 void *
1521 repalloc_extended(void *pointer, Size size, int flags)
1522 {
1523 #if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
1524  MemoryContext context = GetMemoryChunkContext(pointer);
1525 #endif
1526  void *ret;
1527 
1528  if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) :
1529  AllocSizeIsValid(size)))
1530  elog(ERROR, "invalid memory alloc request size %zu", size);
1531 
1532  AssertNotInCriticalSection(context);
1533 
1534  /* isReset must be false already */
1535  Assert(!context->isReset);
1536 
1537  ret = MCXT_METHOD(pointer, realloc) (pointer, size);
1538  if (unlikely(ret == NULL))
1539  {
1540  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
1541  {
1542  MemoryContext cxt = GetMemoryChunkContext(pointer);
1543 
1545  ereport(ERROR,
1546  (errcode(ERRCODE_OUT_OF_MEMORY),
1547  errmsg("out of memory"),
1548  errdetail("Failed on request of size %zu in memory context \"%s\".",
1549  size, cxt->name)));
1550  }
1551  return NULL;
1552  }
1553 
1554  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1555 
1556  return ret;
1557 }
1558 
1559 /*
1560  * repalloc0
1561  * Adjust the size of a previously allocated chunk and zero out the added
1562  * space.
1563  */
1564 void *
1565 repalloc0(void *pointer, Size oldsize, Size size)
1566 {
1567  void *ret;
1568 
1569  /* catch wrong argument order */
1570  if (unlikely(oldsize > size))
1571  elog(ERROR, "invalid repalloc0 call: oldsize %zu, new size %zu",
1572  oldsize, size);
1573 
1574  ret = repalloc(pointer, size);
1575  memset((char *) ret + oldsize, 0, (size - oldsize));
1576  return ret;
1577 }
1578 
1579 /*
1580  * MemoryContextAllocHuge
1581  * Allocate (possibly-expansive) space within the specified context.
1582  *
1583  * See considerations in comment at MaxAllocHugeSize.
1584  */
1585 void *
1587 {
1588  void *ret;
1589 
1590  Assert(MemoryContextIsValid(context));
1591  AssertNotInCriticalSection(context);
1592 
1593  if (!AllocHugeSizeIsValid(size))
1594  elog(ERROR, "invalid memory alloc request size %zu", size);
1595 
1596  context->isReset = false;
1597 
1598  ret = context->methods->alloc(context, size);
1599  if (unlikely(ret == NULL))
1600  {
1602  ereport(ERROR,
1603  (errcode(ERRCODE_OUT_OF_MEMORY),
1604  errmsg("out of memory"),
1605  errdetail("Failed on request of size %zu in memory context \"%s\".",
1606  size, context->name)));
1607  }
1608 
1609  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1610 
1611  return ret;
1612 }
1613 
1614 /*
1615  * repalloc_huge
1616  * Adjust the size of a previously allocated chunk, permitting a large
1617  * value. The previous allocation need not have been "huge".
1618  */
1619 void *
1620 repalloc_huge(void *pointer, Size size)
1621 {
1622  /* this one seems not worth its own implementation */
1623  return repalloc_extended(pointer, size, MCXT_ALLOC_HUGE);
1624 }
1625 
1626 /*
1627  * MemoryContextStrdup
1628  * Like strdup(), but allocate from the specified context
1629  */
1630 char *
1631 MemoryContextStrdup(MemoryContext context, const char *string)
1632 {
1633  char *nstr;
1634  Size len = strlen(string) + 1;
1635 
1636  nstr = (char *) MemoryContextAlloc(context, len);
1637 
1638  memcpy(nstr, string, len);
1639 
1640  return nstr;
1641 }
1642 
1643 char *
1644 pstrdup(const char *in)
1645 {
1647 }
1648 
1649 /*
1650  * pnstrdup
1651  * Like pstrdup(), but append null byte to a
1652  * not-necessarily-null-terminated input string.
1653  */
1654 char *
1655 pnstrdup(const char *in, Size len)
1656 {
1657  char *out;
1658 
1659  len = strnlen(in, len);
1660 
1661  out = palloc(len + 1);
1662  memcpy(out, in, len);
1663  out[len] = '\0';
1664 
1665  return out;
1666 }
1667 
1668 /*
1669  * Make copy of string with all trailing newline characters removed.
1670  */
1671 char *
1672 pchomp(const char *in)
1673 {
1674  size_t n;
1675 
1676  n = strlen(in);
1677  while (n > 0 && in[n - 1] == '\n')
1678  n--;
1679  return pnstrdup(in, n);
1680 }
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
#define MemSetLoop(start, val, len)
Definition: c.h:1074
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
#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:278
void GenerationFree(void *pointer)
Definition: generation.c:623
MemoryContext GenerationGetChunkContext(void *pointer)
Definition: generation.c:880
Size GenerationGetChunkSpace(void *pointer)
Definition: generation.c:906
void * GenerationAlloc(MemoryContext context, Size size)
Definition: generation.c:345
bool GenerationIsEmpty(MemoryContext context)
Definition: generation.c:935
void GenerationStats(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
Definition: generation.c:966
void * GenerationRealloc(void *pointer, Size size)
Definition: generation.c:738
void GenerationDelete(MemoryContext context)
Definition: generation.c:323
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
#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:1655
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:1344
bool MemoryContextIsEmpty(MemoryContext context)
Definition: mcxt.c:652
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:973
MemoryContext TopTransactionContext
Definition: mcxt.c:146
char * pchomp(const char *in)
Definition: mcxt.c:1672
void HandleLogMemoryContextInterrupt(void)
Definition: mcxt.c:1182
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:714
char * pstrdup(const char *in)
Definition: mcxt.c:1644
void pfree(void *pointer)
Definition: mcxt.c:1456
Size GetMemoryChunkSpace(void *pointer)
Definition: mcxt.c:630
void * repalloc0(void *pointer, Size oldsize, Size size)
Definition: mcxt.c:1565
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:1257
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1064
MemoryContext CurTransactionContext
Definition: mcxt.c:147
void * MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
Definition: mcxt.c:1137
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1476
void * palloc_extended(Size size, int flags)
Definition: mcxt.c:1290
MemoryContext GetMemoryChunkContext(void *pointer)
Definition: mcxt.c:616
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1021
void * MemoryContextAllocZeroAligned(MemoryContext context, Size size)
Definition: mcxt.c:1102
Size MemoryContextMemAllocated(MemoryContext context, bool recurse)
Definition: mcxt.c:671
void MemoryContextStats(MemoryContext context)
Definition: mcxt.c:699
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:1446
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1631
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:758
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:1199
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:1586
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:849
void * palloc(Size size)
Definition: mcxt.c:1226
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:1620
void * repalloc_extended(void *pointer, Size size, int flags)
Definition: mcxt.c:1521
#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: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
#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