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-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, 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 context creation procedure is a little bit tricky because
598  * we want to be sure that we don't leave the context tree invalid
599  * in case of failure (such as insufficient memory to allocate the
600  * context node itself). The procedure goes like this:
601  * 1. Context-type-specific routine first calls MemoryContextCreate(),
602  * passing the appropriate tag/size/methods values (the methods
603  * pointer will ordinarily point to statically allocated data).
604  * The parent and name parameters usually come from the caller.
605  * 2. MemoryContextCreate() attempts to allocate the context node,
606  * plus space for the name. If this fails we can ereport() with no
607  * damage done.
608  * 3. We fill in all of the type-independent MemoryContext fields.
609  * 4. We call the type-specific init routine (using the methods pointer).
610  * The init routine is required to make the node minimally valid
611  * with zero chance of failure --- it can't allocate more memory,
612  * for example.
613  * 5. Now we have a minimally valid node that can behave correctly
614  * when told to reset or delete itself. We link the node to its
615  * parent (if any), making the node part of the context tree.
616  * 6. We return to the context-type-specific routine, which finishes
617  * up type-specific initialization. This routine can now do things
618  * that might fail (like allocate more memory), so long as it's
619  * sure the node is left in a state that delete will handle.
620  *
621  * This protocol doesn't prevent us from leaking memory if step 6 fails
622  * during creation of a top-level context, since there's no parent link
623  * in that case. However, if you run out of memory while you're building
624  * a top-level context, you might as well go home anyway...
625  *
626  * Normally, the context node and the name are allocated from
627  * TopMemoryContext (NOT from the parent context, since the node must
628  * survive resets of its parent context!). However, this routine is itself
629  * used to create TopMemoryContext! If we see that TopMemoryContext is NULL,
630  * we assume we are creating TopMemoryContext and use malloc() to allocate
631  * the node.
632  *
633  * Note that the name field of a MemoryContext does not point to
634  * separately-allocated storage, so it should not be freed at context
635  * deletion.
636  *--------------------
637  */
640  MemoryContextMethods *methods,
641  MemoryContext parent,
642  const char *name)
643 {
644  MemoryContext node;
645  Size needed = size + strlen(name) + 1;
646 
647  /* creating new memory contexts is not allowed in a critical section */
648  Assert(CritSectionCount == 0);
649 
650  /* Get space for node and name */
651  if (TopMemoryContext != NULL)
652  {
653  /* Normal case: allocate the node in TopMemoryContext */
654  node = (MemoryContext) MemoryContextAlloc(TopMemoryContext,
655  needed);
656  }
657  else
658  {
659  /* Special case for startup: use good ol' malloc */
660  node = (MemoryContext) malloc(needed);
661  Assert(node != NULL);
662  }
663 
664  /* Initialize the node as best we can */
665  MemSet(node, 0, size);
666  node->type = tag;
667  node->methods = methods;
668  node->parent = NULL; /* for the moment */
669  node->firstchild = NULL;
670  node->prevchild = NULL;
671  node->nextchild = NULL;
672  node->isReset = true;
673  node->name = ((char *) node) + size;
674  strcpy(node->name, name);
675 
676  /* Type-specific routine finishes any other essential initialization */
677  node->methods->init(node);
678 
679  /* OK to link node to parent (if any) */
680  /* Could use MemoryContextSetParent here, but doesn't seem worthwhile */
681  if (parent)
682  {
683  node->parent = parent;
684  node->nextchild = parent->firstchild;
685  if (parent->firstchild != NULL)
686  parent->firstchild->prevchild = node;
687  parent->firstchild = node;
688  /* inherit allowInCritSection flag from parent */
689  node->allowInCritSection = parent->allowInCritSection;
690  }
691 
692  VALGRIND_CREATE_MEMPOOL(node, 0, false);
693 
694  /* Return to type-specific creation routine to finish up */
695  return node;
696 }
697 
698 /*
699  * MemoryContextAlloc
700  * Allocate space within the specified context.
701  *
702  * This could be turned into a macro, but we'd have to import
703  * nodes/memnodes.h into postgres.h which seems a bad idea.
704  */
705 void *
707 {
708  void *ret;
709 
712 
713  if (!AllocSizeIsValid(size))
714  elog(ERROR, "invalid memory alloc request size %zu", size);
715 
716  context->isReset = false;
717 
718  ret = context->methods->alloc(context, size);
719  if (ret == NULL)
720  {
721  MemoryContextStats(TopMemoryContext);
722  ereport(ERROR,
723  (errcode(ERRCODE_OUT_OF_MEMORY),
724  errmsg("out of memory"),
725  errdetail("Failed on request of size %zu.", size)));
726  }
727 
728  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
729 
730  return ret;
731 }
732 
733 /*
734  * MemoryContextAllocZero
735  * Like MemoryContextAlloc, but clears allocated memory
736  *
737  * We could just call MemoryContextAlloc then clear the memory, but this
738  * is a very common combination, so we provide the combined operation.
739  */
740 void *
742 {
743  void *ret;
744 
747 
748  if (!AllocSizeIsValid(size))
749  elog(ERROR, "invalid memory alloc request size %zu", size);
750 
751  context->isReset = false;
752 
753  ret = context->methods->alloc(context, size);
754  if (ret == NULL)
755  {
756  MemoryContextStats(TopMemoryContext);
757  ereport(ERROR,
758  (errcode(ERRCODE_OUT_OF_MEMORY),
759  errmsg("out of memory"),
760  errdetail("Failed on request of size %zu.", size)));
761  }
762 
763  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
764 
765  MemSetAligned(ret, 0, size);
766 
767  return ret;
768 }
769 
770 /*
771  * MemoryContextAllocZeroAligned
772  * MemoryContextAllocZero where length is suitable for MemSetLoop
773  *
774  * This might seem overly specialized, but it's not because newNode()
775  * is so often called with compile-time-constant sizes.
776  */
777 void *
779 {
780  void *ret;
781 
784 
785  if (!AllocSizeIsValid(size))
786  elog(ERROR, "invalid memory alloc request size %zu", size);
787 
788  context->isReset = false;
789 
790  ret = context->methods->alloc(context, size);
791  if (ret == NULL)
792  {
793  MemoryContextStats(TopMemoryContext);
794  ereport(ERROR,
795  (errcode(ERRCODE_OUT_OF_MEMORY),
796  errmsg("out of memory"),
797  errdetail("Failed on request of size %zu.", size)));
798  }
799 
800  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
801 
802  MemSetLoop(ret, 0, size);
803 
804  return ret;
805 }
806 
807 /*
808  * MemoryContextAllocExtended
809  * Allocate space within the specified context using the given flags.
810  */
811 void *
813 {
814  void *ret;
815 
818 
819  if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
820  ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
821  elog(ERROR, "invalid memory alloc request size %zu", size);
822 
823  context->isReset = false;
824 
825  ret = context->methods->alloc(context, size);
826  if (ret == NULL)
827  {
828  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
829  {
830  MemoryContextStats(TopMemoryContext);
831  ereport(ERROR,
832  (errcode(ERRCODE_OUT_OF_MEMORY),
833  errmsg("out of memory"),
834  errdetail("Failed on request of size %zu.", size)));
835  }
836  return NULL;
837  }
838 
839  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
840 
841  if ((flags & MCXT_ALLOC_ZERO) != 0)
842  MemSetAligned(ret, 0, size);
843 
844  return ret;
845 }
846 
847 void *
849 {
850  /* duplicates MemoryContextAlloc to avoid increased overhead */
851  void *ret;
852 
853  AssertArg(MemoryContextIsValid(CurrentMemoryContext));
854  AssertNotInCriticalSection(CurrentMemoryContext);
855 
856  if (!AllocSizeIsValid(size))
857  elog(ERROR, "invalid memory alloc request size %zu", size);
858 
859  CurrentMemoryContext->isReset = false;
860 
861  ret = CurrentMemoryContext->methods->alloc(CurrentMemoryContext, size);
862  if (ret == NULL)
863  {
864  MemoryContextStats(TopMemoryContext);
865  ereport(ERROR,
866  (errcode(ERRCODE_OUT_OF_MEMORY),
867  errmsg("out of memory"),
868  errdetail("Failed on request of size %zu.", size)));
869  }
870 
871  VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
872 
873  return ret;
874 }
875 
876 void *
878 {
879  /* duplicates MemoryContextAllocZero to avoid increased overhead */
880  void *ret;
881 
882  AssertArg(MemoryContextIsValid(CurrentMemoryContext));
883  AssertNotInCriticalSection(CurrentMemoryContext);
884 
885  if (!AllocSizeIsValid(size))
886  elog(ERROR, "invalid memory alloc request size %zu", size);
887 
888  CurrentMemoryContext->isReset = false;
889 
890  ret = CurrentMemoryContext->methods->alloc(CurrentMemoryContext, size);
891  if (ret == NULL)
892  {
893  MemoryContextStats(TopMemoryContext);
894  ereport(ERROR,
895  (errcode(ERRCODE_OUT_OF_MEMORY),
896  errmsg("out of memory"),
897  errdetail("Failed on request of size %zu.", size)));
898  }
899 
900  VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
901 
902  MemSetAligned(ret, 0, size);
903 
904  return ret;
905 }
906 
907 void *
908 palloc_extended(Size size, int flags)
909 {
910  /* duplicates MemoryContextAllocExtended to avoid increased overhead */
911  void *ret;
912 
913  AssertArg(MemoryContextIsValid(CurrentMemoryContext));
914  AssertNotInCriticalSection(CurrentMemoryContext);
915 
916  if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
917  ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
918  elog(ERROR, "invalid memory alloc request size %zu", size);
919 
920  CurrentMemoryContext->isReset = false;
921 
922  ret = CurrentMemoryContext->methods->alloc(CurrentMemoryContext, size);
923  if (ret == NULL)
924  {
925  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
926  {
927  MemoryContextStats(TopMemoryContext);
928  ereport(ERROR,
929  (errcode(ERRCODE_OUT_OF_MEMORY),
930  errmsg("out of memory"),
931  errdetail("Failed on request of size %zu.", size)));
932  }
933  return NULL;
934  }
935 
936  VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
937 
938  if ((flags & MCXT_ALLOC_ZERO) != 0)
939  MemSetAligned(ret, 0, size);
940 
941  return ret;
942 }
943 
944 /*
945  * pfree
946  * Release an allocated chunk.
947  */
948 void
949 pfree(void *pointer)
950 {
951  MemoryContext context = GetMemoryChunkContext(pointer);
952 
953  context->methods->free_p(context, pointer);
954  VALGRIND_MEMPOOL_FREE(context, pointer);
955 }
956 
957 /*
958  * repalloc
959  * Adjust the size of a previously allocated chunk.
960  */
961 void *
962 repalloc(void *pointer, Size size)
963 {
964  MemoryContext context = GetMemoryChunkContext(pointer);
965  void *ret;
966 
967  if (!AllocSizeIsValid(size))
968  elog(ERROR, "invalid memory alloc request size %zu", size);
969 
971 
972  /* isReset must be false already */
973  Assert(!context->isReset);
974 
975  ret = context->methods->realloc(context, pointer, size);
976  if (ret == NULL)
977  {
978  MemoryContextStats(TopMemoryContext);
979  ereport(ERROR,
980  (errcode(ERRCODE_OUT_OF_MEMORY),
981  errmsg("out of memory"),
982  errdetail("Failed on request of size %zu.", size)));
983  }
984 
985  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
986 
987  return ret;
988 }
989 
990 /*
991  * MemoryContextAllocHuge
992  * Allocate (possibly-expansive) space within the specified context.
993  *
994  * See considerations in comment at MaxAllocHugeSize.
995  */
996 void *
998 {
999  void *ret;
1000 
1001  AssertArg(MemoryContextIsValid(context));
1002  AssertNotInCriticalSection(context);
1003 
1004  if (!AllocHugeSizeIsValid(size))
1005  elog(ERROR, "invalid memory alloc request size %zu", size);
1006 
1007  context->isReset = false;
1008 
1009  ret = context->methods->alloc(context, size);
1010  if (ret == NULL)
1011  {
1012  MemoryContextStats(TopMemoryContext);
1013  ereport(ERROR,
1014  (errcode(ERRCODE_OUT_OF_MEMORY),
1015  errmsg("out of memory"),
1016  errdetail("Failed on request of size %zu.", size)));
1017  }
1018 
1019  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1020 
1021  return ret;
1022 }
1023 
1024 /*
1025  * repalloc_huge
1026  * Adjust the size of a previously allocated chunk, permitting a large
1027  * value. The previous allocation need not have been "huge".
1028  */
1029 void *
1030 repalloc_huge(void *pointer, Size size)
1031 {
1032  MemoryContext context = GetMemoryChunkContext(pointer);
1033  void *ret;
1034 
1035  if (!AllocHugeSizeIsValid(size))
1036  elog(ERROR, "invalid memory alloc request size %zu", size);
1037 
1038  AssertNotInCriticalSection(context);
1039 
1040  /* isReset must be false already */
1041  Assert(!context->isReset);
1042 
1043  ret = context->methods->realloc(context, pointer, size);
1044  if (ret == NULL)
1045  {
1046  MemoryContextStats(TopMemoryContext);
1047  ereport(ERROR,
1048  (errcode(ERRCODE_OUT_OF_MEMORY),
1049  errmsg("out of memory"),
1050  errdetail("Failed on request of size %zu.", size)));
1051  }
1052 
1053  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1054 
1055  return ret;
1056 }
1057 
1058 /*
1059  * MemoryContextStrdup
1060  * Like strdup(), but allocate from the specified context
1061  */
1062 char *
1063 MemoryContextStrdup(MemoryContext context, const char *string)
1064 {
1065  char *nstr;
1066  Size len = strlen(string) + 1;
1067 
1068  nstr = (char *) MemoryContextAlloc(context, len);
1069 
1070  memcpy(nstr, string, len);
1071 
1072  return nstr;
1073 }
1074 
1075 char *
1076 pstrdup(const char *in)
1077 {
1078  return MemoryContextStrdup(CurrentMemoryContext, in);
1079 }
1080 
1081 /*
1082  * pnstrdup
1083  * Like pstrdup(), but append null byte to a
1084  * not-necessarily-null-terminated input string.
1085  */
1086 char *
1087 pnstrdup(const char *in, Size len)
1088 {
1089  char *out;
1090 
1091  len = strnlen(in, len);
1092 
1093  out = palloc(len + 1);
1094  memcpy(out, in, len);
1095  out[len] = '\0';
1096 
1097  return out;
1098 }
1099 
1100 /*
1101  * Make copy of string with all trailing newline characters removed.
1102  */
1103 char *
1104 pchomp(const char *in)
1105 {
1106  size_t n;
1107 
1108  n = strlen(in);
1109  while (n > 0 && in[n - 1] == '\n')
1110  n--;
1111  return pnstrdup(in, n);
1112 }
#define MemSetAligned(start, val, len)
Definition: c.h:886
MemoryContextCallbackFunction func
Definition: palloc.h:49
Size(* get_chunk_space)(MemoryContext context, void *pointer)
Definition: memnodes.h:63
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1087
static void MemoryContextCallResetCallbacks(MemoryContext context)
Definition: mcxt.c:282
#define AssertState(condition)
Definition: c.h:673
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:402
MemoryContext ErrorContext
Definition: mcxt.c:44
void(* reset)(MemoryContext context)
Definition: memnodes.h:61
void * MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
Definition: mcxt.c:812
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:1076
bool allowInCritSection
Definition: memnodes.h:78
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:908
#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:853
void(* init)(MemoryContext context)
Definition: memnodes.h:60
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 *(* realloc)(MemoryContext context, void *pointer, Size size)
Definition: memnodes.h:59
MemoryContext PortalContext
Definition: mcxt.c:52
#define malloc(a)
Definition: header.h:50
char * pchomp(const char *in)
Definition: mcxt.c:1104
MemoryContext firstchild
Definition: memnodes.h:81
void pfree(void *pointer)
Definition: mcxt.c:949
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:64
#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:921
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
void * MemoryContextAllocHuge(MemoryContext context, Size size)
Definition: mcxt.c:997
#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:639
MemoryContext prevchild
Definition: memnodes.h:82
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:672
void * MemoryContextAllocZeroAligned(MemoryContext context, Size size)
Definition: mcxt.c:778
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:877
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
#define VALGRIND_CREATE_MEMPOOL(context, redzones, zeroed)
Definition: memdebug.h:24
#define MemoryContextIsValid(context)
Definition: memnodes.h:97
#define VALGRIND_MEMPOOL_ALLOC(context, addr, size)
Definition: memdebug.h:29
#define Assert(condition)
Definition: c.h:670
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:566
void(* stats)(MemoryContext context, int level, bool print, MemoryContextCounters *totals)
Definition: memnodes.h:65
size_t Size
Definition: c.h:404
#define MAXALIGN(LEN)
Definition: c.h:623
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:962
const char * name
Definition: encode.c:521
#define AllocHugeSizeIsValid(size)
Definition: memutils.h:46
void * repalloc_huge(void *pointer, Size size)
Definition: mcxt.c:1030
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1063
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
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
void(* delete_context)(MemoryContext context)
Definition: memnodes.h:62
#define elog
Definition: elog.h:219
MemoryContext PostmasterContext
Definition: mcxt.c:45
MemoryContext nextchild
Definition: memnodes.h:83
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:75