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-2022, 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 "storage/proc.h"
27 #include "storage/procarray.h"
28 #include "storage/procsignal.h"
29 #include "utils/fmgrprotos.h"
30 #include "utils/memdebug.h"
31 #include "utils/memutils.h"
33 
34 
35 /*****************************************************************************
36  * GLOBAL MEMORY *
37  *****************************************************************************/
38 
40  /* aset.c */
42  [MCTX_ASET_ID].free_p = AllocSetFree,
43  [MCTX_ASET_ID].realloc = AllocSetRealloc,
44  [MCTX_ASET_ID].reset = AllocSetReset,
45  [MCTX_ASET_ID].delete_context = AllocSetDelete,
46  [MCTX_ASET_ID].get_chunk_context = AllocSetGetChunkContext,
47  [MCTX_ASET_ID].get_chunk_space = AllocSetGetChunkSpace,
48  [MCTX_ASET_ID].is_empty = AllocSetIsEmpty,
49  [MCTX_ASET_ID].stats = AllocSetStats,
50 #ifdef MEMORY_CONTEXT_CHECKING
51  [MCTX_ASET_ID].check = AllocSetCheck,
52 #endif
53 
54  /* generation.c */
59  [MCTX_GENERATION_ID].delete_context = GenerationDelete,
60  [MCTX_GENERATION_ID].get_chunk_context = GenerationGetChunkContext,
61  [MCTX_GENERATION_ID].get_chunk_space = GenerationGetChunkSpace,
64 #ifdef MEMORY_CONTEXT_CHECKING
65  [MCTX_GENERATION_ID].check = GenerationCheck,
66 #endif
67 
68  /* slab.c */
69  [MCTX_SLAB_ID].alloc = SlabAlloc,
70  [MCTX_SLAB_ID].free_p = SlabFree,
71  [MCTX_SLAB_ID].realloc = SlabRealloc,
72  [MCTX_SLAB_ID].reset = SlabReset,
73  [MCTX_SLAB_ID].delete_context = SlabDelete,
74  [MCTX_SLAB_ID].get_chunk_context = SlabGetChunkContext,
75  [MCTX_SLAB_ID].get_chunk_space = SlabGetChunkSpace,
76  [MCTX_SLAB_ID].is_empty = SlabIsEmpty,
77  [MCTX_SLAB_ID].stats = SlabStats
78 #ifdef MEMORY_CONTEXT_CHECKING
79  ,[MCTX_SLAB_ID].check = SlabCheck
80 #endif
81 };
82 
83 /*
84  * CurrentMemoryContext
85  * Default memory context for allocations.
86  */
88 
89 /*
90  * Standard top-level contexts. For a description of the purpose of each
91  * of these contexts, refer to src/backend/utils/mmgr/README
92  */
100 
101 /* This is a transient link to the active portal's memory context: */
103 
105 static void MemoryContextStatsInternal(MemoryContext context, int level,
106  bool print, int max_children,
107  MemoryContextCounters *totals,
108  bool print_to_stderr);
109 static void MemoryContextStatsPrint(MemoryContext context, void *passthru,
110  const char *stats_string,
111  bool print_to_stderr);
112 
113 /*
114  * You should not do memory allocations within a critical section, because
115  * an out-of-memory error will be escalated to a PANIC. To enforce that
116  * rule, the allocation functions Assert that.
117  */
118 #define AssertNotInCriticalSection(context) \
119  Assert(CritSectionCount == 0 || (context)->allowInCritSection)
120 
121 /*
122  * Call the given function in the MemoryContextMethods for the memory context
123  * type that 'pointer' belongs to.
124  */
125 #define MCXT_METHOD(pointer, method) \
126  mcxt_methods[GetMemoryChunkMethodID(pointer)].method
127 
128 
129 /*****************************************************************************
130  * EXPORTED ROUTINES *
131  *****************************************************************************/
132 
133 
134 /*
135  * MemoryContextInit
136  * Start up the memory-context subsystem.
137  *
138  * This must be called before creating contexts or allocating memory in
139  * contexts. TopMemoryContext and ErrorContext are initialized here;
140  * other contexts must be created afterwards.
141  *
142  * In normal multi-backend operation, this is called once during
143  * postmaster startup, and not at all by individual backend startup
144  * (since the backends inherit an already-initialized context subsystem
145  * by virtue of being forked off the postmaster). But in an EXEC_BACKEND
146  * build, each process must do this for itself.
147  *
148  * In a standalone backend this must be called during backend startup.
149  */
150 void
152 {
153  AssertState(TopMemoryContext == NULL);
154 
155  /*
156  * First, initialize TopMemoryContext, which is the parent of all others.
157  */
159  "TopMemoryContext",
161 
162  /*
163  * Not having any other place to point CurrentMemoryContext, make it point
164  * to TopMemoryContext. Caller should change this soon!
165  */
167 
168  /*
169  * Initialize ErrorContext as an AllocSetContext with slow growth rate ---
170  * we don't really expect much to be allocated in it. More to the point,
171  * require it to contain at least 8K at all times. This is the only case
172  * where retained memory in a context is *essential* --- we want to be
173  * sure ErrorContext still has some memory even if we've run out
174  * elsewhere! Also, allow allocations in ErrorContext within a critical
175  * section. Otherwise a PANIC will cause an assertion failure in the error
176  * reporting code, before printing out the real cause of the failure.
177  *
178  * This should be the last step in this function, as elog.c assumes memory
179  * management works once ErrorContext is non-null.
180  */
182  "ErrorContext",
183  8 * 1024,
184  8 * 1024,
185  8 * 1024);
187 }
188 
189 /*
190  * MemoryContextReset
191  * Release all space allocated within a context and delete all its
192  * descendant contexts (but not the named context itself).
193  */
194 void
196 {
198 
199  /* save a function call in common case where there are no children */
200  if (context->firstchild != NULL)
202 
203  /* save a function call if no pallocs since startup or last reset */
204  if (!context->isReset)
205  MemoryContextResetOnly(context);
206 }
207 
208 /*
209  * MemoryContextResetOnly
210  * Release all space allocated within a context.
211  * Nothing is done to the context's descendant contexts.
212  */
213 void
215 {
217 
218  /* Nothing to do if no pallocs since startup or last reset */
219  if (!context->isReset)
220  {
222 
223  /*
224  * If context->ident points into the context's memory, it will become
225  * a dangling pointer. We could prevent that by setting it to NULL
226  * here, but that would break valid coding patterns that keep the
227  * ident elsewhere, e.g. in a parent context. Another idea is to use
228  * MemoryContextContains(), but we don't require ident strings to be
229  * in separately-palloc'd chunks, so that risks false positives. So
230  * for now we assume the programmer got it right.
231  */
232 
233  context->methods->reset(context);
234  context->isReset = true;
235  VALGRIND_DESTROY_MEMPOOL(context);
236  VALGRIND_CREATE_MEMPOOL(context, 0, false);
237  }
238 }
239 
240 /*
241  * MemoryContextResetChildren
242  * Release all space allocated within a context's descendants,
243  * but don't delete the contexts themselves. The named context
244  * itself is not touched.
245  */
246 void
248 {
249  MemoryContext child;
250 
252 
253  for (child = context->firstchild; child != NULL; child = child->nextchild)
254  {
256  MemoryContextResetOnly(child);
257  }
258 }
259 
260 /*
261  * MemoryContextDelete
262  * Delete a context and its descendants, and release all space
263  * allocated therein.
264  *
265  * The type-specific delete routine removes all storage for the context,
266  * but we have to recurse to handle the children.
267  * We must also delink the context from its parent, if it has one.
268  */
269 void
271 {
273  /* We had better not be deleting TopMemoryContext ... */
274  Assert(context != TopMemoryContext);
275  /* And not CurrentMemoryContext, either */
276  Assert(context != CurrentMemoryContext);
277 
278  /* save a function call in common case where there are no children */
279  if (context->firstchild != NULL)
281 
282  /*
283  * It's not entirely clear whether 'tis better to do this before or after
284  * delinking the context; but an error in a callback will likely result in
285  * leaking the whole context (if it's not a root context) if we do it
286  * after, so let's do it before.
287  */
289 
290  /*
291  * We delink the context from its parent before deleting it, so that if
292  * there's an error we won't have deleted/busted contexts still attached
293  * to the context tree. Better a leak than a crash.
294  */
295  MemoryContextSetParent(context, NULL);
296 
297  /*
298  * Also reset the context's ident pointer, in case it points into the
299  * context. This would only matter if someone tries to get stats on the
300  * (already unlinked) context, which is unlikely, but let's be safe.
301  */
302  context->ident = NULL;
303 
304  context->methods->delete_context(context);
305 
306  VALGRIND_DESTROY_MEMPOOL(context);
307 }
308 
309 /*
310  * MemoryContextDeleteChildren
311  * Delete all the descendants of the named context and release all
312  * space allocated therein. The named context itself is not touched.
313  */
314 void
316 {
318 
319  /*
320  * MemoryContextDelete will delink the child from me, so just iterate as
321  * long as there is a child.
322  */
323  while (context->firstchild != NULL)
325 }
326 
327 /*
328  * MemoryContextRegisterResetCallback
329  * Register a function to be called before next context reset/delete.
330  * Such callbacks will be called in reverse order of registration.
331  *
332  * The caller is responsible for allocating a MemoryContextCallback struct
333  * to hold the info about this callback request, and for filling in the
334  * "func" and "arg" fields in the struct to show what function to call with
335  * what argument. Typically the callback struct should be allocated within
336  * the specified context, since that means it will automatically be freed
337  * when no longer needed.
338  *
339  * There is no API for deregistering a callback once registered. If you
340  * want it to not do anything anymore, adjust the state pointed to by its
341  * "arg" to indicate that.
342  */
343 void
346 {
348 
349  /* Push onto head so this will be called before older registrants. */
350  cb->next = context->reset_cbs;
351  context->reset_cbs = cb;
352  /* Mark the context as non-reset (it probably is already). */
353  context->isReset = false;
354 }
355 
356 /*
357  * MemoryContextCallResetCallbacks
358  * Internal function to call all registered callbacks for context.
359  */
360 static void
362 {
364 
365  /*
366  * We pop each callback from the list before calling. That way, if an
367  * error occurs inside the callback, we won't try to call it a second time
368  * in the likely event that we reset or delete the context later.
369  */
370  while ((cb = context->reset_cbs) != NULL)
371  {
372  context->reset_cbs = cb->next;
373  cb->func(cb->arg);
374  }
375 }
376 
377 /*
378  * MemoryContextSetIdentifier
379  * Set the identifier string for a memory context.
380  *
381  * An identifier can be provided to help distinguish among different contexts
382  * of the same kind in memory context stats dumps. The identifier string
383  * must live at least as long as the context it is for; typically it is
384  * allocated inside that context, so that it automatically goes away on
385  * context deletion. Pass id = NULL to forget any old identifier.
386  */
387 void
389 {
391  context->ident = id;
392 }
393 
394 /*
395  * MemoryContextSetParent
396  * Change a context to belong to a new parent (or no parent).
397  *
398  * We provide this as an API function because it is sometimes useful to
399  * change a context's lifespan after creation. For example, a context
400  * might be created underneath a transient context, filled with data,
401  * and then reparented underneath CacheMemoryContext to make it long-lived.
402  * In this way no special effort is needed to get rid of the context in case
403  * a failure occurs before its contents are completely set up.
404  *
405  * Callers often assume that this function cannot fail, so don't put any
406  * elog(ERROR) calls in it.
407  *
408  * A possible caller error is to reparent a context under itself, creating
409  * a loop in the context graph. We assert here that context != new_parent,
410  * but checking for multi-level loops seems more trouble than it's worth.
411  */
412 void
414 {
416  AssertArg(context != new_parent);
417 
418  /* Fast path if it's got correct parent already */
419  if (new_parent == context->parent)
420  return;
421 
422  /* Delink from existing parent, if any */
423  if (context->parent)
424  {
425  MemoryContext parent = context->parent;
426 
427  if (context->prevchild != NULL)
428  context->prevchild->nextchild = context->nextchild;
429  else
430  {
431  Assert(parent->firstchild == context);
432  parent->firstchild = context->nextchild;
433  }
434 
435  if (context->nextchild != NULL)
436  context->nextchild->prevchild = context->prevchild;
437  }
438 
439  /* And relink */
440  if (new_parent)
441  {
442  AssertArg(MemoryContextIsValid(new_parent));
443  context->parent = new_parent;
444  context->prevchild = NULL;
445  context->nextchild = new_parent->firstchild;
446  if (new_parent->firstchild != NULL)
447  new_parent->firstchild->prevchild = context;
448  new_parent->firstchild = context;
449  }
450  else
451  {
452  context->parent = NULL;
453  context->prevchild = NULL;
454  context->nextchild = NULL;
455  }
456 }
457 
458 /*
459  * MemoryContextAllowInCriticalSection
460  * Allow/disallow allocations in this memory context within a critical
461  * section.
462  *
463  * Normally, memory allocations are not allowed within a critical section,
464  * because a failure would lead to PANIC. There are a few exceptions to
465  * that, like allocations related to debugging code that is not supposed to
466  * be enabled in production. This function can be used to exempt specific
467  * memory contexts from the assertion in palloc().
468  */
469 void
471 {
473 
474  context->allowInCritSection = allow;
475 }
476 
477 /*
478  * GetMemoryChunkContext
479  * Given a currently-allocated chunk, determine the MemoryContext that
480  * the chunk belongs to.
481  */
483 GetMemoryChunkContext(void *pointer)
484 {
485  /*
486  * Try to detect bogus pointers handed to us, poorly though we can.
487  * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
488  * allocated chunk.
489  */
490  Assert(pointer != NULL);
491  Assert(pointer == (void *) MAXALIGN(pointer));
492  /* adding further Asserts here? See pre-checks in MemoryContextContains */
493 
494  return MCXT_METHOD(pointer, get_chunk_context) (pointer);
495 }
496 
497 /*
498  * GetMemoryChunkSpace
499  * Given a currently-allocated chunk, determine the total space
500  * it occupies (including all memory-allocation overhead).
501  *
502  * This is useful for measuring the total space occupied by a set of
503  * allocated chunks.
504  */
505 Size
506 GetMemoryChunkSpace(void *pointer)
507 {
508  return MCXT_METHOD(pointer, get_chunk_space) (pointer);
509 }
510 
511 /*
512  * MemoryContextGetParent
513  * Get the parent context (if any) of the specified context
514  */
517 {
519 
520  return context->parent;
521 }
522 
523 /*
524  * MemoryContextIsEmpty
525  * Is a memory context empty of any allocated space?
526  */
527 bool
529 {
531 
532  /*
533  * For now, we consider a memory context nonempty if it has any children;
534  * perhaps this should be changed later.
535  */
536  if (context->firstchild != NULL)
537  return false;
538  /* Otherwise use the type-specific inquiry */
539  return context->methods->is_empty(context);
540 }
541 
542 /*
543  * Find the memory allocated to blocks for this memory context. If recurse is
544  * true, also include children.
545  */
546 Size
548 {
549  Size total = context->mem_allocated;
550 
552 
553  if (recurse)
554  {
555  MemoryContext child;
556 
557  for (child = context->firstchild;
558  child != NULL;
559  child = child->nextchild)
560  total += MemoryContextMemAllocated(child, true);
561  }
562 
563  return total;
564 }
565 
566 /*
567  * MemoryContextStats
568  * Print statistics about the named context and all its descendants.
569  *
570  * This is just a debugging utility, so it's not very fancy. However, we do
571  * make some effort to summarize when the output would otherwise be very long.
572  * The statistics are sent to stderr.
573  */
574 void
576 {
577  /* A hard-wired limit on the number of children is usually good enough */
578  MemoryContextStatsDetail(context, 100, true);
579 }
580 
581 /*
582  * MemoryContextStatsDetail
583  *
584  * Entry point for use if you want to vary the number of child contexts shown.
585  *
586  * If print_to_stderr is true, print statistics about the memory contexts
587  * with fprintf(stderr), otherwise use ereport().
588  */
589 void
590 MemoryContextStatsDetail(MemoryContext context, int max_children,
591  bool print_to_stderr)
592 {
593  MemoryContextCounters grand_totals;
594 
595  memset(&grand_totals, 0, sizeof(grand_totals));
596 
597  MemoryContextStatsInternal(context, 0, true, max_children, &grand_totals, print_to_stderr);
598 
599  if (print_to_stderr)
600  fprintf(stderr,
601  "Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used\n",
602  grand_totals.totalspace, grand_totals.nblocks,
603  grand_totals.freespace, grand_totals.freechunks,
604  grand_totals.totalspace - grand_totals.freespace);
605  else
606 
607  /*
608  * Use LOG_SERVER_ONLY to prevent the memory contexts from being sent
609  * to the connected client.
610  *
611  * We don't buffer the information about all memory contexts in a
612  * backend into StringInfo and log it as one message. Otherwise which
613  * may require the buffer to be enlarged very much and lead to OOM
614  * error since there can be a large number of memory contexts in a
615  * backend. Instead, we log one message per memory context.
616  */
618  (errhidestmt(true),
619  errhidecontext(true),
620  errmsg_internal("Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used",
621  grand_totals.totalspace, grand_totals.nblocks,
622  grand_totals.freespace, grand_totals.freechunks,
623  grand_totals.totalspace - grand_totals.freespace)));
624 }
625 
626 /*
627  * MemoryContextStatsInternal
628  * One recursion level for MemoryContextStats
629  *
630  * Print this context if print is true, but in any case accumulate counts into
631  * *totals (if given).
632  */
633 static void
635  bool print, int max_children,
636  MemoryContextCounters *totals,
637  bool print_to_stderr)
638 {
639  MemoryContextCounters local_totals;
640  MemoryContext child;
641  int ichild;
642 
644 
645  /* Examine the context itself */
646  context->methods->stats(context,
648  (void *) &level,
649  totals, print_to_stderr);
650 
651  /*
652  * Examine children. If there are more than max_children of them, we do
653  * not print the rest explicitly, but just summarize them.
654  */
655  memset(&local_totals, 0, sizeof(local_totals));
656 
657  for (child = context->firstchild, ichild = 0;
658  child != NULL;
659  child = child->nextchild, ichild++)
660  {
661  if (ichild < max_children)
662  MemoryContextStatsInternal(child, level + 1,
663  print, max_children,
664  totals,
665  print_to_stderr);
666  else
667  MemoryContextStatsInternal(child, level + 1,
668  false, max_children,
669  &local_totals,
670  print_to_stderr);
671  }
672 
673  /* Deal with excess children */
674  if (ichild > max_children)
675  {
676  if (print)
677  {
678  if (print_to_stderr)
679  {
680  int i;
681 
682  for (i = 0; i <= level; i++)
683  fprintf(stderr, " ");
684  fprintf(stderr,
685  "%d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used\n",
686  ichild - max_children,
687  local_totals.totalspace,
688  local_totals.nblocks,
689  local_totals.freespace,
690  local_totals.freechunks,
691  local_totals.totalspace - local_totals.freespace);
692  }
693  else
695  (errhidestmt(true),
696  errhidecontext(true),
697  errmsg_internal("level: %d; %d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used",
698  level,
699  ichild - max_children,
700  local_totals.totalspace,
701  local_totals.nblocks,
702  local_totals.freespace,
703  local_totals.freechunks,
704  local_totals.totalspace - local_totals.freespace)));
705  }
706 
707  if (totals)
708  {
709  totals->nblocks += local_totals.nblocks;
710  totals->freechunks += local_totals.freechunks;
711  totals->totalspace += local_totals.totalspace;
712  totals->freespace += local_totals.freespace;
713  }
714  }
715 }
716 
717 /*
718  * MemoryContextStatsPrint
719  * Print callback used by MemoryContextStatsInternal
720  *
721  * For now, the passthru pointer just points to "int level"; later we might
722  * make that more complicated.
723  */
724 static void
725 MemoryContextStatsPrint(MemoryContext context, void *passthru,
726  const char *stats_string,
727  bool print_to_stderr)
728 {
729  int level = *(int *) passthru;
730  const char *name = context->name;
731  const char *ident = context->ident;
732  char truncated_ident[110];
733  int i;
734 
735  /*
736  * It seems preferable to label dynahash contexts with just the hash table
737  * name. Those are already unique enough, so the "dynahash" part isn't
738  * very helpful, and this way is more consistent with pre-v11 practice.
739  */
740  if (ident && strcmp(name, "dynahash") == 0)
741  {
742  name = ident;
743  ident = NULL;
744  }
745 
746  truncated_ident[0] = '\0';
747 
748  if (ident)
749  {
750  /*
751  * Some contexts may have very long identifiers (e.g., SQL queries).
752  * Arbitrarily truncate at 100 bytes, but be careful not to break
753  * multibyte characters. Also, replace ASCII control characters, such
754  * as newlines, with spaces.
755  */
756  int idlen = strlen(ident);
757  bool truncated = false;
758 
759  strcpy(truncated_ident, ": ");
760  i = strlen(truncated_ident);
761 
762  if (idlen > 100)
763  {
764  idlen = pg_mbcliplen(ident, idlen, 100);
765  truncated = true;
766  }
767 
768  while (idlen-- > 0)
769  {
770  unsigned char c = *ident++;
771 
772  if (c < ' ')
773  c = ' ';
774  truncated_ident[i++] = c;
775  }
776  truncated_ident[i] = '\0';
777 
778  if (truncated)
779  strcat(truncated_ident, "...");
780  }
781 
782  if (print_to_stderr)
783  {
784  for (i = 0; i < level; i++)
785  fprintf(stderr, " ");
786  fprintf(stderr, "%s: %s%s\n", name, stats_string, truncated_ident);
787  }
788  else
790  (errhidestmt(true),
791  errhidecontext(true),
792  errmsg_internal("level: %d; %s: %s%s",
793  level, name, stats_string, truncated_ident)));
794 }
795 
796 /*
797  * MemoryContextCheck
798  * Check all chunks in the named context.
799  *
800  * This is just a debugging utility, so it's not fancy.
801  */
802 #ifdef MEMORY_CONTEXT_CHECKING
803 void
804 MemoryContextCheck(MemoryContext context)
805 {
806  MemoryContext child;
807 
809 
810  context->methods->check(context);
811  for (child = context->firstchild; child != NULL; child = child->nextchild)
812  MemoryContextCheck(child);
813 }
814 #endif
815 
816 /*
817  * MemoryContextContains
818  * Detect whether an allocated chunk of memory belongs to a given
819  * context or not.
820  *
821  * Caution: 'pointer' must point to a pointer which was allocated by a
822  * MemoryContext. It's not safe or valid to use this function on arbitrary
823  * pointers as obtaining the MemoryContext which 'pointer' belongs to requires
824  * possibly several pointer dereferences.
825  */
826 bool
827 MemoryContextContains(MemoryContext context, void *pointer)
828 {
829  /*
830  * Temporarily make this always return false as we don't yet have a fully
831  * baked idea on how to make it work correctly with the new MemoryChunk
832  * code.
833  */
834  return false;
835 
836 #ifdef NOT_USED
837  MemoryContext ptr_context;
838 
839  /*
840  * NB: We must perform run-time checks here which GetMemoryChunkContext()
841  * does as assertions before calling GetMemoryChunkContext().
842  *
843  * Try to detect bogus pointers handed to us, poorly though we can.
844  * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
845  * allocated chunk.
846  */
847  if (pointer == NULL || pointer != (void *) MAXALIGN(pointer))
848  return false;
849 
850  /*
851  * OK, it's probably safe to look at the context.
852  */
853  ptr_context = GetMemoryChunkContext(pointer);
854 
855  return ptr_context == context;
856 #endif
857 }
858 
859 /*
860  * MemoryContextCreate
861  * Context-type-independent part of context creation.
862  *
863  * This is only intended to be called by context-type-specific
864  * context creation routines, not by the unwashed masses.
865  *
866  * The memory context creation procedure goes like this:
867  * 1. Context-type-specific routine makes some initial space allocation,
868  * including enough space for the context header. If it fails,
869  * it can ereport() with no damage done.
870  * 2. Context-type-specific routine sets up all type-specific fields of
871  * the header (those beyond MemoryContextData proper), as well as any
872  * other management fields it needs to have a fully valid context.
873  * Usually, failure in this step is impossible, but if it's possible
874  * the initial space allocation should be freed before ereport'ing.
875  * 3. Context-type-specific routine calls MemoryContextCreate() to fill in
876  * the generic header fields and link the context into the context tree.
877  * 4. We return to the context-type-specific routine, which finishes
878  * up type-specific initialization. This routine can now do things
879  * that might fail (like allocate more memory), so long as it's
880  * sure the node is left in a state that delete will handle.
881  *
882  * node: the as-yet-uninitialized common part of the context header node.
883  * tag: NodeTag code identifying the memory context type.
884  * method_id: MemoryContextMethodID of the context-type being created.
885  * parent: parent context, or NULL if this will be a top-level context.
886  * name: name of context (must be statically allocated).
887  *
888  * Context routines generally assume that MemoryContextCreate can't fail,
889  * so this can contain Assert but not elog/ereport.
890  */
891 void
893  NodeTag tag,
894  MemoryContextMethodID method_id,
895  MemoryContext parent,
896  const char *name)
897 {
898  /* Creating new memory contexts is not allowed in a critical section */
899  Assert(CritSectionCount == 0);
900 
901  /* Initialize all standard fields of memory context header */
902  node->type = tag;
903  node->isReset = true;
904  node->methods = &mcxt_methods[method_id];
905  node->parent = parent;
906  node->firstchild = NULL;
907  node->mem_allocated = 0;
908  node->prevchild = NULL;
909  node->name = name;
910  node->ident = NULL;
911  node->reset_cbs = NULL;
912 
913  /* OK to link node into context tree */
914  if (parent)
915  {
916  node->nextchild = parent->firstchild;
917  if (parent->firstchild != NULL)
918  parent->firstchild->prevchild = node;
919  parent->firstchild = node;
920  /* inherit allowInCritSection flag from parent */
921  node->allowInCritSection = parent->allowInCritSection;
922  }
923  else
924  {
925  node->nextchild = NULL;
926  node->allowInCritSection = false;
927  }
928 
929  VALGRIND_CREATE_MEMPOOL(node, 0, false);
930 }
931 
932 /*
933  * MemoryContextAlloc
934  * Allocate space within the specified context.
935  *
936  * This could be turned into a macro, but we'd have to import
937  * nodes/memnodes.h into postgres.h which seems a bad idea.
938  */
939 void *
941 {
942  void *ret;
943 
946 
947  if (!AllocSizeIsValid(size))
948  elog(ERROR, "invalid memory alloc request size %zu", size);
949 
950  context->isReset = false;
951 
952  ret = context->methods->alloc(context, size);
953  if (unlikely(ret == NULL))
954  {
956 
957  /*
958  * Here, and elsewhere in this module, we show the target context's
959  * "name" but not its "ident" (if any) in user-visible error messages.
960  * The "ident" string might contain security-sensitive data, such as
961  * values in SQL commands.
962  */
963  ereport(ERROR,
964  (errcode(ERRCODE_OUT_OF_MEMORY),
965  errmsg("out of memory"),
966  errdetail("Failed on request of size %zu in memory context \"%s\".",
967  size, context->name)));
968  }
969 
970  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
971 
972  return ret;
973 }
974 
975 /*
976  * MemoryContextAllocZero
977  * Like MemoryContextAlloc, but clears allocated memory
978  *
979  * We could just call MemoryContextAlloc then clear the memory, but this
980  * is a very common combination, so we provide the combined operation.
981  */
982 void *
984 {
985  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  {
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 /*
1014  * MemoryContextAllocZeroAligned
1015  * MemoryContextAllocZero where length is suitable for MemSetLoop
1016  *
1017  * This might seem overly specialized, but it's not because newNode()
1018  * is so often called with compile-time-constant sizes.
1019  */
1020 void *
1022 {
1023  void *ret;
1024 
1025  AssertArg(MemoryContextIsValid(context));
1026  AssertNotInCriticalSection(context);
1027 
1028  if (!AllocSizeIsValid(size))
1029  elog(ERROR, "invalid memory alloc request size %zu", size);
1030 
1031  context->isReset = false;
1032 
1033  ret = context->methods->alloc(context, size);
1034  if (unlikely(ret == NULL))
1035  {
1037  ereport(ERROR,
1038  (errcode(ERRCODE_OUT_OF_MEMORY),
1039  errmsg("out of memory"),
1040  errdetail("Failed on request of size %zu in memory context \"%s\".",
1041  size, context->name)));
1042  }
1043 
1044  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1045 
1046  MemSetLoop(ret, 0, size);
1047 
1048  return ret;
1049 }
1050 
1051 /*
1052  * MemoryContextAllocExtended
1053  * Allocate space within the specified context using the given flags.
1054  */
1055 void *
1057 {
1058  void *ret;
1059 
1060  AssertArg(MemoryContextIsValid(context));
1061  AssertNotInCriticalSection(context);
1062 
1063  if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
1064  ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
1065  elog(ERROR, "invalid memory alloc request size %zu", size);
1066 
1067  context->isReset = false;
1068 
1069  ret = context->methods->alloc(context, size);
1070  if (unlikely(ret == NULL))
1071  {
1072  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
1073  {
1075  ereport(ERROR,
1076  (errcode(ERRCODE_OUT_OF_MEMORY),
1077  errmsg("out of memory"),
1078  errdetail("Failed on request of size %zu in memory context \"%s\".",
1079  size, context->name)));
1080  }
1081  return NULL;
1082  }
1083 
1084  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1085 
1086  if ((flags & MCXT_ALLOC_ZERO) != 0)
1087  MemSetAligned(ret, 0, size);
1088 
1089  return ret;
1090 }
1091 
1092 /*
1093  * HandleLogMemoryContextInterrupt
1094  * Handle receipt of an interrupt indicating logging of memory
1095  * contexts.
1096  *
1097  * All the actual work is deferred to ProcessLogMemoryContextInterrupt(),
1098  * because we cannot safely emit a log message inside the signal handler.
1099  */
1100 void
1102 {
1103  InterruptPending = true;
1104  LogMemoryContextPending = true;
1105  /* latch will be set by procsignal_sigusr1_handler */
1106 }
1107 
1108 /*
1109  * ProcessLogMemoryContextInterrupt
1110  * Perform logging of memory contexts of this backend process.
1111  *
1112  * Any backend that participates in ProcSignal signaling must arrange
1113  * to call this function if we see LogMemoryContextPending set.
1114  * It is called from CHECK_FOR_INTERRUPTS(), which is enough because
1115  * the target process for logging of memory contexts is a backend.
1116  */
1117 void
1119 {
1120  LogMemoryContextPending = false;
1121 
1122  /*
1123  * Use LOG_SERVER_ONLY to prevent this message from being sent to the
1124  * connected client.
1125  */
1127  (errhidestmt(true),
1128  errhidecontext(true),
1129  errmsg("logging memory contexts of PID %d", MyProcPid)));
1130 
1131  /*
1132  * When a backend process is consuming huge memory, logging all its memory
1133  * contexts might overrun available disk space. To prevent this, we limit
1134  * the number of child contexts to log per parent to 100.
1135  *
1136  * As with MemoryContextStats(), we suppose that practical cases where the
1137  * dump gets long will typically be huge numbers of siblings under the
1138  * same parent context; while the additional debugging value from seeing
1139  * details about individual siblings beyond 100 will not be large.
1140  */
1142 }
1143 
1144 void *
1146 {
1147  /* duplicates MemoryContextAlloc to avoid increased overhead */
1148  void *ret;
1150 
1151  AssertArg(MemoryContextIsValid(context));
1152  AssertNotInCriticalSection(context);
1153 
1154  if (!AllocSizeIsValid(size))
1155  elog(ERROR, "invalid memory alloc request size %zu", size);
1156 
1157  context->isReset = false;
1158 
1159  ret = context->methods->alloc(context, size);
1160  if (unlikely(ret == NULL))
1161  {
1163  ereport(ERROR,
1164  (errcode(ERRCODE_OUT_OF_MEMORY),
1165  errmsg("out of memory"),
1166  errdetail("Failed on request of size %zu in memory context \"%s\".",
1167  size, context->name)));
1168  }
1169 
1170  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1171 
1172  return ret;
1173 }
1174 
1175 void *
1177 {
1178  /* duplicates MemoryContextAllocZero to avoid increased overhead */
1179  void *ret;
1181 
1182  AssertArg(MemoryContextIsValid(context));
1183  AssertNotInCriticalSection(context);
1184 
1185  if (!AllocSizeIsValid(size))
1186  elog(ERROR, "invalid memory alloc request size %zu", size);
1187 
1188  context->isReset = false;
1189 
1190  ret = context->methods->alloc(context, size);
1191  if (unlikely(ret == NULL))
1192  {
1194  ereport(ERROR,
1195  (errcode(ERRCODE_OUT_OF_MEMORY),
1196  errmsg("out of memory"),
1197  errdetail("Failed on request of size %zu in memory context \"%s\".",
1198  size, context->name)));
1199  }
1200 
1201  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1202 
1203  MemSetAligned(ret, 0, size);
1204 
1205  return ret;
1206 }
1207 
1208 void *
1209 palloc_extended(Size size, int flags)
1210 {
1211  /* duplicates MemoryContextAllocExtended to avoid increased overhead */
1212  void *ret;
1214 
1215  AssertArg(MemoryContextIsValid(context));
1216  AssertNotInCriticalSection(context);
1217 
1218  if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
1219  ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
1220  elog(ERROR, "invalid memory alloc request size %zu", size);
1221 
1222  context->isReset = false;
1223 
1224  ret = context->methods->alloc(context, size);
1225  if (unlikely(ret == NULL))
1226  {
1227  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
1228  {
1230  ereport(ERROR,
1231  (errcode(ERRCODE_OUT_OF_MEMORY),
1232  errmsg("out of memory"),
1233  errdetail("Failed on request of size %zu in memory context \"%s\".",
1234  size, context->name)));
1235  }
1236  return NULL;
1237  }
1238 
1239  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1240 
1241  if ((flags & MCXT_ALLOC_ZERO) != 0)
1242  MemSetAligned(ret, 0, size);
1243 
1244  return ret;
1245 }
1246 
1247 /*
1248  * pfree
1249  * Release an allocated chunk.
1250  */
1251 void
1252 pfree(void *pointer)
1253 {
1254 #ifdef USE_VALGRIND
1255  MemoryContext context = GetMemoryChunkContext(pointer);
1256 #endif
1257 
1258  MCXT_METHOD(pointer, free_p) (pointer);
1259  VALGRIND_MEMPOOL_FREE(context, pointer);
1260 }
1261 
1262 /*
1263  * repalloc
1264  * Adjust the size of a previously allocated chunk.
1265  */
1266 void *
1267 repalloc(void *pointer, Size size)
1268 {
1269 #if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
1270  MemoryContext context = GetMemoryChunkContext(pointer);
1271 #endif
1272  void *ret;
1273 
1274  if (!AllocSizeIsValid(size))
1275  elog(ERROR, "invalid memory alloc request size %zu", size);
1276 
1277  AssertNotInCriticalSection(context);
1278 
1279  /* isReset must be false already */
1280  Assert(!context->isReset);
1281 
1282  ret = MCXT_METHOD(pointer, realloc) (pointer, size);
1283  if (unlikely(ret == NULL))
1284  {
1285  MemoryContext cxt = GetMemoryChunkContext(pointer);
1286 
1288  ereport(ERROR,
1289  (errcode(ERRCODE_OUT_OF_MEMORY),
1290  errmsg("out of memory"),
1291  errdetail("Failed on request of size %zu in memory context \"%s\".",
1292  size, cxt->name)));
1293  }
1294 
1295  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1296 
1297  return ret;
1298 }
1299 
1300 /*
1301  * MemoryContextAllocHuge
1302  * Allocate (possibly-expansive) space within the specified context.
1303  *
1304  * See considerations in comment at MaxAllocHugeSize.
1305  */
1306 void *
1308 {
1309  void *ret;
1310 
1311  AssertArg(MemoryContextIsValid(context));
1312  AssertNotInCriticalSection(context);
1313 
1314  if (!AllocHugeSizeIsValid(size))
1315  elog(ERROR, "invalid memory alloc request size %zu", size);
1316 
1317  context->isReset = false;
1318 
1319  ret = context->methods->alloc(context, size);
1320  if (unlikely(ret == NULL))
1321  {
1323  ereport(ERROR,
1324  (errcode(ERRCODE_OUT_OF_MEMORY),
1325  errmsg("out of memory"),
1326  errdetail("Failed on request of size %zu in memory context \"%s\".",
1327  size, context->name)));
1328  }
1329 
1330  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1331 
1332  return ret;
1333 }
1334 
1335 /*
1336  * repalloc_huge
1337  * Adjust the size of a previously allocated chunk, permitting a large
1338  * value. The previous allocation need not have been "huge".
1339  */
1340 void *
1341 repalloc_huge(void *pointer, Size size)
1342 {
1343 #if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
1344  MemoryContext context = GetMemoryChunkContext(pointer);
1345 #endif
1346  void *ret;
1347 
1348  if (!AllocHugeSizeIsValid(size))
1349  elog(ERROR, "invalid memory alloc request size %zu", size);
1350 
1351  AssertNotInCriticalSection(context);
1352 
1353  /* isReset must be false already */
1354  Assert(!context->isReset);
1355 
1356  ret = MCXT_METHOD(pointer, realloc) (pointer, size);
1357  if (unlikely(ret == NULL))
1358  {
1359  MemoryContext cxt = GetMemoryChunkContext(pointer);
1360 
1362  ereport(ERROR,
1363  (errcode(ERRCODE_OUT_OF_MEMORY),
1364  errmsg("out of memory"),
1365  errdetail("Failed on request of size %zu in memory context \"%s\".",
1366  size, cxt->name)));
1367  }
1368 
1369  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1370 
1371  return ret;
1372 }
1373 
1374 /*
1375  * MemoryContextStrdup
1376  * Like strdup(), but allocate from the specified context
1377  */
1378 char *
1379 MemoryContextStrdup(MemoryContext context, const char *string)
1380 {
1381  char *nstr;
1382  Size len = strlen(string) + 1;
1383 
1384  nstr = (char *) MemoryContextAlloc(context, len);
1385 
1386  memcpy(nstr, string, len);
1387 
1388  return nstr;
1389 }
1390 
1391 char *
1392 pstrdup(const char *in)
1393 {
1395 }
1396 
1397 /*
1398  * pnstrdup
1399  * Like pstrdup(), but append null byte to a
1400  * not-necessarily-null-terminated input string.
1401  */
1402 char *
1403 pnstrdup(const char *in, Size len)
1404 {
1405  char *out;
1406 
1407  len = strnlen(in, len);
1408 
1409  out = palloc(len + 1);
1410  memcpy(out, in, len);
1411  out[len] = '\0';
1412 
1413  return out;
1414 }
1415 
1416 /*
1417  * Make copy of string with all trailing newline characters removed.
1418  */
1419 char *
1420 pchomp(const char *in)
1421 {
1422  size_t n;
1423 
1424  n = strlen(in);
1425  while (n > 0 && in[n - 1] == '\n')
1426  n--;
1427  return pnstrdup(in, n);
1428 }
void AllocSetReset(MemoryContext context)
Definition: aset.c:529
Size AllocSetGetChunkSpace(void *pointer)
Definition: aset.c:1342
MemoryContext AllocSetGetChunkContext(void *pointer)
Definition: aset.c:1320
void AllocSetStats(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
Definition: aset.c:1385
bool AllocSetIsEmpty(MemoryContext context)
Definition: aset.c:1362
void * AllocSetRealloc(void *pointer, Size size)
Definition: aset.c:1086
void AllocSetFree(void *pointer)
Definition: aset.c:987
void AllocSetDelete(MemoryContext context)
Definition: aset.c:597
void * AllocSetAlloc(MemoryContext context, Size size)
Definition: aset.c:691
void print(const void *obj)
Definition: print.c:36
#define AssertState(condition)
Definition: c.h:797
#define MAXALIGN(LEN)
Definition: c.h:747
#define MemSetAligned(start, val, len)
Definition: c.h:1028
#define unlikely(x)
Definition: c.h:295
size_t Size
Definition: c.h:541
#define MemSetLoop(start, val, len)
Definition: c.h:1063
#define AssertArg(condition)
Definition: c.h:796
int errmsg_internal(const char *fmt,...)
Definition: elog.c:993
int errhidestmt(bool hide_stmt)
Definition: elog.c:1247
int errdetail(const char *fmt,...)
Definition: elog.c:1039
int errhidecontext(bool hide_ctx)
Definition: elog.c:1266
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define LOG_SERVER_ONLY
Definition: elog.h:28
#define ERROR
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:145
const char * name
Definition: encode.c:561
#define MCXT_ALLOC_ZERO
Definition: fe_memutils.h:18
#define MCXT_ALLOC_HUGE
Definition: fe_memutils.h:16
#define MCXT_ALLOC_NO_OOM
Definition: fe_memutils.h:17
void GenerationReset(MemoryContext context)
Definition: generation.c:273
void GenerationFree(void *pointer)
Definition: generation.c:616
MemoryContext GenerationGetChunkContext(void *pointer)
Definition: generation.c:838
Size GenerationGetChunkSpace(void *pointer)
Definition: generation.c:857
void * GenerationAlloc(MemoryContext context, Size size)
Definition: generation.c:340
bool GenerationIsEmpty(MemoryContext context)
Definition: generation.c:879
void GenerationStats(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
Definition: generation.c:908
void * GenerationRealloc(void *pointer, Size size)
Definition: generation.c:712
void GenerationDelete(MemoryContext context)
Definition: generation.c:318
volatile sig_atomic_t LogMemoryContextPending
Definition: globals.c:38
volatile sig_atomic_t InterruptPending
Definition: globals.c:30
int MyProcPid
Definition: globals.c:44
volatile uint32 CritSectionCount
Definition: globals.c:42
#define realloc(a, b)
Definition: header.h:60
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1026
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1403
static void MemoryContextCallResetCallbacks(MemoryContext context)
Definition: mcxt.c:361
MemoryContext MessageContext
Definition: mcxt.c:97
bool MemoryContextIsEmpty(MemoryContext context)
Definition: mcxt.c:528
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:195
void MemoryContextCreate(MemoryContext node, NodeTag tag, MemoryContextMethodID method_id, MemoryContext parent, const char *name)
Definition: mcxt.c:892
MemoryContext TopTransactionContext
Definition: mcxt.c:98
char * pchomp(const char *in)
Definition: mcxt.c:1420
void HandleLogMemoryContextInterrupt(void)
Definition: mcxt.c:1101
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:344
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:413
void MemoryContextStatsDetail(MemoryContext context, int max_children, bool print_to_stderr)
Definition: mcxt.c:590
char * pstrdup(const char *in)
Definition: mcxt.c:1392
void pfree(void *pointer)
Definition: mcxt.c:1252
Size GetMemoryChunkSpace(void *pointer)
Definition: mcxt.c:506
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:315
MemoryContext TopMemoryContext
Definition: mcxt.c:93
#define AssertNotInCriticalSection(context)
Definition: mcxt.c:118
void * palloc0(Size size)
Definition: mcxt.c:1176
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:983
MemoryContext CurTransactionContext
Definition: mcxt.c:99
void * MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
Definition: mcxt.c:1056
MemoryContext CurrentMemoryContext
Definition: mcxt.c:87
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1267
void * palloc_extended(Size size, int flags)
Definition: mcxt.c:1209
MemoryContext GetMemoryChunkContext(void *pointer)
Definition: mcxt.c:483
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:940
void * MemoryContextAllocZeroAligned(MemoryContext context, Size size)
Definition: mcxt.c:1021
Size MemoryContextMemAllocated(MemoryContext context, bool recurse)
Definition: mcxt.c:547
void MemoryContextStats(MemoryContext context)
Definition: mcxt.c:575
void MemoryContextInit(void)
Definition: mcxt.c:151
bool MemoryContextContains(MemoryContext context, void *pointer)
Definition: mcxt.c:827
MemoryContext PostmasterContext
Definition: mcxt.c:95
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1379
static const MemoryContextMethods mcxt_methods[]
Definition: mcxt.c:39
static void MemoryContextStatsInternal(MemoryContext context, int level, bool print, int max_children, MemoryContextCounters *totals, bool print_to_stderr)
Definition: mcxt.c:634
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:516
void ProcessLogMemoryContextInterrupt(void)
Definition: mcxt.c:1118
MemoryContext ErrorContext
Definition: mcxt.c:94
MemoryContext CacheMemoryContext
Definition: mcxt.c:96
void * MemoryContextAllocHuge(MemoryContext context, Size size)
Definition: mcxt.c:1307
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:270
void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
Definition: mcxt.c:470
void MemoryContextResetChildren(MemoryContext context)
Definition: mcxt.c:247
static void MemoryContextStatsPrint(MemoryContext context, void *passthru, const char *stats_string, bool print_to_stderr)
Definition: mcxt.c:725
void * palloc(Size size)
Definition: mcxt.c:1145
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:388
void MemoryContextResetOnly(MemoryContext context)
Definition: mcxt.c:214
MemoryContext PortalContext
Definition: mcxt.c:102
void * repalloc_huge(void *pointer, Size size)
Definition: mcxt.c:1341
#define MCXT_METHOD(pointer, method)
Definition: mcxt.c:125
#define VALGRIND_DESTROY_MEMPOOL(context)
Definition: memdebug.h:25
#define VALGRIND_MEMPOOL_CHANGE(context, optr, nptr, size)
Definition: memdebug.h:31
#define VALGRIND_CREATE_MEMPOOL(context, redzones, zeroed)
Definition: memdebug.h:24
#define VALGRIND_MEMPOOL_ALLOC(context, addr, size)
Definition: memdebug.h:29
#define VALGRIND_MEMPOOL_FREE(context, addr)
Definition: memdebug.h:30
#define MemoryContextIsValid(context)
Definition: memnodes.h:107
#define AllocSetContextCreate
Definition: memutils.h:130
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:154
#define AllocHugeSizeIsValid(size)
Definition: memutils.h:49
#define AllocSizeIsValid(size)
Definition: memutils.h:42
MemoryContextMethodID
@ MCTX_GENERATION_ID
@ MCTX_SLAB_ID
@ MCTX_ASET_ID
NodeTag
Definition: nodes.h:27
const void size_t len
#define fprintf
Definition: port.h:238
size_t strnlen(const char *str, size_t maxlen)
Definition: strnlen.c:26
char * c
void * SlabAlloc(MemoryContext context, Size size)
Definition: slab.c:294
void SlabFree(void *pointer)
Definition: slab.c:451
void SlabReset(MemoryContext context)
Definition: slab.c:237
Size SlabGetChunkSpace(void *pointer)
Definition: slab.c:576
bool SlabIsEmpty(MemoryContext context)
Definition: slab.c:592
MemoryContext SlabGetChunkContext(void *pointer)
Definition: slab.c:559
void SlabStats(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
Definition: slab.c:611
void * SlabRealloc(void *pointer, Size size)
Definition: slab.c:539
void SlabDelete(MemoryContext context)
Definition: slab.c:280
struct MemoryContextCallback * next
Definition: palloc.h:51
MemoryContextCallbackFunction func
Definition: palloc.h:49
MemoryContext prevchild
Definition: memnodes.h:91
MemoryContext firstchild
Definition: memnodes.h:90
bool allowInCritSection
Definition: memnodes.h:86
const char * ident
Definition: memnodes.h:94
MemoryContext parent
Definition: memnodes.h:89
MemoryContextCallback * reset_cbs
Definition: memnodes.h:95
const MemoryContextMethods * methods
Definition: memnodes.h:88
MemoryContext nextchild
Definition: memnodes.h:92
Size mem_allocated
Definition: memnodes.h:87
const char * name
Definition: memnodes.h:93
void(* delete_context)(MemoryContext context)
Definition: memnodes.h:65
void(* stats)(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
Definition: memnodes.h:69
bool(* is_empty)(MemoryContext context)
Definition: memnodes.h:68
void(* reset)(MemoryContext context)
Definition: memnodes.h:64
void *(* alloc)(MemoryContext context, Size size)
Definition: memnodes.h:60