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-2018, 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 "miscadmin.h"
25 #include "utils/memdebug.h"
26 #include "utils/memutils.h"
27 
28 
29 /*****************************************************************************
30  * GLOBAL MEMORY *
31  *****************************************************************************/
32 
33 /*
34  * CurrentMemoryContext
35  * Default memory context for allocations.
36  */
38 
39 /*
40  * Standard top-level contexts. For a description of the purpose of each
41  * of these contexts, refer to src/backend/utils/mmgr/README
42  */
50 
51 /* This is a transient link to the active portal's memory context: */
53 
55 static void MemoryContextStatsInternal(MemoryContext context, int level,
56  bool print, int max_children,
57  MemoryContextCounters *totals);
58 
59 /*
60  * You should not do memory allocations within a critical section, because
61  * an out-of-memory error will be escalated to a PANIC. To enforce that
62  * rule, the allocation functions Assert that.
63  */
64 #define AssertNotInCriticalSection(context) \
65  Assert(CritSectionCount == 0 || (context)->allowInCritSection)
66 
67 /*****************************************************************************
68  * EXPORTED ROUTINES *
69  *****************************************************************************/
70 
71 
72 /*
73  * MemoryContextInit
74  * Start up the memory-context subsystem.
75  *
76  * This must be called before creating contexts or allocating memory in
77  * contexts. TopMemoryContext and ErrorContext are initialized here;
78  * other contexts must be created afterwards.
79  *
80  * In normal multi-backend operation, this is called once during
81  * postmaster startup, and not at all by individual backend startup
82  * (since the backends inherit an already-initialized context subsystem
83  * by virtue of being forked off the postmaster). But in an EXEC_BACKEND
84  * build, each process must do this for itself.
85  *
86  * In a standalone backend this must be called during backend startup.
87  */
88 void
90 {
91  AssertState(TopMemoryContext == NULL);
92 
93  /*
94  * First, initialize TopMemoryContext, which is the parent of all others.
95  */
96  TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
97  "TopMemoryContext",
99 
100  /*
101  * Not having any other place to point CurrentMemoryContext, make it point
102  * to TopMemoryContext. Caller should change this soon!
103  */
104  CurrentMemoryContext = TopMemoryContext;
105 
106  /*
107  * Initialize ErrorContext as an AllocSetContext with slow growth rate ---
108  * we don't really expect much to be allocated in it. More to the point,
109  * require it to contain at least 8K at all times. This is the only case
110  * where retained memory in a context is *essential* --- we want to be
111  * sure ErrorContext still has some memory even if we've run out
112  * elsewhere! Also, allow allocations in ErrorContext within a critical
113  * section. Otherwise a PANIC will cause an assertion failure in the error
114  * reporting code, before printing out the real cause of the failure.
115  *
116  * This should be the last step in this function, as elog.c assumes memory
117  * management works once ErrorContext is non-null.
118  */
119  ErrorContext = AllocSetContextCreateExtended(TopMemoryContext,
120  "ErrorContext",
121  0,
122  8 * 1024,
123  8 * 1024,
124  8 * 1024);
125  MemoryContextAllowInCriticalSection(ErrorContext, true);
126 }
127 
128 /*
129  * MemoryContextReset
130  * Release all space allocated within a context and delete all its
131  * descendant contexts (but not the named context itself).
132  */
133 void
135 {
137 
138  /* save a function call in common case where there are no children */
139  if (context->firstchild != NULL)
141 
142  /* save a function call if no pallocs since startup or last reset */
143  if (!context->isReset)
144  MemoryContextResetOnly(context);
145 }
146 
147 /*
148  * MemoryContextResetOnly
149  * Release all space allocated within a context.
150  * Nothing is done to the context's descendant contexts.
151  */
152 void
154 {
156 
157  /* Nothing to do if no pallocs since startup or last reset */
158  if (!context->isReset)
159  {
161  context->methods->reset(context);
162  context->isReset = true;
163  VALGRIND_DESTROY_MEMPOOL(context);
164  VALGRIND_CREATE_MEMPOOL(context, 0, false);
165  }
166 }
167 
168 /*
169  * MemoryContextResetChildren
170  * Release all space allocated within a context's descendants,
171  * but don't delete the contexts themselves. The named context
172  * itself is not touched.
173  */
174 void
176 {
177  MemoryContext child;
178 
180 
181  for (child = context->firstchild; child != NULL; child = child->nextchild)
182  {
184  MemoryContextResetOnly(child);
185  }
186 }
187 
188 /*
189  * MemoryContextDelete
190  * Delete a context and its descendants, and release all space
191  * allocated therein.
192  *
193  * The type-specific delete routine removes all storage for the context,
194  * but we have to recurse to handle the children.
195  * We must also delink the context from its parent, if it has one.
196  */
197 void
199 {
201  /* We had better not be deleting TopMemoryContext ... */
202  Assert(context != TopMemoryContext);
203  /* And not CurrentMemoryContext, either */
204  Assert(context != CurrentMemoryContext);
205 
206  /* save a function call in common case where there are no children */
207  if (context->firstchild != NULL)
209 
210  /*
211  * It's not entirely clear whether 'tis better to do this before or after
212  * delinking the context; but an error in a callback will likely result in
213  * leaking the whole context (if it's not a root context) if we do it
214  * after, so let's do it before.
215  */
217 
218  /*
219  * We delink the context from its parent before deleting it, so that if
220  * there's an error we won't have deleted/busted contexts still attached
221  * to the context tree. Better a leak than a crash.
222  */
223  MemoryContextSetParent(context, NULL);
224 
225  context->methods->delete_context(context);
226 
227  VALGRIND_DESTROY_MEMPOOL(context);
228 }
229 
230 /*
231  * MemoryContextDeleteChildren
232  * Delete all the descendants of the named context and release all
233  * space allocated therein. The named context itself is not touched.
234  */
235 void
237 {
239 
240  /*
241  * MemoryContextDelete will delink the child from me, so just iterate as
242  * long as there is a child.
243  */
244  while (context->firstchild != NULL)
246 }
247 
248 /*
249  * MemoryContextRegisterResetCallback
250  * Register a function to be called before next context reset/delete.
251  * Such callbacks will be called in reverse order of registration.
252  *
253  * The caller is responsible for allocating a MemoryContextCallback struct
254  * to hold the info about this callback request, and for filling in the
255  * "func" and "arg" fields in the struct to show what function to call with
256  * what argument. Typically the callback struct should be allocated within
257  * the specified context, since that means it will automatically be freed
258  * when no longer needed.
259  *
260  * There is no API for deregistering a callback once registered. If you
261  * want it to not do anything anymore, adjust the state pointed to by its
262  * "arg" to indicate that.
263  */
264 void
267 {
269 
270  /* Push onto head so this will be called before older registrants. */
271  cb->next = context->reset_cbs;
272  context->reset_cbs = cb;
273  /* Mark the context as non-reset (it probably is already). */
274  context->isReset = false;
275 }
276 
277 /*
278  * MemoryContextCallResetCallbacks
279  * Internal function to call all registered callbacks for context.
280  */
281 static void
283 {
285 
286  /*
287  * We pop each callback from the list before calling. That way, if an
288  * error occurs inside the callback, we won't try to call it a second time
289  * in the likely event that we reset or delete the context later.
290  */
291  while ((cb = context->reset_cbs) != NULL)
292  {
293  context->reset_cbs = cb->next;
294  cb->func(cb->arg);
295  }
296 }
297 
298 /*
299  * MemoryContextSetParent
300  * Change a context to belong to a new parent (or no parent).
301  *
302  * We provide this as an API function because it is sometimes useful to
303  * change a context's lifespan after creation. For example, a context
304  * might be created underneath a transient context, filled with data,
305  * and then reparented underneath CacheMemoryContext to make it long-lived.
306  * In this way no special effort is needed to get rid of the context in case
307  * a failure occurs before its contents are completely set up.
308  *
309  * Callers often assume that this function cannot fail, so don't put any
310  * elog(ERROR) calls in it.
311  *
312  * A possible caller error is to reparent a context under itself, creating
313  * a loop in the context graph. We assert here that context != new_parent,
314  * but checking for multi-level loops seems more trouble than it's worth.
315  */
316 void
318 {
320  AssertArg(context != new_parent);
321 
322  /* Fast path if it's got correct parent already */
323  if (new_parent == context->parent)
324  return;
325 
326  /* Delink from existing parent, if any */
327  if (context->parent)
328  {
329  MemoryContext parent = context->parent;
330 
331  if (context->prevchild != NULL)
332  context->prevchild->nextchild = context->nextchild;
333  else
334  {
335  Assert(parent->firstchild == context);
336  parent->firstchild = context->nextchild;
337  }
338 
339  if (context->nextchild != NULL)
340  context->nextchild->prevchild = context->prevchild;
341  }
342 
343  /* And relink */
344  if (new_parent)
345  {
346  AssertArg(MemoryContextIsValid(new_parent));
347  context->parent = new_parent;
348  context->prevchild = NULL;
349  context->nextchild = new_parent->firstchild;
350  if (new_parent->firstchild != NULL)
351  new_parent->firstchild->prevchild = context;
352  new_parent->firstchild = context;
353  }
354  else
355  {
356  context->parent = NULL;
357  context->prevchild = NULL;
358  context->nextchild = NULL;
359  }
360 }
361 
362 /*
363  * MemoryContextAllowInCriticalSection
364  * Allow/disallow allocations in this memory context within a critical
365  * section.
366  *
367  * Normally, memory allocations are not allowed within a critical section,
368  * because a failure would lead to PANIC. There are a few exceptions to
369  * that, like allocations related to debugging code that is not supposed to
370  * be enabled in production. This function can be used to exempt specific
371  * memory contexts from the assertion in palloc().
372  */
373 void
375 {
377 
378  context->allowInCritSection = allow;
379 }
380 
381 /*
382  * GetMemoryChunkSpace
383  * Given a currently-allocated chunk, determine the total space
384  * it occupies (including all memory-allocation overhead).
385  *
386  * This is useful for measuring the total space occupied by a set of
387  * allocated chunks.
388  */
389 Size
390 GetMemoryChunkSpace(void *pointer)
391 {
392  MemoryContext context = GetMemoryChunkContext(pointer);
393 
394  return context->methods->get_chunk_space(context, pointer);
395 }
396 
397 /*
398  * MemoryContextGetParent
399  * Get the parent context (if any) of the specified context
400  */
403 {
405 
406  return context->parent;
407 }
408 
409 /*
410  * MemoryContextIsEmpty
411  * Is a memory context empty of any allocated space?
412  */
413 bool
415 {
417 
418  /*
419  * For now, we consider a memory context nonempty if it has any children;
420  * perhaps this should be changed later.
421  */
422  if (context->firstchild != NULL)
423  return false;
424  /* Otherwise use the type-specific inquiry */
425  return context->methods->is_empty(context);
426 }
427 
428 /*
429  * MemoryContextStats
430  * Print statistics about the named context and all its descendants.
431  *
432  * This is just a debugging utility, so it's not very fancy. However, we do
433  * make some effort to summarize when the output would otherwise be very long.
434  * The statistics are sent to stderr.
435  */
436 void
438 {
439  /* A hard-wired limit on the number of children is usually good enough */
440  MemoryContextStatsDetail(context, 100);
441 }
442 
443 /*
444  * MemoryContextStatsDetail
445  *
446  * Entry point for use if you want to vary the number of child contexts shown.
447  */
448 void
449 MemoryContextStatsDetail(MemoryContext context, int max_children)
450 {
451  MemoryContextCounters grand_totals;
452 
453  memset(&grand_totals, 0, sizeof(grand_totals));
454 
455  MemoryContextStatsInternal(context, 0, true, max_children, &grand_totals);
456 
457  fprintf(stderr,
458  "Grand total: %zu bytes in %zd blocks; %zu free (%zd chunks); %zu used\n",
459  grand_totals.totalspace, grand_totals.nblocks,
460  grand_totals.freespace, grand_totals.freechunks,
461  grand_totals.totalspace - grand_totals.freespace);
462 }
463 
464 /*
465  * MemoryContextStatsInternal
466  * One recursion level for MemoryContextStats
467  *
468  * Print this context if print is true, but in any case accumulate counts into
469  * *totals (if given).
470  */
471 static void
473  bool print, int max_children,
474  MemoryContextCounters *totals)
475 {
476  MemoryContextCounters local_totals;
477  MemoryContext child;
478  int ichild;
479 
481 
482  /* Examine the context itself */
483  context->methods->stats(context, level, print, totals);
484 
485  /*
486  * Examine children. If there are more than max_children of them, we do
487  * not print the rest explicitly, but just summarize them.
488  */
489  memset(&local_totals, 0, sizeof(local_totals));
490 
491  for (child = context->firstchild, ichild = 0;
492  child != NULL;
493  child = child->nextchild, ichild++)
494  {
495  if (ichild < max_children)
496  MemoryContextStatsInternal(child, level + 1,
497  print, max_children,
498  totals);
499  else
500  MemoryContextStatsInternal(child, level + 1,
501  false, max_children,
502  &local_totals);
503  }
504 
505  /* Deal with excess children */
506  if (ichild > max_children)
507  {
508  if (print)
509  {
510  int i;
511 
512  for (i = 0; i <= level; i++)
513  fprintf(stderr, " ");
514  fprintf(stderr,
515  "%d more child contexts containing %zu total in %zd blocks; %zu free (%zd chunks); %zu used\n",
516  ichild - max_children,
517  local_totals.totalspace,
518  local_totals.nblocks,
519  local_totals.freespace,
520  local_totals.freechunks,
521  local_totals.totalspace - local_totals.freespace);
522  }
523 
524  if (totals)
525  {
526  totals->nblocks += local_totals.nblocks;
527  totals->freechunks += local_totals.freechunks;
528  totals->totalspace += local_totals.totalspace;
529  totals->freespace += local_totals.freespace;
530  }
531  }
532 }
533 
534 /*
535  * MemoryContextCheck
536  * Check all chunks in the named context.
537  *
538  * This is just a debugging utility, so it's not fancy.
539  */
540 #ifdef MEMORY_CONTEXT_CHECKING
541 void
542 MemoryContextCheck(MemoryContext context)
543 {
544  MemoryContext child;
545 
547 
548  context->methods->check(context);
549  for (child = context->firstchild; child != NULL; child = child->nextchild)
550  MemoryContextCheck(child);
551 }
552 #endif
553 
554 /*
555  * MemoryContextContains
556  * Detect whether an allocated chunk of memory belongs to a given
557  * context or not.
558  *
559  * Caution: this test is reliable as long as 'pointer' does point to
560  * a chunk of memory allocated from *some* context. If 'pointer' points
561  * at memory obtained in some other way, there is a small chance of a
562  * false-positive result, since the bits right before it might look like
563  * a valid chunk header by chance.
564  */
565 bool
566 MemoryContextContains(MemoryContext context, void *pointer)
567 {
568  MemoryContext ptr_context;
569 
570  /*
571  * NB: Can't use GetMemoryChunkContext() here - that performs assertions
572  * that aren't acceptable here since we might be passed memory not
573  * allocated by any memory context.
574  *
575  * Try to detect bogus pointers handed to us, poorly though we can.
576  * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
577  * allocated chunk.
578  */
579  if (pointer == NULL || pointer != (void *) MAXALIGN(pointer))
580  return false;
581 
582  /*
583  * OK, it's probably safe to look at the context.
584  */
585  ptr_context = *(MemoryContext *) (((char *) pointer) - sizeof(void *));
586 
587  return ptr_context == context;
588 }
589 
590 /*
591  * MemoryContextCreate
592  * Context-type-independent part of context creation.
593  *
594  * This is only intended to be called by context-type-specific
595  * context creation routines, not by the unwashed masses.
596  *
597  * The memory context creation procedure goes like this:
598  * 1. Context-type-specific routine makes some initial space allocation,
599  * including enough space for the context header. If it fails,
600  * it can ereport() with no damage done.
601  * 2. Context-type-specific routine sets up all type-specific fields of
602  * the header (those beyond MemoryContextData proper), as well as any
603  * other management fields it needs to have a fully valid context.
604  * Usually, failure in this step is impossible, but if it's possible
605  * the initial space allocation should be freed before ereport'ing.
606  * 3. Context-type-specific routine calls MemoryContextCreate() to fill in
607  * the generic header fields and link the context into the context tree.
608  * 4. We return to the context-type-specific routine, which finishes
609  * up type-specific initialization. This routine can now do things
610  * that might fail (like allocate more memory), so long as it's
611  * sure the node is left in a state that delete will handle.
612  *
613  * node: the as-yet-uninitialized common part of the context header node.
614  * tag: NodeTag code identifying the memory context type.
615  * size: total size of context header including context-type-specific fields,
616  * as well as space for the context name if MEMCONTEXT_COPY_NAME is set.
617  * nameoffset: where within the "size" space to insert the context name.
618  * methods: context-type-specific methods (usually statically allocated).
619  * parent: parent context, or NULL if this will be a top-level context.
620  * name: name of context (for debugging only, need not be unique).
621  * flags: bitmask of MEMCONTEXT_XXX option flags.
622  *
623  * Context routines generally assume that MemoryContextCreate can't fail,
624  * so this can contain Assert but not elog/ereport.
625  */
626 void
628  NodeTag tag, Size size, Size nameoffset,
629  const MemoryContextMethods *methods,
630  MemoryContext parent,
631  const char *name,
632  int flags)
633 {
634  /* Creating new memory contexts is not allowed in a critical section */
635  Assert(CritSectionCount == 0);
636 
637  /* Check size is sane */
638  Assert(nameoffset >= sizeof(MemoryContextData));
639  Assert((flags & MEMCONTEXT_COPY_NAME) ?
640  size >= nameoffset + strlen(name) + 1 :
641  size >= nameoffset);
642 
643  /* Initialize all standard fields of memory context header */
644  node->type = tag;
645  node->isReset = true;
646  node->methods = methods;
647  node->parent = parent;
648  node->firstchild = NULL;
649  node->prevchild = NULL;
650  node->reset_cbs = NULL;
651 
652  if (flags & MEMCONTEXT_COPY_NAME)
653  {
654  /* Insert context name into space reserved for it */
655  char *namecopy = ((char *) node) + nameoffset;
656 
657  node->name = namecopy;
658  strcpy(namecopy, name);
659  }
660  else
661  {
662  /* Assume the passed-in name is statically allocated */
663  node->name = name;
664  }
665 
666  /* OK to link node into context tree */
667  if (parent)
668  {
669  node->nextchild = parent->firstchild;
670  if (parent->firstchild != NULL)
671  parent->firstchild->prevchild = node;
672  parent->firstchild = node;
673  /* inherit allowInCritSection flag from parent */
674  node->allowInCritSection = parent->allowInCritSection;
675  }
676  else
677  {
678  node->nextchild = NULL;
679  node->allowInCritSection = false;
680  }
681 
682  VALGRIND_CREATE_MEMPOOL(node, 0, false);
683 }
684 
685 /*
686  * MemoryContextAlloc
687  * Allocate space within the specified context.
688  *
689  * This could be turned into a macro, but we'd have to import
690  * nodes/memnodes.h into postgres.h which seems a bad idea.
691  */
692 void *
694 {
695  void *ret;
696 
699 
700  if (!AllocSizeIsValid(size))
701  elog(ERROR, "invalid memory alloc request size %zu", size);
702 
703  context->isReset = false;
704 
705  ret = context->methods->alloc(context, size);
706  if (ret == NULL)
707  {
708  MemoryContextStats(TopMemoryContext);
709  ereport(ERROR,
710  (errcode(ERRCODE_OUT_OF_MEMORY),
711  errmsg("out of memory"),
712  errdetail("Failed on request of size %zu.", size)));
713  }
714 
715  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
716 
717  return ret;
718 }
719 
720 /*
721  * MemoryContextAllocZero
722  * Like MemoryContextAlloc, but clears allocated memory
723  *
724  * We could just call MemoryContextAlloc then clear the memory, but this
725  * is a very common combination, so we provide the combined operation.
726  */
727 void *
729 {
730  void *ret;
731 
734 
735  if (!AllocSizeIsValid(size))
736  elog(ERROR, "invalid memory alloc request size %zu", size);
737 
738  context->isReset = false;
739 
740  ret = context->methods->alloc(context, size);
741  if (ret == NULL)
742  {
743  MemoryContextStats(TopMemoryContext);
744  ereport(ERROR,
745  (errcode(ERRCODE_OUT_OF_MEMORY),
746  errmsg("out of memory"),
747  errdetail("Failed on request of size %zu.", size)));
748  }
749 
750  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
751 
752  MemSetAligned(ret, 0, size);
753 
754  return ret;
755 }
756 
757 /*
758  * MemoryContextAllocZeroAligned
759  * MemoryContextAllocZero where length is suitable for MemSetLoop
760  *
761  * This might seem overly specialized, but it's not because newNode()
762  * is so often called with compile-time-constant sizes.
763  */
764 void *
766 {
767  void *ret;
768 
771 
772  if (!AllocSizeIsValid(size))
773  elog(ERROR, "invalid memory alloc request size %zu", size);
774 
775  context->isReset = false;
776 
777  ret = context->methods->alloc(context, size);
778  if (ret == NULL)
779  {
780  MemoryContextStats(TopMemoryContext);
781  ereport(ERROR,
782  (errcode(ERRCODE_OUT_OF_MEMORY),
783  errmsg("out of memory"),
784  errdetail("Failed on request of size %zu.", size)));
785  }
786 
787  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
788 
789  MemSetLoop(ret, 0, size);
790 
791  return ret;
792 }
793 
794 /*
795  * MemoryContextAllocExtended
796  * Allocate space within the specified context using the given flags.
797  */
798 void *
800 {
801  void *ret;
802 
805 
806  if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
807  ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
808  elog(ERROR, "invalid memory alloc request size %zu", size);
809 
810  context->isReset = false;
811 
812  ret = context->methods->alloc(context, size);
813  if (ret == NULL)
814  {
815  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
816  {
817  MemoryContextStats(TopMemoryContext);
818  ereport(ERROR,
819  (errcode(ERRCODE_OUT_OF_MEMORY),
820  errmsg("out of memory"),
821  errdetail("Failed on request of size %zu.", size)));
822  }
823  return NULL;
824  }
825 
826  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
827 
828  if ((flags & MCXT_ALLOC_ZERO) != 0)
829  MemSetAligned(ret, 0, size);
830 
831  return ret;
832 }
833 
834 void *
836 {
837  /* duplicates MemoryContextAlloc to avoid increased overhead */
838  void *ret;
839 
840  AssertArg(MemoryContextIsValid(CurrentMemoryContext));
841  AssertNotInCriticalSection(CurrentMemoryContext);
842 
843  if (!AllocSizeIsValid(size))
844  elog(ERROR, "invalid memory alloc request size %zu", size);
845 
846  CurrentMemoryContext->isReset = false;
847 
848  ret = CurrentMemoryContext->methods->alloc(CurrentMemoryContext, size);
849  if (ret == NULL)
850  {
851  MemoryContextStats(TopMemoryContext);
852  ereport(ERROR,
853  (errcode(ERRCODE_OUT_OF_MEMORY),
854  errmsg("out of memory"),
855  errdetail("Failed on request of size %zu.", size)));
856  }
857 
858  VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
859 
860  return ret;
861 }
862 
863 void *
865 {
866  /* duplicates MemoryContextAllocZero to avoid increased overhead */
867  void *ret;
868 
869  AssertArg(MemoryContextIsValid(CurrentMemoryContext));
870  AssertNotInCriticalSection(CurrentMemoryContext);
871 
872  if (!AllocSizeIsValid(size))
873  elog(ERROR, "invalid memory alloc request size %zu", size);
874 
875  CurrentMemoryContext->isReset = false;
876 
877  ret = CurrentMemoryContext->methods->alloc(CurrentMemoryContext, size);
878  if (ret == NULL)
879  {
880  MemoryContextStats(TopMemoryContext);
881  ereport(ERROR,
882  (errcode(ERRCODE_OUT_OF_MEMORY),
883  errmsg("out of memory"),
884  errdetail("Failed on request of size %zu.", size)));
885  }
886 
887  VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
888 
889  MemSetAligned(ret, 0, size);
890 
891  return ret;
892 }
893 
894 void *
895 palloc_extended(Size size, int flags)
896 {
897  /* duplicates MemoryContextAllocExtended to avoid increased overhead */
898  void *ret;
899 
900  AssertArg(MemoryContextIsValid(CurrentMemoryContext));
901  AssertNotInCriticalSection(CurrentMemoryContext);
902 
903  if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
904  ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
905  elog(ERROR, "invalid memory alloc request size %zu", size);
906 
907  CurrentMemoryContext->isReset = false;
908 
909  ret = CurrentMemoryContext->methods->alloc(CurrentMemoryContext, size);
910  if (ret == NULL)
911  {
912  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
913  {
914  MemoryContextStats(TopMemoryContext);
915  ereport(ERROR,
916  (errcode(ERRCODE_OUT_OF_MEMORY),
917  errmsg("out of memory"),
918  errdetail("Failed on request of size %zu.", size)));
919  }
920  return NULL;
921  }
922 
923  VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
924 
925  if ((flags & MCXT_ALLOC_ZERO) != 0)
926  MemSetAligned(ret, 0, size);
927 
928  return ret;
929 }
930 
931 /*
932  * pfree
933  * Release an allocated chunk.
934  */
935 void
936 pfree(void *pointer)
937 {
938  MemoryContext context = GetMemoryChunkContext(pointer);
939 
940  context->methods->free_p(context, pointer);
941  VALGRIND_MEMPOOL_FREE(context, pointer);
942 }
943 
944 /*
945  * repalloc
946  * Adjust the size of a previously allocated chunk.
947  */
948 void *
949 repalloc(void *pointer, Size size)
950 {
951  MemoryContext context = GetMemoryChunkContext(pointer);
952  void *ret;
953 
954  if (!AllocSizeIsValid(size))
955  elog(ERROR, "invalid memory alloc request size %zu", size);
956 
958 
959  /* isReset must be false already */
960  Assert(!context->isReset);
961 
962  ret = context->methods->realloc(context, pointer, size);
963  if (ret == NULL)
964  {
965  MemoryContextStats(TopMemoryContext);
966  ereport(ERROR,
967  (errcode(ERRCODE_OUT_OF_MEMORY),
968  errmsg("out of memory"),
969  errdetail("Failed on request of size %zu.", size)));
970  }
971 
972  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
973 
974  return ret;
975 }
976 
977 /*
978  * MemoryContextAllocHuge
979  * Allocate (possibly-expansive) space within the specified context.
980  *
981  * See considerations in comment at MaxAllocHugeSize.
982  */
983 void *
985 {
986  void *ret;
987 
990 
991  if (!AllocHugeSizeIsValid(size))
992  elog(ERROR, "invalid memory alloc request size %zu", size);
993 
994  context->isReset = false;
995 
996  ret = context->methods->alloc(context, size);
997  if (ret == NULL)
998  {
999  MemoryContextStats(TopMemoryContext);
1000  ereport(ERROR,
1001  (errcode(ERRCODE_OUT_OF_MEMORY),
1002  errmsg("out of memory"),
1003  errdetail("Failed on request of size %zu.", size)));
1004  }
1005 
1006  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1007 
1008  return ret;
1009 }
1010 
1011 /*
1012  * repalloc_huge
1013  * Adjust the size of a previously allocated chunk, permitting a large
1014  * value. The previous allocation need not have been "huge".
1015  */
1016 void *
1017 repalloc_huge(void *pointer, Size size)
1018 {
1019  MemoryContext context = GetMemoryChunkContext(pointer);
1020  void *ret;
1021 
1022  if (!AllocHugeSizeIsValid(size))
1023  elog(ERROR, "invalid memory alloc request size %zu", size);
1024 
1025  AssertNotInCriticalSection(context);
1026 
1027  /* isReset must be false already */
1028  Assert(!context->isReset);
1029 
1030  ret = context->methods->realloc(context, pointer, size);
1031  if (ret == NULL)
1032  {
1033  MemoryContextStats(TopMemoryContext);
1034  ereport(ERROR,
1035  (errcode(ERRCODE_OUT_OF_MEMORY),
1036  errmsg("out of memory"),
1037  errdetail("Failed on request of size %zu.", size)));
1038  }
1039 
1040  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1041 
1042  return ret;
1043 }
1044 
1045 /*
1046  * MemoryContextStrdup
1047  * Like strdup(), but allocate from the specified context
1048  */
1049 char *
1050 MemoryContextStrdup(MemoryContext context, const char *string)
1051 {
1052  char *nstr;
1053  Size len = strlen(string) + 1;
1054 
1055  nstr = (char *) MemoryContextAlloc(context, len);
1056 
1057  memcpy(nstr, string, len);
1058 
1059  return nstr;
1060 }
1061 
1062 char *
1063 pstrdup(const char *in)
1064 {
1065  return MemoryContextStrdup(CurrentMemoryContext, in);
1066 }
1067 
1068 /*
1069  * pnstrdup
1070  * Like pstrdup(), but append null byte to a
1071  * not-necessarily-null-terminated input string.
1072  */
1073 char *
1074 pnstrdup(const char *in, Size len)
1075 {
1076  char *out;
1077 
1078  len = strnlen(in, len);
1079 
1080  out = palloc(len + 1);
1081  memcpy(out, in, len);
1082  out[len] = '\0';
1083 
1084  return out;
1085 }
1086 
1087 /*
1088  * Make copy of string with all trailing newline characters removed.
1089  */
1090 char *
1091 pchomp(const char *in)
1092 {
1093  size_t n;
1094 
1095  n = strlen(in);
1096  while (n > 0 && in[n - 1] == '\n')
1097  n--;
1098  return pnstrdup(in, n);
1099 }
#define MemSetAligned(start, val, len)
Definition: c.h:910
MemoryContextCallbackFunction func
Definition: palloc.h:49
Size(* get_chunk_space)(MemoryContext context, void *pointer)
Definition: memnodes.h:62
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:198
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1074
static void MemoryContextCallResetCallbacks(MemoryContext context)
Definition: mcxt.c:282
#define AssertState(condition)
Definition: c.h:683
MemoryContext TopTransactionContext
Definition: mcxt.c:48
MemoryContextCallback * reset_cbs
Definition: memnodes.h:84
void print(const void *obj)
Definition: print.c:35
void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
Definition: mcxt.c:374
void MemoryContextInit(void)
Definition: mcxt.c:89
#define MCXT_ALLOC_HUGE
Definition: fe_memutils.h:16
const MemoryContextMethods * methods
Definition: memnodes.h:78
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:402
MemoryContext ErrorContext
Definition: mcxt.c:44
void(* reset)(MemoryContext context)
Definition: memnodes.h:60
#define MEMCONTEXT_COPY_NAME
Definition: memutils.h:188
void * MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
Definition: mcxt.c:799
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
char * pstrdup(const char *in)
Definition: mcxt.c:1063
bool allowInCritSection
Definition: memnodes.h:77
static void MemoryContextStatsInternal(MemoryContext context, int level, bool print, int max_children, MemoryContextCounters *totals)
Definition: mcxt.c:472
MemoryContext CurTransactionContext
Definition: mcxt.c:49
void * palloc_extended(Size size, int flags)
Definition: mcxt.c:895
#define MCXT_ALLOC_NO_OOM
Definition: fe_memutils.h:18
int errcode(int sqlerrcode)
Definition: elog.c:575
Size GetMemoryChunkSpace(void *pointer)
Definition: mcxt.c:390
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:134
#define AssertNotInCriticalSection(context)
Definition: mcxt.c:64
NodeTag
Definition: nodes.h:26
void MemoryContextResetOnly(MemoryContext context)
Definition: mcxt.c:153
void *(* realloc)(MemoryContext context, void *pointer, Size size)
Definition: memnodes.h:59
MemoryContext PortalContext
Definition: mcxt.c:52
char * pchomp(const char *in)
Definition: mcxt.c:1091
MemoryContext firstchild
Definition: memnodes.h:80
void pfree(void *pointer)
Definition: mcxt.c:936
void(* free_p)(MemoryContext context, void *pointer)
Definition: memnodes.h:58
#define ERROR
Definition: elog.h:43
bool MemoryContextIsEmpty(MemoryContext context)
Definition: mcxt.c:414
bool(* is_empty)(MemoryContext context)
Definition: memnodes.h:63
MemoryContext AllocSetContextCreateExtended(MemoryContext parent, const char *name, int flags, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:394
#define VALGRIND_MEMPOOL_CHANGE(context, optr, nptr, size)
Definition: memdebug.h:31
void MemoryContextStats(MemoryContext context)
Definition: mcxt.c:437
#define MemSetLoop(start, val, len)
Definition: c.h:945
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
void MemoryContextCreate(MemoryContext node, NodeTag tag, Size size, Size nameoffset, const MemoryContextMethods *methods, MemoryContext parent, const char *name, int flags)
Definition: mcxt.c:627
void * MemoryContextAllocHuge(MemoryContext context, Size size)
Definition: mcxt.c:984
#define VALGRIND_MEMPOOL_FREE(context, addr)
Definition: memdebug.h:30
int errdetail(const char *fmt,...)
Definition: elog.c:873
MemoryContext prevchild
Definition: memnodes.h:81
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
void *(* alloc)(MemoryContext context, Size size)
Definition: memnodes.h:56
volatile uint32 CritSectionCount
Definition: globals.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
#define AssertArg(condition)
Definition: c.h:682
void * MemoryContextAllocZeroAligned(MemoryContext context, Size size)
Definition: mcxt.c:765
MemoryContext TopMemoryContext
Definition: mcxt.c:43
#define AllocSizeIsValid(size)
Definition: memutils.h:42
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:236
#define VALGRIND_DESTROY_MEMPOOL(context)
Definition: memdebug.h:25
void * palloc0(Size size)
Definition: mcxt.c:864
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:728
#define VALGRIND_CREATE_MEMPOOL(context, redzones, zeroed)
Definition: memdebug.h:24
#define MemoryContextIsValid(context)
Definition: memnodes.h:96
#define VALGRIND_MEMPOOL_ALLOC(context, addr, size)
Definition: memdebug.h:29
#define Assert(condition)
Definition: c.h:680
void MemoryContextResetChildren(MemoryContext context)
Definition: mcxt.c:175
#define MCXT_ALLOC_ZERO
Definition: fe_memutils.h:19
bool MemoryContextContains(MemoryContext context, void *pointer)
Definition: mcxt.c:566
void(* stats)(MemoryContext context, int level, bool print, MemoryContextCounters *totals)
Definition: memnodes.h:64
size_t Size
Definition: c.h:414
#define MAXALIGN(LEN)
Definition: c.h:633
size_t strnlen(const char *str, size_t maxlen)
Definition: strnlen.c:26
MemoryContext MessageContext
Definition: mcxt.c:47
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:949
const char * name
Definition: encode.c:521
#define AllocHugeSizeIsValid(size)
Definition: memutils.h:46
void * repalloc_huge(void *pointer, Size size)
Definition: mcxt.c:1017
void * palloc(Size size)
Definition: mcxt.c:835
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1050
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:693
struct MemoryContextCallback * next
Definition: palloc.h:51
int i
MemoryContext parent
Definition: memnodes.h:79
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:265
void(* delete_context)(MemoryContext context)
Definition: memnodes.h:61
#define elog
Definition: elog.h:219
MemoryContext PostmasterContext
Definition: mcxt.c:45
const char * name
Definition: memnodes.h:83
MemoryContext nextchild
Definition: memnodes.h:82
void MemoryContextStatsDetail(MemoryContext context, int max_children)
Definition: mcxt.c:449
static MemoryContext GetMemoryChunkContext(void *pointer)
Definition: memutils.h:107
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
NodeTag type
Definition: memnodes.h:74