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 {
393 
394  /*
395  * Try to detect bogus pointers handed to us, poorly though we can.
396  * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
397  * allocated chunk.
398  */
399  Assert(pointer != NULL);
400  Assert(pointer == (void *) MAXALIGN(pointer));
401 
402  /*
403  * OK, it's probably safe to look at the chunk header.
404  */
405  header = (StandardChunkHeader *)
406  ((char *) pointer - STANDARDCHUNKHEADERSIZE);
407 
409 
410  return (*header->context->methods->get_chunk_space) (header->context,
411  pointer);
412 }
413 
414 /*
415  * GetMemoryChunkContext
416  * Given a currently-allocated chunk, determine the context
417  * it belongs to.
418  */
420 GetMemoryChunkContext(void *pointer)
421 {
423 
424  /*
425  * Try to detect bogus pointers handed to us, poorly though we can.
426  * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
427  * allocated chunk.
428  */
429  Assert(pointer != NULL);
430  Assert(pointer == (void *) MAXALIGN(pointer));
431 
432  /*
433  * OK, it's probably safe to look at the chunk header.
434  */
435  header = (StandardChunkHeader *)
436  ((char *) pointer - STANDARDCHUNKHEADERSIZE);
437 
439 
440  return header->context;
441 }
442 
443 /*
444  * MemoryContextGetParent
445  * Get the parent context (if any) of the specified context
446  */
449 {
451 
452  return context->parent;
453 }
454 
455 /*
456  * MemoryContextIsEmpty
457  * Is a memory context empty of any allocated space?
458  */
459 bool
461 {
463 
464  /*
465  * For now, we consider a memory context nonempty if it has any children;
466  * perhaps this should be changed later.
467  */
468  if (context->firstchild != NULL)
469  return false;
470  /* Otherwise use the type-specific inquiry */
471  return (*context->methods->is_empty) (context);
472 }
473 
474 /*
475  * MemoryContextStats
476  * Print statistics about the named context and all its descendants.
477  *
478  * This is just a debugging utility, so it's not very fancy. However, we do
479  * make some effort to summarize when the output would otherwise be very long.
480  * The statistics are sent to stderr.
481  */
482 void
484 {
485  /* A hard-wired limit on the number of children is usually good enough */
486  MemoryContextStatsDetail(context, 100);
487 }
488 
489 /*
490  * MemoryContextStatsDetail
491  *
492  * Entry point for use if you want to vary the number of child contexts shown.
493  */
494 void
495 MemoryContextStatsDetail(MemoryContext context, int max_children)
496 {
497  MemoryContextCounters grand_totals;
498 
499  memset(&grand_totals, 0, sizeof(grand_totals));
500 
501  MemoryContextStatsInternal(context, 0, true, max_children, &grand_totals);
502 
503  fprintf(stderr,
504  "Grand total: %zu bytes in %zd blocks; %zu free (%zd chunks); %zu used\n",
505  grand_totals.totalspace, grand_totals.nblocks,
506  grand_totals.freespace, grand_totals.freechunks,
507  grand_totals.totalspace - grand_totals.freespace);
508 }
509 
510 /*
511  * MemoryContextStatsInternal
512  * One recursion level for MemoryContextStats
513  *
514  * Print this context if print is true, but in any case accumulate counts into
515  * *totals (if given).
516  */
517 static void
519  bool print, int max_children,
520  MemoryContextCounters *totals)
521 {
522  MemoryContextCounters local_totals;
523  MemoryContext child;
524  int ichild;
525 
527 
528  /* Examine the context itself */
529  (*context->methods->stats) (context, level, print, totals);
530 
531  /*
532  * Examine children. If there are more than max_children of them, we do
533  * not print the rest explicitly, but just summarize them.
534  */
535  memset(&local_totals, 0, sizeof(local_totals));
536 
537  for (child = context->firstchild, ichild = 0;
538  child != NULL;
539  child = child->nextchild, ichild++)
540  {
541  if (ichild < max_children)
542  MemoryContextStatsInternal(child, level + 1,
543  print, max_children,
544  totals);
545  else
546  MemoryContextStatsInternal(child, level + 1,
547  false, max_children,
548  &local_totals);
549  }
550 
551  /* Deal with excess children */
552  if (ichild > max_children)
553  {
554  if (print)
555  {
556  int i;
557 
558  for (i = 0; i <= level; i++)
559  fprintf(stderr, " ");
560  fprintf(stderr,
561  "%d more child contexts containing %zu total in %zd blocks; %zu free (%zd chunks); %zu used\n",
562  ichild - max_children,
563  local_totals.totalspace,
564  local_totals.nblocks,
565  local_totals.freespace,
566  local_totals.freechunks,
567  local_totals.totalspace - local_totals.freespace);
568  }
569 
570  if (totals)
571  {
572  totals->nblocks += local_totals.nblocks;
573  totals->freechunks += local_totals.freechunks;
574  totals->totalspace += local_totals.totalspace;
575  totals->freespace += local_totals.freespace;
576  }
577  }
578 }
579 
580 /*
581  * MemoryContextCheck
582  * Check all chunks in the named context.
583  *
584  * This is just a debugging utility, so it's not fancy.
585  */
586 #ifdef MEMORY_CONTEXT_CHECKING
587 void
588 MemoryContextCheck(MemoryContext context)
589 {
590  MemoryContext child;
591 
593 
594  (*context->methods->check) (context);
595  for (child = context->firstchild; child != NULL; child = child->nextchild)
596  MemoryContextCheck(child);
597 }
598 #endif
599 
600 /*
601  * MemoryContextContains
602  * Detect whether an allocated chunk of memory belongs to a given
603  * context or not.
604  *
605  * Caution: this test is reliable as long as 'pointer' does point to
606  * a chunk of memory allocated from *some* context. If 'pointer' points
607  * at memory obtained in some other way, there is a small chance of a
608  * false-positive result, since the bits right before it might look like
609  * a valid chunk header by chance.
610  */
611 bool
612 MemoryContextContains(MemoryContext context, void *pointer)
613 {
615 
616  /*
617  * Try to detect bogus pointers handed to us, poorly though we can.
618  * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
619  * allocated chunk.
620  */
621  if (pointer == NULL || pointer != (void *) MAXALIGN(pointer))
622  return false;
623 
624  /*
625  * OK, it's probably safe to look at the chunk header.
626  */
627  header = (StandardChunkHeader *)
628  ((char *) pointer - STANDARDCHUNKHEADERSIZE);
629 
630  return header->context == context;
631 }
632 
633 /*--------------------
634  * MemoryContextCreate
635  * Context-type-independent part of context creation.
636  *
637  * This is only intended to be called by context-type-specific
638  * context creation routines, not by the unwashed masses.
639  *
640  * The context creation procedure is a little bit tricky because
641  * we want to be sure that we don't leave the context tree invalid
642  * in case of failure (such as insufficient memory to allocate the
643  * context node itself). The procedure goes like this:
644  * 1. Context-type-specific routine first calls MemoryContextCreate(),
645  * passing the appropriate tag/size/methods values (the methods
646  * pointer will ordinarily point to statically allocated data).
647  * The parent and name parameters usually come from the caller.
648  * 2. MemoryContextCreate() attempts to allocate the context node,
649  * plus space for the name. If this fails we can ereport() with no
650  * damage done.
651  * 3. We fill in all of the type-independent MemoryContext fields.
652  * 4. We call the type-specific init routine (using the methods pointer).
653  * The init routine is required to make the node minimally valid
654  * with zero chance of failure --- it can't allocate more memory,
655  * for example.
656  * 5. Now we have a minimally valid node that can behave correctly
657  * when told to reset or delete itself. We link the node to its
658  * parent (if any), making the node part of the context tree.
659  * 6. We return to the context-type-specific routine, which finishes
660  * up type-specific initialization. This routine can now do things
661  * that might fail (like allocate more memory), so long as it's
662  * sure the node is left in a state that delete will handle.
663  *
664  * This protocol doesn't prevent us from leaking memory if step 6 fails
665  * during creation of a top-level context, since there's no parent link
666  * in that case. However, if you run out of memory while you're building
667  * a top-level context, you might as well go home anyway...
668  *
669  * Normally, the context node and the name are allocated from
670  * TopMemoryContext (NOT from the parent context, since the node must
671  * survive resets of its parent context!). However, this routine is itself
672  * used to create TopMemoryContext! If we see that TopMemoryContext is NULL,
673  * we assume we are creating TopMemoryContext and use malloc() to allocate
674  * the node.
675  *
676  * Note that the name field of a MemoryContext does not point to
677  * separately-allocated storage, so it should not be freed at context
678  * deletion.
679  *--------------------
680  */
683  MemoryContextMethods *methods,
684  MemoryContext parent,
685  const char *name)
686 {
687  MemoryContext node;
688  Size needed = size + strlen(name) + 1;
689 
690  /* creating new memory contexts is not allowed in a critical section */
691  Assert(CritSectionCount == 0);
692 
693  /* Get space for node and name */
694  if (TopMemoryContext != NULL)
695  {
696  /* Normal case: allocate the node in TopMemoryContext */
697  node = (MemoryContext) MemoryContextAlloc(TopMemoryContext,
698  needed);
699  }
700  else
701  {
702  /* Special case for startup: use good ol' malloc */
703  node = (MemoryContext) malloc(needed);
704  Assert(node != NULL);
705  }
706 
707  /* Initialize the node as best we can */
708  MemSet(node, 0, size);
709  node->type = tag;
710  node->methods = methods;
711  node->parent = NULL; /* for the moment */
712  node->firstchild = NULL;
713  node->prevchild = NULL;
714  node->nextchild = NULL;
715  node->isReset = true;
716  node->name = ((char *) node) + size;
717  strcpy(node->name, name);
718 
719  /* Type-specific routine finishes any other essential initialization */
720  (*node->methods->init) (node);
721 
722  /* OK to link node to parent (if any) */
723  /* Could use MemoryContextSetParent here, but doesn't seem worthwhile */
724  if (parent)
725  {
726  node->parent = parent;
727  node->nextchild = parent->firstchild;
728  if (parent->firstchild != NULL)
729  parent->firstchild->prevchild = node;
730  parent->firstchild = node;
731  /* inherit allowInCritSection flag from parent */
732  node->allowInCritSection = parent->allowInCritSection;
733  }
734 
735  VALGRIND_CREATE_MEMPOOL(node, 0, false);
736 
737  /* Return to type-specific creation routine to finish up */
738  return node;
739 }
740 
741 /*
742  * MemoryContextAlloc
743  * Allocate space within the specified context.
744  *
745  * This could be turned into a macro, but we'd have to import
746  * nodes/memnodes.h into postgres.h which seems a bad idea.
747  */
748 void *
750 {
751  void *ret;
752 
755 
756  if (!AllocSizeIsValid(size))
757  elog(ERROR, "invalid memory alloc request size %zu", size);
758 
759  context->isReset = false;
760 
761  ret = (*context->methods->alloc) (context, size);
762  if (ret == NULL)
763  {
764  MemoryContextStats(TopMemoryContext);
765  ereport(ERROR,
766  (errcode(ERRCODE_OUT_OF_MEMORY),
767  errmsg("out of memory"),
768  errdetail("Failed on request of size %zu.", size)));
769  }
770 
771  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
772 
773  return ret;
774 }
775 
776 /*
777  * MemoryContextAllocZero
778  * Like MemoryContextAlloc, but clears allocated memory
779  *
780  * We could just call MemoryContextAlloc then clear the memory, but this
781  * is a very common combination, so we provide the combined operation.
782  */
783 void *
785 {
786  void *ret;
787 
790 
791  if (!AllocSizeIsValid(size))
792  elog(ERROR, "invalid memory alloc request size %zu", size);
793 
794  context->isReset = false;
795 
796  ret = (*context->methods->alloc) (context, size);
797  if (ret == NULL)
798  {
799  MemoryContextStats(TopMemoryContext);
800  ereport(ERROR,
801  (errcode(ERRCODE_OUT_OF_MEMORY),
802  errmsg("out of memory"),
803  errdetail("Failed on request of size %zu.", size)));
804  }
805 
806  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
807 
808  MemSetAligned(ret, 0, size);
809 
810  return ret;
811 }
812 
813 /*
814  * MemoryContextAllocZeroAligned
815  * MemoryContextAllocZero where length is suitable for MemSetLoop
816  *
817  * This might seem overly specialized, but it's not because newNode()
818  * is so often called with compile-time-constant sizes.
819  */
820 void *
822 {
823  void *ret;
824 
827 
828  if (!AllocSizeIsValid(size))
829  elog(ERROR, "invalid memory alloc request size %zu", size);
830 
831  context->isReset = false;
832 
833  ret = (*context->methods->alloc) (context, size);
834  if (ret == NULL)
835  {
836  MemoryContextStats(TopMemoryContext);
837  ereport(ERROR,
838  (errcode(ERRCODE_OUT_OF_MEMORY),
839  errmsg("out of memory"),
840  errdetail("Failed on request of size %zu.", size)));
841  }
842 
843  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
844 
845  MemSetLoop(ret, 0, size);
846 
847  return ret;
848 }
849 
850 /*
851  * MemoryContextAllocExtended
852  * Allocate space within the specified context using the given flags.
853  */
854 void *
856 {
857  void *ret;
858 
861 
862  if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
863  ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
864  elog(ERROR, "invalid memory alloc request size %zu", size);
865 
866  context->isReset = false;
867 
868  ret = (*context->methods->alloc) (context, size);
869  if (ret == NULL)
870  {
871  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
872  {
873  MemoryContextStats(TopMemoryContext);
874  ereport(ERROR,
875  (errcode(ERRCODE_OUT_OF_MEMORY),
876  errmsg("out of memory"),
877  errdetail("Failed on request of size %zu.", size)));
878  }
879  return NULL;
880  }
881 
882  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
883 
884  if ((flags & MCXT_ALLOC_ZERO) != 0)
885  MemSetAligned(ret, 0, size);
886 
887  return ret;
888 }
889 
890 void *
892 {
893  /* duplicates MemoryContextAlloc to avoid increased overhead */
894  void *ret;
895 
896  AssertArg(MemoryContextIsValid(CurrentMemoryContext));
897  AssertNotInCriticalSection(CurrentMemoryContext);
898 
899  if (!AllocSizeIsValid(size))
900  elog(ERROR, "invalid memory alloc request size %zu", size);
901 
902  CurrentMemoryContext->isReset = false;
903 
904  ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
905  if (ret == NULL)
906  {
907  MemoryContextStats(TopMemoryContext);
908  ereport(ERROR,
909  (errcode(ERRCODE_OUT_OF_MEMORY),
910  errmsg("out of memory"),
911  errdetail("Failed on request of size %zu.", size)));
912  }
913 
914  VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
915 
916  return ret;
917 }
918 
919 void *
921 {
922  /* duplicates MemoryContextAllocZero to avoid increased overhead */
923  void *ret;
924 
925  AssertArg(MemoryContextIsValid(CurrentMemoryContext));
926  AssertNotInCriticalSection(CurrentMemoryContext);
927 
928  if (!AllocSizeIsValid(size))
929  elog(ERROR, "invalid memory alloc request size %zu", size);
930 
931  CurrentMemoryContext->isReset = false;
932 
933  ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
934  if (ret == NULL)
935  {
936  MemoryContextStats(TopMemoryContext);
937  ereport(ERROR,
938  (errcode(ERRCODE_OUT_OF_MEMORY),
939  errmsg("out of memory"),
940  errdetail("Failed on request of size %zu.", size)));
941  }
942 
943  VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
944 
945  MemSetAligned(ret, 0, size);
946 
947  return ret;
948 }
949 
950 void *
951 palloc_extended(Size size, int flags)
952 {
953  /* duplicates MemoryContextAllocExtended to avoid increased overhead */
954  void *ret;
955 
956  AssertArg(MemoryContextIsValid(CurrentMemoryContext));
957  AssertNotInCriticalSection(CurrentMemoryContext);
958 
959  if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
960  ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
961  elog(ERROR, "invalid memory alloc request size %zu", size);
962 
963  CurrentMemoryContext->isReset = false;
964 
965  ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
966  if (ret == NULL)
967  {
968  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
969  {
970  MemoryContextStats(TopMemoryContext);
971  ereport(ERROR,
972  (errcode(ERRCODE_OUT_OF_MEMORY),
973  errmsg("out of memory"),
974  errdetail("Failed on request of size %zu.", size)));
975  }
976  return NULL;
977  }
978 
979  VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
980 
981  if ((flags & MCXT_ALLOC_ZERO) != 0)
982  MemSetAligned(ret, 0, size);
983 
984  return ret;
985 }
986 
987 /*
988  * pfree
989  * Release an allocated chunk.
990  */
991 void
992 pfree(void *pointer)
993 {
994  MemoryContext context;
995 
996  /*
997  * Try to detect bogus pointers handed to us, poorly though we can.
998  * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
999  * allocated chunk.
1000  */
1001  Assert(pointer != NULL);
1002  Assert(pointer == (void *) MAXALIGN(pointer));
1003 
1004  /*
1005  * OK, it's probably safe to look at the chunk header.
1006  */
1007  context = ((StandardChunkHeader *)
1008  ((char *) pointer - STANDARDCHUNKHEADERSIZE))->context;
1009 
1010  AssertArg(MemoryContextIsValid(context));
1011 
1012  (*context->methods->free_p) (context, pointer);
1013  VALGRIND_MEMPOOL_FREE(context, pointer);
1014 }
1015 
1016 /*
1017  * repalloc
1018  * Adjust the size of a previously allocated chunk.
1019  */
1020 void *
1021 repalloc(void *pointer, Size size)
1022 {
1023  MemoryContext context;
1024  void *ret;
1025 
1026  if (!AllocSizeIsValid(size))
1027  elog(ERROR, "invalid memory alloc request size %zu", size);
1028 
1029  /*
1030  * Try to detect bogus pointers handed to us, poorly though we can.
1031  * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
1032  * allocated chunk.
1033  */
1034  Assert(pointer != NULL);
1035  Assert(pointer == (void *) MAXALIGN(pointer));
1036 
1037  /*
1038  * OK, it's probably safe to look at the chunk header.
1039  */
1040  context = ((StandardChunkHeader *)
1041  ((char *) pointer - STANDARDCHUNKHEADERSIZE))->context;
1042 
1043  AssertArg(MemoryContextIsValid(context));
1044  AssertNotInCriticalSection(context);
1045 
1046  /* isReset must be false already */
1047  Assert(!context->isReset);
1048 
1049  ret = (*context->methods->realloc) (context, pointer, size);
1050  if (ret == NULL)
1051  {
1052  MemoryContextStats(TopMemoryContext);
1053  ereport(ERROR,
1054  (errcode(ERRCODE_OUT_OF_MEMORY),
1055  errmsg("out of memory"),
1056  errdetail("Failed on request of size %zu.", size)));
1057  }
1058 
1059  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1060 
1061  return ret;
1062 }
1063 
1064 /*
1065  * MemoryContextAllocHuge
1066  * Allocate (possibly-expansive) space within the specified context.
1067  *
1068  * See considerations in comment at MaxAllocHugeSize.
1069  */
1070 void *
1072 {
1073  void *ret;
1074 
1075  AssertArg(MemoryContextIsValid(context));
1076  AssertNotInCriticalSection(context);
1077 
1078  if (!AllocHugeSizeIsValid(size))
1079  elog(ERROR, "invalid memory alloc request size %zu", size);
1080 
1081  context->isReset = false;
1082 
1083  ret = (*context->methods->alloc) (context, size);
1084  if (ret == NULL)
1085  {
1086  MemoryContextStats(TopMemoryContext);
1087  ereport(ERROR,
1088  (errcode(ERRCODE_OUT_OF_MEMORY),
1089  errmsg("out of memory"),
1090  errdetail("Failed on request of size %zu.", size)));
1091  }
1092 
1093  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1094 
1095  return ret;
1096 }
1097 
1098 /*
1099  * repalloc_huge
1100  * Adjust the size of a previously allocated chunk, permitting a large
1101  * value. The previous allocation need not have been "huge".
1102  */
1103 void *
1104 repalloc_huge(void *pointer, Size size)
1105 {
1106  MemoryContext context;
1107  void *ret;
1108 
1109  if (!AllocHugeSizeIsValid(size))
1110  elog(ERROR, "invalid memory alloc request size %zu", size);
1111 
1112  /*
1113  * Try to detect bogus pointers handed to us, poorly though we can.
1114  * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
1115  * allocated chunk.
1116  */
1117  Assert(pointer != NULL);
1118  Assert(pointer == (void *) MAXALIGN(pointer));
1119 
1120  /*
1121  * OK, it's probably safe to look at the chunk header.
1122  */
1123  context = ((StandardChunkHeader *)
1124  ((char *) pointer - STANDARDCHUNKHEADERSIZE))->context;
1125 
1126  AssertArg(MemoryContextIsValid(context));
1127  AssertNotInCriticalSection(context);
1128 
1129  /* isReset must be false already */
1130  Assert(!context->isReset);
1131 
1132  ret = (*context->methods->realloc) (context, pointer, size);
1133  if (ret == NULL)
1134  {
1135  MemoryContextStats(TopMemoryContext);
1136  ereport(ERROR,
1137  (errcode(ERRCODE_OUT_OF_MEMORY),
1138  errmsg("out of memory"),
1139  errdetail("Failed on request of size %zu.", size)));
1140  }
1141 
1142  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1143 
1144  return ret;
1145 }
1146 
1147 /*
1148  * MemoryContextStrdup
1149  * Like strdup(), but allocate from the specified context
1150  */
1151 char *
1152 MemoryContextStrdup(MemoryContext context, const char *string)
1153 {
1154  char *nstr;
1155  Size len = strlen(string) + 1;
1156 
1157  nstr = (char *) MemoryContextAlloc(context, len);
1158 
1159  memcpy(nstr, string, len);
1160 
1161  return nstr;
1162 }
1163 
1164 char *
1165 pstrdup(const char *in)
1166 {
1167  return MemoryContextStrdup(CurrentMemoryContext, in);
1168 }
1169 
1170 /*
1171  * pnstrdup
1172  * Like pstrdup(), but append null byte to a
1173  * not-necessarily-null-terminated input string.
1174  */
1175 char *
1176 pnstrdup(const char *in, Size len)
1177 {
1178  char *out = palloc(len + 1);
1179 
1180  memcpy(out, in, len);
1181  out[len] = '\0';
1182  return out;
1183 }
#define MemSetAligned(start, val, len)
Definition: c.h:886
MemoryContextCallbackFunction func
Definition: palloc.h:49
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1176
static void MemoryContextCallResetCallbacks(MemoryContext context)
Definition: mcxt.c:282
#define AssertState(condition)
Definition: c.h:674
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:448
MemoryContext ErrorContext
Definition: mcxt.c:44
void * MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
Definition: mcxt.c:855
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:1165
bool allowInCritSection
Definition: memnodes.h:78
static void MemoryContextStatsInternal(MemoryContext context, int level, bool print, int max_children, MemoryContextCounters *totals)
Definition: mcxt.c:518
MemoryContext CurTransactionContext
Definition: mcxt.c:49
void * palloc_extended(Size size, int flags)
Definition: mcxt.c:951
#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
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:45
bool(* is_empty)(MemoryContext context)
Definition: memnodes.h:64
MemoryContext firstchild
Definition: memnodes.h:81
void pfree(void *pointer)
Definition: mcxt.c:992
#define ERROR
Definition: elog.h:43
bool MemoryContextIsEmpty(MemoryContext context)
Definition: mcxt.c:460
#define VALGRIND_MEMPOOL_CHANGE(context, optr, nptr, size)
Definition: memdebug.h:31
void MemoryContextStats(MemoryContext context)
Definition: mcxt.c:483
#define MemSetLoop(start, val, len)
Definition: c.h:921
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:145
void * MemoryContextAllocHuge(MemoryContext context, Size size)
Definition: mcxt.c:1071
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:682
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:36
#define ereport(elevel, rest)
Definition: elog.h:122
#define AssertArg(condition)
Definition: c.h:673
void * MemoryContextAllocZeroAligned(MemoryContext context, Size size)
Definition: mcxt.c:821
MemoryContext TopMemoryContext
Definition: mcxt.c:43
struct MemoryContextData * MemoryContext
Definition: palloc.h:36
#define AllocSizeIsValid(size)
Definition: memutils.h:42
MemoryContext GetMemoryChunkContext(void *pointer)
Definition: mcxt.c:420
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:440
void * palloc0(Size size)
Definition: mcxt.c:920
void *(* realloc)(MemoryContext context, void *pointer, Size size)
Definition: memnodes.h:59
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:784
#define VALGRIND_CREATE_MEMPOOL(context, redzones, zeroed)
Definition: memdebug.h:24
#define MemoryContextIsValid(context)
Definition: memnodes.h:97
#define NULL
Definition: c.h:226
#define VALGRIND_MEMPOOL_ALLOC(context, addr, size)
Definition: memdebug.h:29
#define Assert(condition)
Definition: c.h:671
void MemoryContextResetChildren(MemoryContext context)
Definition: mcxt.c:176
#define MCXT_ALLOC_ZERO
Definition: fe_memutils.h:19
#define STANDARDCHUNKHEADERSIZE
Definition: memutils.h:67
bool MemoryContextContains(MemoryContext context, void *pointer)
Definition: mcxt.c:612
MemoryContext context
Definition: memutils.h:59
size_t Size
Definition: c.h:353
#define MAXALIGN(LEN)
Definition: c.h:584
MemoryContext MessageContext
Definition: mcxt.c:47
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:205
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1021
const char * name
Definition: encode.c:521
#define AllocHugeSizeIsValid(size)
Definition: memutils.h:46
void * repalloc_huge(void *pointer, Size size)
Definition: mcxt.c:1104
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1152
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
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:495
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
NodeTag type
Definition: memnodes.h:75