PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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-2017, 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 will hold the MemoryContext
95  * nodes for all other contexts. (There is special-case code in
96  * MemoryContextCreate() to handle this call.)
97  */
98  TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
99  "TopMemoryContext",
101 
102  /*
103  * Not having any other place to point CurrentMemoryContext, make it point
104  * to TopMemoryContext. Caller should change this soon!
105  */
106  CurrentMemoryContext = TopMemoryContext;
107 
108  /*
109  * Initialize ErrorContext as an AllocSetContext with slow growth rate ---
110  * we don't really expect much to be allocated in it. More to the point,
111  * require it to contain at least 8K at all times. This is the only case
112  * where retained memory in a context is *essential* --- we want to be
113  * sure ErrorContext still has some memory even if we've run out
114  * elsewhere! Also, allow allocations in ErrorContext within a critical
115  * section. Otherwise a PANIC will cause an assertion failure in the error
116  * reporting code, before printing out the real cause of the failure.
117  *
118  * This should be the last step in this function, as elog.c assumes memory
119  * management works once ErrorContext is non-null.
120  */
121  ErrorContext = AllocSetContextCreate(TopMemoryContext,
122  "ErrorContext",
123  8 * 1024,
124  8 * 1024,
125  8 * 1024);
126  MemoryContextAllowInCriticalSection(ErrorContext, true);
127 }
128 
129 /*
130  * MemoryContextReset
131  * Release all space allocated within a context and delete all its
132  * descendant contexts (but not the named context itself).
133  */
134 void
136 {
138 
139  /* save a function call in common case where there are no children */
140  if (context->firstchild != NULL)
142 
143  /* save a function call if no pallocs since startup or last reset */
144  if (!context->isReset)
145  MemoryContextResetOnly(context);
146 }
147 
148 /*
149  * MemoryContextResetOnly
150  * Release all space allocated within a context.
151  * Nothing is done to the context's descendant contexts.
152  */
153 void
155 {
157 
158  /* Nothing to do if no pallocs since startup or last reset */
159  if (!context->isReset)
160  {
162  (*context->methods->reset) (context);
163  context->isReset = true;
164  VALGRIND_DESTROY_MEMPOOL(context);
165  VALGRIND_CREATE_MEMPOOL(context, 0, false);
166  }
167 }
168 
169 /*
170  * MemoryContextResetChildren
171  * Release all space allocated within a context's descendants,
172  * but don't delete the contexts themselves. The named context
173  * itself is not touched.
174  */
175 void
177 {
178  MemoryContext child;
179 
181 
182  for (child = context->firstchild; child != NULL; child = child->nextchild)
183  {
185  MemoryContextResetOnly(child);
186  }
187 }
188 
189 /*
190  * MemoryContextDelete
191  * Delete a context and its descendants, and release all space
192  * allocated therein.
193  *
194  * The type-specific delete routine removes all subsidiary storage
195  * for the context, but we have to delete the context node itself,
196  * as well as recurse to get the children. We must also delink the
197  * node from its parent, if it has one.
198  */
199 void
201 {
203  /* We had better not be deleting TopMemoryContext ... */
204  Assert(context != TopMemoryContext);
205  /* And not CurrentMemoryContext, either */
206  Assert(context != CurrentMemoryContext);
207 
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  VALGRIND_DESTROY_MEMPOOL(context);
227  pfree(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,
395  pointer);
396 }
397 
398 /*
399  * MemoryContextGetParent
400  * Get the parent context (if any) of the specified context
401  */
404 {
406 
407  return context->parent;
408 }
409 
410 /*
411  * MemoryContextIsEmpty
412  * Is a memory context empty of any allocated space?
413  */
414 bool
416 {
418 
419  /*
420  * For now, we consider a memory context nonempty if it has any children;
421  * perhaps this should be changed later.
422  */
423  if (context->firstchild != NULL)
424  return false;
425  /* Otherwise use the type-specific inquiry */
426  return (*context->methods->is_empty) (context);
427 }
428 
429 /*
430  * MemoryContextStats
431  * Print statistics about the named context and all its descendants.
432  *
433  * This is just a debugging utility, so it's not very fancy. However, we do
434  * make some effort to summarize when the output would otherwise be very long.
435  * The statistics are sent to stderr.
436  */
437 void
439 {
440  /* A hard-wired limit on the number of children is usually good enough */
441  MemoryContextStatsDetail(context, 100);
442 }
443 
444 /*
445  * MemoryContextStatsDetail
446  *
447  * Entry point for use if you want to vary the number of child contexts shown.
448  */
449 void
450 MemoryContextStatsDetail(MemoryContext context, int max_children)
451 {
452  MemoryContextCounters grand_totals;
453 
454  memset(&grand_totals, 0, sizeof(grand_totals));
455 
456  MemoryContextStatsInternal(context, 0, true, max_children, &grand_totals);
457 
458  fprintf(stderr,
459  "Grand total: %zu bytes in %zd blocks; %zu free (%zd chunks); %zu used\n",
460  grand_totals.totalspace, grand_totals.nblocks,
461  grand_totals.freespace, grand_totals.freechunks,
462  grand_totals.totalspace - grand_totals.freespace);
463 }
464 
465 /*
466  * MemoryContextStatsInternal
467  * One recursion level for MemoryContextStats
468  *
469  * Print this context if print is true, but in any case accumulate counts into
470  * *totals (if given).
471  */
472 static void
474  bool print, int max_children,
475  MemoryContextCounters *totals)
476 {
477  MemoryContextCounters local_totals;
478  MemoryContext child;
479  int ichild;
480 
482 
483  /* Examine the context itself */
484  (*context->methods->stats) (context, level, print, totals);
485 
486  /*
487  * Examine children. If there are more than max_children of them, we do
488  * not print the rest explicitly, but just summarize them.
489  */
490  memset(&local_totals, 0, sizeof(local_totals));
491 
492  for (child = context->firstchild, ichild = 0;
493  child != NULL;
494  child = child->nextchild, ichild++)
495  {
496  if (ichild < max_children)
497  MemoryContextStatsInternal(child, level + 1,
498  print, max_children,
499  totals);
500  else
501  MemoryContextStatsInternal(child, level + 1,
502  false, max_children,
503  &local_totals);
504  }
505 
506  /* Deal with excess children */
507  if (ichild > max_children)
508  {
509  if (print)
510  {
511  int i;
512 
513  for (i = 0; i <= level; i++)
514  fprintf(stderr, " ");
515  fprintf(stderr,
516  "%d more child contexts containing %zu total in %zd blocks; %zu free (%zd chunks); %zu used\n",
517  ichild - max_children,
518  local_totals.totalspace,
519  local_totals.nblocks,
520  local_totals.freespace,
521  local_totals.freechunks,
522  local_totals.totalspace - local_totals.freespace);
523  }
524 
525  if (totals)
526  {
527  totals->nblocks += local_totals.nblocks;
528  totals->freechunks += local_totals.freechunks;
529  totals->totalspace += local_totals.totalspace;
530  totals->freespace += local_totals.freespace;
531  }
532  }
533 }
534 
535 /*
536  * MemoryContextCheck
537  * Check all chunks in the named context.
538  *
539  * This is just a debugging utility, so it's not fancy.
540  */
541 #ifdef MEMORY_CONTEXT_CHECKING
542 void
543 MemoryContextCheck(MemoryContext context)
544 {
545  MemoryContext child;
546 
548 
549  (*context->methods->check) (context);
550  for (child = context->firstchild; child != NULL; child = child->nextchild)
551  MemoryContextCheck(child);
552 }
553 #endif
554 
555 /*
556  * MemoryContextContains
557  * Detect whether an allocated chunk of memory belongs to a given
558  * context or not.
559  *
560  * Caution: this test is reliable as long as 'pointer' does point to
561  * a chunk of memory allocated from *some* context. If 'pointer' points
562  * at memory obtained in some other way, there is a small chance of a
563  * false-positive result, since the bits right before it might look like
564  * a valid chunk header by chance.
565  */
566 bool
567 MemoryContextContains(MemoryContext context, void *pointer)
568 {
569  MemoryContext ptr_context;
570 
571  /*
572  * NB: Can't use GetMemoryChunkContext() here - that performs assertions
573  * that aren't acceptable here since we might be passed memory not
574  * allocated by any memory context.
575  *
576  * Try to detect bogus pointers handed to us, poorly though we can.
577  * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
578  * allocated chunk.
579  */
580  if (pointer == NULL || pointer != (void *) MAXALIGN(pointer))
581  return false;
582 
583  /*
584  * OK, it's probably safe to look at the context.
585  */
586  ptr_context = *(MemoryContext *) (((char *) pointer) - sizeof(void *));
587 
588  return ptr_context == context;
589 }
590 
591 /*--------------------
592  * MemoryContextCreate
593  * Context-type-independent part of context creation.
594  *
595  * This is only intended to be called by context-type-specific
596  * context creation routines, not by the unwashed masses.
597  *
598  * The context creation procedure is a little bit tricky because
599  * we want to be sure that we don't leave the context tree invalid
600  * in case of failure (such as insufficient memory to allocate the
601  * context node itself). The procedure goes like this:
602  * 1. Context-type-specific routine first calls MemoryContextCreate(),
603  * passing the appropriate tag/size/methods values (the methods
604  * pointer will ordinarily point to statically allocated data).
605  * The parent and name parameters usually come from the caller.
606  * 2. MemoryContextCreate() attempts to allocate the context node,
607  * plus space for the name. If this fails we can ereport() with no
608  * damage done.
609  * 3. We fill in all of the type-independent MemoryContext fields.
610  * 4. We call the type-specific init routine (using the methods pointer).
611  * The init routine is required to make the node minimally valid
612  * with zero chance of failure --- it can't allocate more memory,
613  * for example.
614  * 5. Now we have a minimally valid node that can behave correctly
615  * when told to reset or delete itself. We link the node to its
616  * parent (if any), making the node part of the context tree.
617  * 6. We return to the context-type-specific routine, which finishes
618  * up type-specific initialization. This routine can now do things
619  * that might fail (like allocate more memory), so long as it's
620  * sure the node is left in a state that delete will handle.
621  *
622  * This protocol doesn't prevent us from leaking memory if step 6 fails
623  * during creation of a top-level context, since there's no parent link
624  * in that case. However, if you run out of memory while you're building
625  * a top-level context, you might as well go home anyway...
626  *
627  * Normally, the context node and the name are allocated from
628  * TopMemoryContext (NOT from the parent context, since the node must
629  * survive resets of its parent context!). However, this routine is itself
630  * used to create TopMemoryContext! If we see that TopMemoryContext is NULL,
631  * we assume we are creating TopMemoryContext and use malloc() to allocate
632  * the node.
633  *
634  * Note that the name field of a MemoryContext does not point to
635  * separately-allocated storage, so it should not be freed at context
636  * deletion.
637  *--------------------
638  */
641  MemoryContextMethods *methods,
642  MemoryContext parent,
643  const char *name)
644 {
645  MemoryContext node;
646  Size needed = size + strlen(name) + 1;
647 
648  /* creating new memory contexts is not allowed in a critical section */
649  Assert(CritSectionCount == 0);
650 
651  /* Get space for node and name */
652  if (TopMemoryContext != NULL)
653  {
654  /* Normal case: allocate the node in TopMemoryContext */
655  node = (MemoryContext) MemoryContextAlloc(TopMemoryContext,
656  needed);
657  }
658  else
659  {
660  /* Special case for startup: use good ol' malloc */
661  node = (MemoryContext) malloc(needed);
662  Assert(node != NULL);
663  }
664 
665  /* Initialize the node as best we can */
666  MemSet(node, 0, size);
667  node->type = tag;
668  node->methods = methods;
669  node->parent = NULL; /* for the moment */
670  node->firstchild = NULL;
671  node->prevchild = NULL;
672  node->nextchild = NULL;
673  node->isReset = true;
674  node->name = ((char *) node) + size;
675  strcpy(node->name, name);
676 
677  /* Type-specific routine finishes any other essential initialization */
678  (*node->methods->init) (node);
679 
680  /* OK to link node to parent (if any) */
681  /* Could use MemoryContextSetParent here, but doesn't seem worthwhile */
682  if (parent)
683  {
684  node->parent = parent;
685  node->nextchild = parent->firstchild;
686  if (parent->firstchild != NULL)
687  parent->firstchild->prevchild = node;
688  parent->firstchild = node;
689  /* inherit allowInCritSection flag from parent */
690  node->allowInCritSection = parent->allowInCritSection;
691  }
692 
693  VALGRIND_CREATE_MEMPOOL(node, 0, false);
694 
695  /* Return to type-specific creation routine to finish up */
696  return node;
697 }
698 
699 /*
700  * MemoryContextAlloc
701  * Allocate space within the specified context.
702  *
703  * This could be turned into a macro, but we'd have to import
704  * nodes/memnodes.h into postgres.h which seems a bad idea.
705  */
706 void *
708 {
709  void *ret;
710 
713 
714  if (!AllocSizeIsValid(size))
715  elog(ERROR, "invalid memory alloc request size %zu", size);
716 
717  context->isReset = false;
718 
719  ret = (*context->methods->alloc) (context, size);
720  if (ret == NULL)
721  {
722  MemoryContextStats(TopMemoryContext);
723  ereport(ERROR,
724  (errcode(ERRCODE_OUT_OF_MEMORY),
725  errmsg("out of memory"),
726  errdetail("Failed on request of size %zu.", size)));
727  }
728 
729  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
730 
731  return ret;
732 }
733 
734 /*
735  * MemoryContextAllocZero
736  * Like MemoryContextAlloc, but clears allocated memory
737  *
738  * We could just call MemoryContextAlloc then clear the memory, but this
739  * is a very common combination, so we provide the combined operation.
740  */
741 void *
743 {
744  void *ret;
745 
748 
749  if (!AllocSizeIsValid(size))
750  elog(ERROR, "invalid memory alloc request size %zu", size);
751 
752  context->isReset = false;
753 
754  ret = (*context->methods->alloc) (context, size);
755  if (ret == NULL)
756  {
757  MemoryContextStats(TopMemoryContext);
758  ereport(ERROR,
759  (errcode(ERRCODE_OUT_OF_MEMORY),
760  errmsg("out of memory"),
761  errdetail("Failed on request of size %zu.", size)));
762  }
763 
764  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
765 
766  MemSetAligned(ret, 0, size);
767 
768  return ret;
769 }
770 
771 /*
772  * MemoryContextAllocZeroAligned
773  * MemoryContextAllocZero where length is suitable for MemSetLoop
774  *
775  * This might seem overly specialized, but it's not because newNode()
776  * is so often called with compile-time-constant sizes.
777  */
778 void *
780 {
781  void *ret;
782 
785 
786  if (!AllocSizeIsValid(size))
787  elog(ERROR, "invalid memory alloc request size %zu", size);
788 
789  context->isReset = false;
790 
791  ret = (*context->methods->alloc) (context, size);
792  if (ret == NULL)
793  {
794  MemoryContextStats(TopMemoryContext);
795  ereport(ERROR,
796  (errcode(ERRCODE_OUT_OF_MEMORY),
797  errmsg("out of memory"),
798  errdetail("Failed on request of size %zu.", size)));
799  }
800 
801  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
802 
803  MemSetLoop(ret, 0, size);
804 
805  return ret;
806 }
807 
808 /*
809  * MemoryContextAllocExtended
810  * Allocate space within the specified context using the given flags.
811  */
812 void *
814 {
815  void *ret;
816 
819 
820  if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
821  ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
822  elog(ERROR, "invalid memory alloc request size %zu", size);
823 
824  context->isReset = false;
825 
826  ret = (*context->methods->alloc) (context, size);
827  if (ret == NULL)
828  {
829  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
830  {
831  MemoryContextStats(TopMemoryContext);
832  ereport(ERROR,
833  (errcode(ERRCODE_OUT_OF_MEMORY),
834  errmsg("out of memory"),
835  errdetail("Failed on request of size %zu.", size)));
836  }
837  return NULL;
838  }
839 
840  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
841 
842  if ((flags & MCXT_ALLOC_ZERO) != 0)
843  MemSetAligned(ret, 0, size);
844 
845  return ret;
846 }
847 
848 void *
850 {
851  /* duplicates MemoryContextAlloc to avoid increased overhead */
852  void *ret;
853 
854  AssertArg(MemoryContextIsValid(CurrentMemoryContext));
855  AssertNotInCriticalSection(CurrentMemoryContext);
856 
857  if (!AllocSizeIsValid(size))
858  elog(ERROR, "invalid memory alloc request size %zu", size);
859 
860  CurrentMemoryContext->isReset = false;
861 
862  ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
863  if (ret == NULL)
864  {
865  MemoryContextStats(TopMemoryContext);
866  ereport(ERROR,
867  (errcode(ERRCODE_OUT_OF_MEMORY),
868  errmsg("out of memory"),
869  errdetail("Failed on request of size %zu.", size)));
870  }
871 
872  VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
873 
874  return ret;
875 }
876 
877 void *
879 {
880  /* duplicates MemoryContextAllocZero to avoid increased overhead */
881  void *ret;
882 
883  AssertArg(MemoryContextIsValid(CurrentMemoryContext));
884  AssertNotInCriticalSection(CurrentMemoryContext);
885 
886  if (!AllocSizeIsValid(size))
887  elog(ERROR, "invalid memory alloc request size %zu", size);
888 
889  CurrentMemoryContext->isReset = false;
890 
891  ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
892  if (ret == NULL)
893  {
894  MemoryContextStats(TopMemoryContext);
895  ereport(ERROR,
896  (errcode(ERRCODE_OUT_OF_MEMORY),
897  errmsg("out of memory"),
898  errdetail("Failed on request of size %zu.", size)));
899  }
900 
901  VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
902 
903  MemSetAligned(ret, 0, size);
904 
905  return ret;
906 }
907 
908 void *
909 palloc_extended(Size size, int flags)
910 {
911  /* duplicates MemoryContextAllocExtended to avoid increased overhead */
912  void *ret;
913 
914  AssertArg(MemoryContextIsValid(CurrentMemoryContext));
915  AssertNotInCriticalSection(CurrentMemoryContext);
916 
917  if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
918  ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
919  elog(ERROR, "invalid memory alloc request size %zu", size);
920 
921  CurrentMemoryContext->isReset = false;
922 
923  ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
924  if (ret == NULL)
925  {
926  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
927  {
928  MemoryContextStats(TopMemoryContext);
929  ereport(ERROR,
930  (errcode(ERRCODE_OUT_OF_MEMORY),
931  errmsg("out of memory"),
932  errdetail("Failed on request of size %zu.", size)));
933  }
934  return NULL;
935  }
936 
937  VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
938 
939  if ((flags & MCXT_ALLOC_ZERO) != 0)
940  MemSetAligned(ret, 0, size);
941 
942  return ret;
943 }
944 
945 /*
946  * pfree
947  * Release an allocated chunk.
948  */
949 void
950 pfree(void *pointer)
951 {
952  MemoryContext context = GetMemoryChunkContext(pointer);
953 
954  (*context->methods->free_p) (context, pointer);
955  VALGRIND_MEMPOOL_FREE(context, pointer);
956 }
957 
958 /*
959  * repalloc
960  * Adjust the size of a previously allocated chunk.
961  */
962 void *
963 repalloc(void *pointer, Size size)
964 {
965  MemoryContext context = GetMemoryChunkContext(pointer);
966  void *ret;
967 
968  if (!AllocSizeIsValid(size))
969  elog(ERROR, "invalid memory alloc request size %zu", size);
970 
972 
973  /* isReset must be false already */
974  Assert(!context->isReset);
975 
976  ret = (*context->methods->realloc) (context, pointer, size);
977  if (ret == NULL)
978  {
979  MemoryContextStats(TopMemoryContext);
980  ereport(ERROR,
981  (errcode(ERRCODE_OUT_OF_MEMORY),
982  errmsg("out of memory"),
983  errdetail("Failed on request of size %zu.", size)));
984  }
985 
986  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
987 
988  return ret;
989 }
990 
991 /*
992  * MemoryContextAllocHuge
993  * Allocate (possibly-expansive) space within the specified context.
994  *
995  * See considerations in comment at MaxAllocHugeSize.
996  */
997 void *
999 {
1000  void *ret;
1001 
1002  AssertArg(MemoryContextIsValid(context));
1003  AssertNotInCriticalSection(context);
1004 
1005  if (!AllocHugeSizeIsValid(size))
1006  elog(ERROR, "invalid memory alloc request size %zu", size);
1007 
1008  context->isReset = false;
1009 
1010  ret = (*context->methods->alloc) (context, size);
1011  if (ret == NULL)
1012  {
1013  MemoryContextStats(TopMemoryContext);
1014  ereport(ERROR,
1015  (errcode(ERRCODE_OUT_OF_MEMORY),
1016  errmsg("out of memory"),
1017  errdetail("Failed on request of size %zu.", size)));
1018  }
1019 
1020  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1021 
1022  return ret;
1023 }
1024 
1025 /*
1026  * repalloc_huge
1027  * Adjust the size of a previously allocated chunk, permitting a large
1028  * value. The previous allocation need not have been "huge".
1029  */
1030 void *
1031 repalloc_huge(void *pointer, Size size)
1032 {
1033  MemoryContext context = GetMemoryChunkContext(pointer);
1034  void *ret;
1035 
1036  if (!AllocHugeSizeIsValid(size))
1037  elog(ERROR, "invalid memory alloc request size %zu", size);
1038 
1039  AssertNotInCriticalSection(context);
1040 
1041  /* isReset must be false already */
1042  Assert(!context->isReset);
1043 
1044  ret = (*context->methods->realloc) (context, pointer, size);
1045  if (ret == NULL)
1046  {
1047  MemoryContextStats(TopMemoryContext);
1048  ereport(ERROR,
1049  (errcode(ERRCODE_OUT_OF_MEMORY),
1050  errmsg("out of memory"),
1051  errdetail("Failed on request of size %zu.", size)));
1052  }
1053 
1054  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1055 
1056  return ret;
1057 }
1058 
1059 /*
1060  * MemoryContextStrdup
1061  * Like strdup(), but allocate from the specified context
1062  */
1063 char *
1064 MemoryContextStrdup(MemoryContext context, const char *string)
1065 {
1066  char *nstr;
1067  Size len = strlen(string) + 1;
1068 
1069  nstr = (char *) MemoryContextAlloc(context, len);
1070 
1071  memcpy(nstr, string, len);
1072 
1073  return nstr;
1074 }
1075 
1076 char *
1077 pstrdup(const char *in)
1078 {
1079  return MemoryContextStrdup(CurrentMemoryContext, in);
1080 }
1081 
1082 /*
1083  * pnstrdup
1084  * Like pstrdup(), but append null byte to a
1085  * not-necessarily-null-terminated input string.
1086  */
1087 char *
1088 pnstrdup(const char *in, Size len)
1089 {
1090  char *out = palloc(len + 1);
1091 
1092  memcpy(out, in, len);
1093  out[len] = '\0';
1094  return out;
1095 }
1096 
1097 /*
1098  * Make copy of string with all trailing newline characters removed.
1099  */
1100 char *
1101 pchomp(const char *in)
1102 {
1103  size_t n;
1104 
1105  n = strlen(in);
1106  while (n > 0 && in[n - 1] == '\n')
1107  n--;
1108  return pnstrdup(in, n);
1109 }
#define MemSetAligned(start, val, len)
Definition: c.h:890
MemoryContextCallbackFunction func
Definition: palloc.h:49
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1088
static void MemoryContextCallResetCallbacks(MemoryContext context)
Definition: mcxt.c:282
#define AssertState(condition)
Definition: c.h:678
MemoryContext TopTransactionContext
Definition: mcxt.c:48
MemoryContextCallback * reset_cbs
Definition: memnodes.h:85
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
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:403
MemoryContext ErrorContext
Definition: mcxt.c:44
void * MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
Definition: mcxt.c:813
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
MemoryContextMethods * methods
Definition: memnodes.h:79
char * pstrdup(const char *in)
Definition: mcxt.c:1077
bool allowInCritSection
Definition: memnodes.h:78
static void MemoryContextStatsInternal(MemoryContext context, int level, bool print, int max_children, MemoryContextCounters *totals)
Definition: mcxt.c:473
MemoryContext CurTransactionContext
Definition: mcxt.c:49
void * palloc_extended(Size size, int flags)
Definition: mcxt.c:909
#define MCXT_ALLOC_NO_OOM
Definition: fe_memutils.h:18
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:857
Size GetMemoryChunkSpace(void *pointer)
Definition: mcxt.c:390
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
#define AssertNotInCriticalSection(context)
Definition: mcxt.c:64
NodeTag
Definition: nodes.h:26
void MemoryContextResetOnly(MemoryContext context)
Definition: mcxt.c:154
void(* free_p)(MemoryContext context, void *pointer)
Definition: memnodes.h:58
void(* delete_context)(MemoryContext context)
Definition: memnodes.h:62
MemoryContext PortalContext
Definition: mcxt.c:52
#define malloc(a)
Definition: header.h:50
char * pchomp(const char *in)
Definition: mcxt.c:1101
bool(* is_empty)(MemoryContext context)
Definition: memnodes.h:64
MemoryContext firstchild
Definition: memnodes.h:81
void pfree(void *pointer)
Definition: mcxt.c:950
#define ERROR
Definition: elog.h:43
bool MemoryContextIsEmpty(MemoryContext context)
Definition: mcxt.c:415
#define VALGRIND_MEMPOOL_CHANGE(context, optr, nptr, size)
Definition: memdebug.h:31
void MemoryContextStats(MemoryContext context)
Definition: mcxt.c:438
#define MemSetLoop(start, val, len)
Definition: c.h:925
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
void * MemoryContextAllocHuge(MemoryContext context, Size size)
Definition: mcxt.c:998
void(* stats)(MemoryContext context, int level, bool print, MemoryContextCounters *totals)
Definition: memnodes.h:65
void *(* alloc)(MemoryContext context, Size size)
Definition: memnodes.h:56
#define VALGRIND_MEMPOOL_FREE(context, addr)
Definition: memdebug.h:30
int errdetail(const char *fmt,...)
Definition: elog.c:873
MemoryContext MemoryContextCreate(NodeTag tag, Size size, MemoryContextMethods *methods, MemoryContext parent, const char *name)
Definition: mcxt.c:640
void(* reset)(MemoryContext context)
Definition: memnodes.h:61
MemoryContext prevchild
Definition: memnodes.h:82
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
volatile uint32 CritSectionCount
Definition: globals.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
#define AssertArg(condition)
Definition: c.h:677
void * MemoryContextAllocZeroAligned(MemoryContext context, Size size)
Definition: mcxt.c:779
MemoryContext TopMemoryContext
Definition: mcxt.c:43
struct MemoryContextData * MemoryContext
Definition: palloc.h:36
#define AllocSizeIsValid(size)
Definition: memutils.h:42
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:236
#define VALGRIND_DESTROY_MEMPOOL(context)
Definition: memdebug.h:25
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:878
void *(* realloc)(MemoryContext context, void *pointer, Size size)
Definition: memnodes.h:59
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:742
#define VALGRIND_CREATE_MEMPOOL(context, redzones, zeroed)
Definition: memdebug.h:24
#define MemoryContextIsValid(context)
Definition: memnodes.h:97
#define NULL
Definition: c.h:229
#define VALGRIND_MEMPOOL_ALLOC(context, addr, size)
Definition: memdebug.h:29
#define Assert(condition)
Definition: c.h:675
void MemoryContextResetChildren(MemoryContext context)
Definition: mcxt.c:176
#define MCXT_ALLOC_ZERO
Definition: fe_memutils.h:19
bool MemoryContextContains(MemoryContext context, void *pointer)
Definition: mcxt.c:567
size_t Size
Definition: c.h:356
#define MAXALIGN(LEN)
Definition: c.h:588
MemoryContext MessageContext
Definition: mcxt.c:47
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:963
const char * name
Definition: encode.c:521
#define AllocHugeSizeIsValid(size)
Definition: memutils.h:46
void * repalloc_huge(void *pointer, Size size)
Definition: mcxt.c:1031
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1064
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
struct MemoryContextCallback * next
Definition: palloc.h:51
int i
MemoryContext parent
Definition: memnodes.h:80
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:265
Size(* get_chunk_space)(MemoryContext context, void *pointer)
Definition: memnodes.h:63
#define elog
Definition: elog.h:219
MemoryContext PostmasterContext
Definition: mcxt.c:45
void(* init)(MemoryContext context)
Definition: memnodes.h:60
MemoryContext nextchild
Definition: memnodes.h:83
void MemoryContextStatsDetail(MemoryContext context, int max_children)
Definition: mcxt.c:450
static MemoryContext GetMemoryChunkContext(void *pointer)
Definition: memutils.h:107
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
NodeTag type
Definition: memnodes.h:75