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