Line data Source code
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 : */
37 : MemoryContext CurrentMemoryContext = NULL;
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 : */
43 : MemoryContext TopMemoryContext = NULL;
44 : MemoryContext ErrorContext = NULL;
45 : MemoryContext PostmasterContext = NULL;
46 : MemoryContext CacheMemoryContext = NULL;
47 : MemoryContext MessageContext = NULL;
48 : MemoryContext TopTransactionContext = NULL;
49 : MemoryContext CurTransactionContext = NULL;
50 :
51 : /* This is a transient link to the active portal's memory context: */
52 : MemoryContext PortalContext = NULL;
53 :
54 : static void MemoryContextCallResetCallbacks(MemoryContext context);
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
89 6 : MemoryContextInit(void)
90 : {
91 6 : 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 6 : TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
99 : "TopMemoryContext",
100 : ALLOCSET_DEFAULT_SIZES);
101 :
102 : /*
103 : * Not having any other place to point CurrentMemoryContext, make it point
104 : * to TopMemoryContext. Caller should change this soon!
105 : */
106 6 : 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 6 : ErrorContext = AllocSetContextCreate(TopMemoryContext,
122 : "ErrorContext",
123 : 8 * 1024,
124 : 8 * 1024,
125 : 8 * 1024);
126 6 : MemoryContextAllowInCriticalSection(ErrorContext, true);
127 6 : }
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
135 25273396 : MemoryContextReset(MemoryContext context)
136 : {
137 25273396 : AssertArg(MemoryContextIsValid(context));
138 :
139 : /* save a function call in common case where there are no children */
140 25273396 : if (context->firstchild != NULL)
141 1376 : MemoryContextDeleteChildren(context);
142 :
143 : /* save a function call if no pallocs since startup or last reset */
144 25273396 : if (!context->isReset)
145 1188939 : MemoryContextResetOnly(context);
146 25273396 : }
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
154 1188939 : MemoryContextResetOnly(MemoryContext context)
155 : {
156 1188939 : AssertArg(MemoryContextIsValid(context));
157 :
158 : /* Nothing to do if no pallocs since startup or last reset */
159 1188939 : if (!context->isReset)
160 : {
161 1188939 : MemoryContextCallResetCallbacks(context);
162 1188939 : (*context->methods->reset) (context);
163 1188939 : context->isReset = true;
164 : VALGRIND_DESTROY_MEMPOOL(context);
165 : VALGRIND_CREATE_MEMPOOL(context, 0, false);
166 : }
167 1188939 : }
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
176 0 : MemoryContextResetChildren(MemoryContext context)
177 : {
178 : MemoryContext child;
179 :
180 0 : AssertArg(MemoryContextIsValid(context));
181 :
182 0 : for (child = context->firstchild; child != NULL; child = child->nextchild)
183 : {
184 0 : MemoryContextResetChildren(child);
185 0 : MemoryContextResetOnly(child);
186 : }
187 0 : }
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
200 388369 : MemoryContextDelete(MemoryContext context)
201 : {
202 388369 : AssertArg(MemoryContextIsValid(context));
203 : /* We had better not be deleting TopMemoryContext ... */
204 388369 : Assert(context != TopMemoryContext);
205 : /* And not CurrentMemoryContext, either */
206 388369 : Assert(context != CurrentMemoryContext);
207 :
208 388369 : MemoryContextDeleteChildren(context);
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 : */
216 388369 : MemoryContextCallResetCallbacks(context);
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 388369 : MemoryContextSetParent(context, NULL);
224 :
225 388369 : (*context->methods->delete_context) (context);
226 : VALGRIND_DESTROY_MEMPOOL(context);
227 388369 : pfree(context);
228 388369 : }
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
236 405402 : MemoryContextDeleteChildren(MemoryContext context)
237 : {
238 405402 : AssertArg(MemoryContextIsValid(context));
239 :
240 : /*
241 : * MemoryContextDelete will delink the child from me, so just iterate as
242 : * long as there is a child.
243 : */
244 839424 : while (context->firstchild != NULL)
245 28620 : MemoryContextDelete(context->firstchild);
246 405402 : }
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
265 1461 : MemoryContextRegisterResetCallback(MemoryContext context,
266 : MemoryContextCallback *cb)
267 : {
268 1461 : AssertArg(MemoryContextIsValid(context));
269 :
270 : /* Push onto head so this will be called before older registrants. */
271 1461 : cb->next = context->reset_cbs;
272 1461 : context->reset_cbs = cb;
273 : /* Mark the context as non-reset (it probably is already). */
274 1461 : context->isReset = false;
275 1461 : }
276 :
277 : /*
278 : * MemoryContextCallResetCallbacks
279 : * Internal function to call all registered callbacks for context.
280 : */
281 : static void
282 1577308 : MemoryContextCallResetCallbacks(MemoryContext context)
283 : {
284 : MemoryContextCallback *cb;
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 3156077 : while ((cb = context->reset_cbs) != NULL)
292 : {
293 1461 : context->reset_cbs = cb->next;
294 1461 : (*cb->func) (cb->arg);
295 : }
296 1577308 : }
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
317 397668 : MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
318 : {
319 397668 : AssertArg(MemoryContextIsValid(context));
320 397668 : AssertArg(context != new_parent);
321 :
322 : /* Fast path if it's got correct parent already */
323 397668 : if (new_parent == context->parent)
324 398184 : return;
325 :
326 : /* Delink from existing parent, if any */
327 397152 : if (context->parent)
328 : {
329 397152 : MemoryContext parent = context->parent;
330 :
331 397152 : if (context->prevchild != NULL)
332 32298 : context->prevchild->nextchild = context->nextchild;
333 : else
334 : {
335 364854 : Assert(parent->firstchild == context);
336 364854 : parent->firstchild = context->nextchild;
337 : }
338 :
339 397152 : if (context->nextchild != NULL)
340 213162 : context->nextchild->prevchild = context->prevchild;
341 : }
342 :
343 : /* And relink */
344 397152 : if (new_parent)
345 : {
346 8783 : AssertArg(MemoryContextIsValid(new_parent));
347 8783 : context->parent = new_parent;
348 8783 : context->prevchild = NULL;
349 8783 : context->nextchild = new_parent->firstchild;
350 8783 : if (new_parent->firstchild != NULL)
351 8258 : new_parent->firstchild->prevchild = context;
352 8783 : new_parent->firstchild = context;
353 : }
354 : else
355 : {
356 388369 : context->parent = NULL;
357 388369 : context->prevchild = NULL;
358 388369 : 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
374 12 : MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
375 : {
376 12 : AssertArg(MemoryContextIsValid(context));
377 :
378 12 : context->allowInCritSection = allow;
379 12 : }
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 2187503 : GetMemoryChunkSpace(void *pointer)
391 : {
392 2187503 : MemoryContext context = GetMemoryChunkContext(pointer);
393 :
394 2187503 : return (context->methods->get_chunk_space) (context,
395 : pointer);
396 : }
397 :
398 : /*
399 : * MemoryContextGetParent
400 : * Get the parent context (if any) of the specified context
401 : */
402 : MemoryContext
403 833 : MemoryContextGetParent(MemoryContext context)
404 : {
405 833 : AssertArg(MemoryContextIsValid(context));
406 :
407 833 : return context->parent;
408 : }
409 :
410 : /*
411 : * MemoryContextIsEmpty
412 : * Is a memory context empty of any allocated space?
413 : */
414 : bool
415 49 : MemoryContextIsEmpty(MemoryContext context)
416 : {
417 49 : AssertArg(MemoryContextIsValid(context));
418 :
419 : /*
420 : * For now, we consider a memory context nonempty if it has any children;
421 : * perhaps this should be changed later.
422 : */
423 49 : if (context->firstchild != NULL)
424 0 : return false;
425 : /* Otherwise use the type-specific inquiry */
426 49 : return (*context->methods->is_empty) (context);
427 : }
428 :
429 : /*
430 : * MemoryContextStats
431 : * Print statistics about the named context and all its descendants.
432 : *
433 : * This is just a debugging utility, so it's not very fancy. However, we do
434 : * make some effort to summarize when the output would otherwise be very long.
435 : * The statistics are sent to stderr.
436 : */
437 : void
438 0 : MemoryContextStats(MemoryContext context)
439 : {
440 : /* A hard-wired limit on the number of children is usually good enough */
441 0 : MemoryContextStatsDetail(context, 100);
442 0 : }
443 :
444 : /*
445 : * MemoryContextStatsDetail
446 : *
447 : * Entry point for use if you want to vary the number of child contexts shown.
448 : */
449 : void
450 0 : MemoryContextStatsDetail(MemoryContext context, int max_children)
451 : {
452 : MemoryContextCounters grand_totals;
453 :
454 0 : memset(&grand_totals, 0, sizeof(grand_totals));
455 :
456 0 : MemoryContextStatsInternal(context, 0, true, max_children, &grand_totals);
457 :
458 0 : fprintf(stderr,
459 : "Grand total: %zu bytes in %zd blocks; %zu free (%zd chunks); %zu used\n",
460 : grand_totals.totalspace, grand_totals.nblocks,
461 : grand_totals.freespace, grand_totals.freechunks,
462 0 : grand_totals.totalspace - grand_totals.freespace);
463 0 : }
464 :
465 : /*
466 : * MemoryContextStatsInternal
467 : * One recursion level for MemoryContextStats
468 : *
469 : * Print this context if print is true, but in any case accumulate counts into
470 : * *totals (if given).
471 : */
472 : static void
473 0 : MemoryContextStatsInternal(MemoryContext context, int level,
474 : bool print, int max_children,
475 : MemoryContextCounters *totals)
476 : {
477 : MemoryContextCounters local_totals;
478 : MemoryContext child;
479 : int ichild;
480 :
481 0 : AssertArg(MemoryContextIsValid(context));
482 :
483 : /* Examine the context itself */
484 0 : (*context->methods->stats) (context, level, print, totals);
485 :
486 : /*
487 : * Examine children. If there are more than max_children of them, we do
488 : * not print the rest explicitly, but just summarize them.
489 : */
490 0 : memset(&local_totals, 0, sizeof(local_totals));
491 :
492 0 : for (child = context->firstchild, ichild = 0;
493 : child != NULL;
494 0 : child = child->nextchild, ichild++)
495 : {
496 0 : if (ichild < max_children)
497 0 : MemoryContextStatsInternal(child, level + 1,
498 : print, max_children,
499 : totals);
500 : else
501 0 : MemoryContextStatsInternal(child, level + 1,
502 : false, max_children,
503 : &local_totals);
504 : }
505 :
506 : /* Deal with excess children */
507 0 : if (ichild > max_children)
508 : {
509 0 : if (print)
510 : {
511 : int i;
512 :
513 0 : for (i = 0; i <= level; i++)
514 0 : fprintf(stderr, " ");
515 0 : fprintf(stderr,
516 : "%d more child contexts containing %zu total in %zd blocks; %zu free (%zd chunks); %zu used\n",
517 : ichild - max_children,
518 : local_totals.totalspace,
519 : local_totals.nblocks,
520 : local_totals.freespace,
521 : local_totals.freechunks,
522 0 : local_totals.totalspace - local_totals.freespace);
523 : }
524 :
525 0 : if (totals)
526 : {
527 0 : totals->nblocks += local_totals.nblocks;
528 0 : totals->freechunks += local_totals.freechunks;
529 0 : totals->totalspace += local_totals.totalspace;
530 0 : totals->freespace += local_totals.freespace;
531 : }
532 : }
533 0 : }
534 :
535 : /*
536 : * MemoryContextCheck
537 : * Check all chunks in the named context.
538 : *
539 : * This is just a debugging utility, so it's not fancy.
540 : */
541 : #ifdef MEMORY_CONTEXT_CHECKING
542 : void
543 4687201 : MemoryContextCheck(MemoryContext context)
544 : {
545 : MemoryContext child;
546 :
547 4687201 : AssertArg(MemoryContextIsValid(context));
548 :
549 4687201 : (*context->methods->check) (context);
550 9350367 : for (child = context->firstchild; child != NULL; child = child->nextchild)
551 4663166 : MemoryContextCheck(child);
552 4687201 : }
553 : #endif
554 :
555 : /*
556 : * MemoryContextContains
557 : * Detect whether an allocated chunk of memory belongs to a given
558 : * context or not.
559 : *
560 : * Caution: this test is reliable as long as 'pointer' does point to
561 : * a chunk of memory allocated from *some* context. If 'pointer' points
562 : * at memory obtained in some other way, there is a small chance of a
563 : * false-positive result, since the bits right before it might look like
564 : * a valid chunk header by chance.
565 : */
566 : bool
567 4832 : MemoryContextContains(MemoryContext context, void *pointer)
568 : {
569 : MemoryContext ptr_context;
570 :
571 : /*
572 : * NB: Can't use GetMemoryChunkContext() here - that performs assertions
573 : * that aren't acceptable here since we might be passed memory not
574 : * allocated by any memory context.
575 : *
576 : * Try to detect bogus pointers handed to us, poorly though we can.
577 : * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
578 : * allocated chunk.
579 : */
580 4832 : if (pointer == NULL || pointer != (void *) MAXALIGN(pointer))
581 0 : return false;
582 :
583 : /*
584 : * OK, it's probably safe to look at the context.
585 : */
586 4832 : ptr_context = *(MemoryContext *) (((char *) pointer) - sizeof(void *));
587 :
588 4832 : return ptr_context == context;
589 : }
590 :
591 : /*--------------------
592 : * MemoryContextCreate
593 : * Context-type-independent part of context creation.
594 : *
595 : * This is only intended to be called by context-type-specific
596 : * context creation routines, not by the unwashed masses.
597 : *
598 : * The context creation procedure is a little bit tricky because
599 : * we want to be sure that we don't leave the context tree invalid
600 : * in case of failure (such as insufficient memory to allocate the
601 : * context node itself). The procedure goes like this:
602 : * 1. Context-type-specific routine first calls MemoryContextCreate(),
603 : * passing the appropriate tag/size/methods values (the methods
604 : * pointer will ordinarily point to statically allocated data).
605 : * The parent and name parameters usually come from the caller.
606 : * 2. MemoryContextCreate() attempts to allocate the context node,
607 : * plus space for the name. If this fails we can ereport() with no
608 : * damage done.
609 : * 3. We fill in all of the type-independent MemoryContext fields.
610 : * 4. We call the type-specific init routine (using the methods pointer).
611 : * The init routine is required to make the node minimally valid
612 : * with zero chance of failure --- it can't allocate more memory,
613 : * for example.
614 : * 5. Now we have a minimally valid node that can behave correctly
615 : * when told to reset or delete itself. We link the node to its
616 : * parent (if any), making the node part of the context tree.
617 : * 6. We return to the context-type-specific routine, which finishes
618 : * up type-specific initialization. This routine can now do things
619 : * that might fail (like allocate more memory), so long as it's
620 : * sure the node is left in a state that delete will handle.
621 : *
622 : * This protocol doesn't prevent us from leaking memory if step 6 fails
623 : * during creation of a top-level context, since there's no parent link
624 : * in that case. However, if you run out of memory while you're building
625 : * a top-level context, you might as well go home anyway...
626 : *
627 : * Normally, the context node and the name are allocated from
628 : * TopMemoryContext (NOT from the parent context, since the node must
629 : * survive resets of its parent context!). However, this routine is itself
630 : * used to create TopMemoryContext! If we see that TopMemoryContext is NULL,
631 : * we assume we are creating TopMemoryContext and use malloc() to allocate
632 : * the node.
633 : *
634 : * Note that the name field of a MemoryContext does not point to
635 : * separately-allocated storage, so it should not be freed at context
636 : * deletion.
637 : *--------------------
638 : */
639 : MemoryContext
640 420376 : MemoryContextCreate(NodeTag tag, Size size,
641 : MemoryContextMethods *methods,
642 : MemoryContext parent,
643 : const char *name)
644 : {
645 : MemoryContext node;
646 420376 : Size needed = size + strlen(name) + 1;
647 :
648 : /* creating new memory contexts is not allowed in a critical section */
649 420376 : Assert(CritSectionCount == 0);
650 :
651 : /* Get space for node and name */
652 420376 : if (TopMemoryContext != NULL)
653 : {
654 : /* Normal case: allocate the node in TopMemoryContext */
655 420370 : node = (MemoryContext) MemoryContextAlloc(TopMemoryContext,
656 : needed);
657 : }
658 : else
659 : {
660 : /* Special case for startup: use good ol' malloc */
661 6 : node = (MemoryContext) malloc(needed);
662 6 : Assert(node != NULL);
663 : }
664 :
665 : /* Initialize the node as best we can */
666 420376 : MemSet(node, 0, size);
667 420376 : node->type = tag;
668 420376 : node->methods = methods;
669 420376 : node->parent = NULL; /* for the moment */
670 420376 : node->firstchild = NULL;
671 420376 : node->prevchild = NULL;
672 420376 : node->nextchild = NULL;
673 420376 : node->isReset = true;
674 420376 : node->name = ((char *) node) + size;
675 420376 : strcpy(node->name, name);
676 :
677 : /* Type-specific routine finishes any other essential initialization */
678 420376 : (*node->methods->init) (node);
679 :
680 : /* OK to link node to parent (if any) */
681 : /* Could use MemoryContextSetParent here, but doesn't seem worthwhile */
682 420376 : if (parent)
683 : {
684 420369 : node->parent = parent;
685 420369 : node->nextchild = parent->firstchild;
686 420369 : if (parent->firstchild != NULL)
687 239151 : parent->firstchild->prevchild = node;
688 420369 : parent->firstchild = node;
689 : /* inherit allowInCritSection flag from parent */
690 420369 : node->allowInCritSection = parent->allowInCritSection;
691 : }
692 :
693 : VALGRIND_CREATE_MEMPOOL(node, 0, false);
694 :
695 : /* Return to type-specific creation routine to finish up */
696 420376 : return node;
697 : }
698 :
699 : /*
700 : * MemoryContextAlloc
701 : * Allocate space within the specified context.
702 : *
703 : * This could be turned into a macro, but we'd have to import
704 : * nodes/memnodes.h into postgres.h which seems a bad idea.
705 : */
706 : void *
707 3711632 : MemoryContextAlloc(MemoryContext context, Size size)
708 : {
709 : void *ret;
710 :
711 3711632 : AssertArg(MemoryContextIsValid(context));
712 3711632 : AssertNotInCriticalSection(context);
713 :
714 3711632 : if (!AllocSizeIsValid(size))
715 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
716 :
717 3711632 : context->isReset = false;
718 :
719 3711632 : ret = (*context->methods->alloc) (context, size);
720 3711632 : if (ret == NULL)
721 : {
722 0 : MemoryContextStats(TopMemoryContext);
723 0 : ereport(ERROR,
724 : (errcode(ERRCODE_OUT_OF_MEMORY),
725 : errmsg("out of memory"),
726 : errdetail("Failed on request of size %zu.", size)));
727 : }
728 :
729 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
730 :
731 3711632 : return ret;
732 : }
733 :
734 : /*
735 : * MemoryContextAllocZero
736 : * Like MemoryContextAlloc, but clears allocated memory
737 : *
738 : * We could just call MemoryContextAlloc then clear the memory, but this
739 : * is a very common combination, so we provide the combined operation.
740 : */
741 : void *
742 216217 : MemoryContextAllocZero(MemoryContext context, Size size)
743 : {
744 : void *ret;
745 :
746 216217 : AssertArg(MemoryContextIsValid(context));
747 216217 : AssertNotInCriticalSection(context);
748 :
749 216217 : if (!AllocSizeIsValid(size))
750 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
751 :
752 216217 : context->isReset = false;
753 :
754 216217 : ret = (*context->methods->alloc) (context, size);
755 216217 : if (ret == NULL)
756 : {
757 0 : MemoryContextStats(TopMemoryContext);
758 0 : ereport(ERROR,
759 : (errcode(ERRCODE_OUT_OF_MEMORY),
760 : errmsg("out of memory"),
761 : errdetail("Failed on request of size %zu.", size)));
762 : }
763 :
764 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
765 :
766 216217 : MemSetAligned(ret, 0, size);
767 :
768 216217 : return ret;
769 : }
770 :
771 : /*
772 : * MemoryContextAllocZeroAligned
773 : * MemoryContextAllocZero where length is suitable for MemSetLoop
774 : *
775 : * This might seem overly specialized, but it's not because newNode()
776 : * is so often called with compile-time-constant sizes.
777 : */
778 : void *
779 4187553 : MemoryContextAllocZeroAligned(MemoryContext context, Size size)
780 : {
781 : void *ret;
782 :
783 4187553 : AssertArg(MemoryContextIsValid(context));
784 4187553 : AssertNotInCriticalSection(context);
785 :
786 4187553 : if (!AllocSizeIsValid(size))
787 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
788 :
789 4187553 : context->isReset = false;
790 :
791 4187553 : ret = (*context->methods->alloc) (context, size);
792 4187553 : if (ret == NULL)
793 : {
794 0 : MemoryContextStats(TopMemoryContext);
795 0 : ereport(ERROR,
796 : (errcode(ERRCODE_OUT_OF_MEMORY),
797 : errmsg("out of memory"),
798 : errdetail("Failed on request of size %zu.", size)));
799 : }
800 :
801 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
802 :
803 4187553 : MemSetLoop(ret, 0, size);
804 :
805 4187553 : return ret;
806 : }
807 :
808 : /*
809 : * MemoryContextAllocExtended
810 : * Allocate space within the specified context using the given flags.
811 : */
812 : void *
813 1006 : MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
814 : {
815 : void *ret;
816 :
817 1006 : AssertArg(MemoryContextIsValid(context));
818 1006 : AssertNotInCriticalSection(context);
819 :
820 2012 : if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
821 1006 : ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
822 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
823 :
824 1006 : context->isReset = false;
825 :
826 1006 : ret = (*context->methods->alloc) (context, size);
827 1006 : if (ret == NULL)
828 : {
829 0 : if ((flags & MCXT_ALLOC_NO_OOM) == 0)
830 : {
831 0 : MemoryContextStats(TopMemoryContext);
832 0 : ereport(ERROR,
833 : (errcode(ERRCODE_OUT_OF_MEMORY),
834 : errmsg("out of memory"),
835 : errdetail("Failed on request of size %zu.", size)));
836 : }
837 0 : return NULL;
838 : }
839 :
840 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
841 :
842 1006 : if ((flags & MCXT_ALLOC_ZERO) != 0)
843 1006 : MemSetAligned(ret, 0, size);
844 :
845 1006 : return ret;
846 : }
847 :
848 : void *
849 19558863 : palloc(Size size)
850 : {
851 : /* duplicates MemoryContextAlloc to avoid increased overhead */
852 : void *ret;
853 :
854 19558863 : AssertArg(MemoryContextIsValid(CurrentMemoryContext));
855 19558863 : AssertNotInCriticalSection(CurrentMemoryContext);
856 :
857 19558863 : if (!AllocSizeIsValid(size))
858 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
859 :
860 19558863 : CurrentMemoryContext->isReset = false;
861 :
862 19558863 : ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
863 19558863 : if (ret == NULL)
864 : {
865 0 : MemoryContextStats(TopMemoryContext);
866 0 : ereport(ERROR,
867 : (errcode(ERRCODE_OUT_OF_MEMORY),
868 : errmsg("out of memory"),
869 : errdetail("Failed on request of size %zu.", size)));
870 : }
871 :
872 : VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
873 :
874 19558863 : return ret;
875 : }
876 :
877 : void *
878 5005320 : palloc0(Size size)
879 : {
880 : /* duplicates MemoryContextAllocZero to avoid increased overhead */
881 : void *ret;
882 :
883 5005320 : AssertArg(MemoryContextIsValid(CurrentMemoryContext));
884 5005320 : AssertNotInCriticalSection(CurrentMemoryContext);
885 :
886 5005320 : if (!AllocSizeIsValid(size))
887 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
888 :
889 5005320 : CurrentMemoryContext->isReset = false;
890 :
891 5005320 : ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
892 5005320 : if (ret == NULL)
893 : {
894 0 : MemoryContextStats(TopMemoryContext);
895 0 : ereport(ERROR,
896 : (errcode(ERRCODE_OUT_OF_MEMORY),
897 : errmsg("out of memory"),
898 : errdetail("Failed on request of size %zu.", size)));
899 : }
900 :
901 : VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
902 :
903 5005320 : MemSetAligned(ret, 0, size);
904 :
905 5005320 : return ret;
906 : }
907 :
908 : void *
909 36 : palloc_extended(Size size, int flags)
910 : {
911 : /* duplicates MemoryContextAllocExtended to avoid increased overhead */
912 : void *ret;
913 :
914 36 : AssertArg(MemoryContextIsValid(CurrentMemoryContext));
915 36 : AssertNotInCriticalSection(CurrentMemoryContext);
916 :
917 72 : if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
918 72 : ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
919 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
920 :
921 36 : CurrentMemoryContext->isReset = false;
922 :
923 36 : ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
924 36 : if (ret == NULL)
925 : {
926 0 : if ((flags & MCXT_ALLOC_NO_OOM) == 0)
927 : {
928 0 : MemoryContextStats(TopMemoryContext);
929 0 : ereport(ERROR,
930 : (errcode(ERRCODE_OUT_OF_MEMORY),
931 : errmsg("out of memory"),
932 : errdetail("Failed on request of size %zu.", size)));
933 : }
934 0 : return NULL;
935 : }
936 :
937 : VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
938 :
939 36 : if ((flags & MCXT_ALLOC_ZERO) != 0)
940 9 : MemSetAligned(ret, 0, size);
941 :
942 36 : return ret;
943 : }
944 :
945 : /*
946 : * pfree
947 : * Release an allocated chunk.
948 : */
949 : void
950 10720411 : pfree(void *pointer)
951 : {
952 10720411 : MemoryContext context = GetMemoryChunkContext(pointer);
953 :
954 10720411 : (*context->methods->free_p) (context, pointer);
955 : VALGRIND_MEMPOOL_FREE(context, pointer);
956 10720411 : }
957 :
958 : /*
959 : * repalloc
960 : * Adjust the size of a previously allocated chunk.
961 : */
962 : void *
963 61990 : repalloc(void *pointer, Size size)
964 : {
965 61990 : MemoryContext context = GetMemoryChunkContext(pointer);
966 : void *ret;
967 :
968 61990 : if (!AllocSizeIsValid(size))
969 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
970 :
971 61990 : AssertNotInCriticalSection(context);
972 :
973 : /* isReset must be false already */
974 61990 : Assert(!context->isReset);
975 :
976 61990 : ret = (*context->methods->realloc) (context, pointer, size);
977 61990 : if (ret == NULL)
978 : {
979 0 : MemoryContextStats(TopMemoryContext);
980 0 : ereport(ERROR,
981 : (errcode(ERRCODE_OUT_OF_MEMORY),
982 : errmsg("out of memory"),
983 : errdetail("Failed on request of size %zu.", size)));
984 : }
985 :
986 : VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
987 :
988 61990 : return ret;
989 : }
990 :
991 : /*
992 : * MemoryContextAllocHuge
993 : * Allocate (possibly-expansive) space within the specified context.
994 : *
995 : * See considerations in comment at MaxAllocHugeSize.
996 : */
997 : void *
998 0 : MemoryContextAllocHuge(MemoryContext context, Size size)
999 : {
1000 : void *ret;
1001 :
1002 0 : AssertArg(MemoryContextIsValid(context));
1003 0 : AssertNotInCriticalSection(context);
1004 :
1005 0 : if (!AllocHugeSizeIsValid(size))
1006 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
1007 :
1008 0 : context->isReset = false;
1009 :
1010 0 : ret = (*context->methods->alloc) (context, size);
1011 0 : if (ret == NULL)
1012 : {
1013 0 : MemoryContextStats(TopMemoryContext);
1014 0 : ereport(ERROR,
1015 : (errcode(ERRCODE_OUT_OF_MEMORY),
1016 : errmsg("out of memory"),
1017 : errdetail("Failed on request of size %zu.", size)));
1018 : }
1019 :
1020 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1021 :
1022 0 : return ret;
1023 : }
1024 :
1025 : /*
1026 : * repalloc_huge
1027 : * Adjust the size of a previously allocated chunk, permitting a large
1028 : * value. The previous allocation need not have been "huge".
1029 : */
1030 : void *
1031 3880 : repalloc_huge(void *pointer, Size size)
1032 : {
1033 3880 : MemoryContext context = GetMemoryChunkContext(pointer);
1034 : void *ret;
1035 :
1036 3880 : if (!AllocHugeSizeIsValid(size))
1037 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
1038 :
1039 3880 : AssertNotInCriticalSection(context);
1040 :
1041 : /* isReset must be false already */
1042 3880 : Assert(!context->isReset);
1043 :
1044 3880 : ret = (*context->methods->realloc) (context, pointer, size);
1045 3880 : if (ret == NULL)
1046 : {
1047 0 : MemoryContextStats(TopMemoryContext);
1048 0 : ereport(ERROR,
1049 : (errcode(ERRCODE_OUT_OF_MEMORY),
1050 : errmsg("out of memory"),
1051 : errdetail("Failed on request of size %zu.", size)));
1052 : }
1053 :
1054 : VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1055 :
1056 3880 : return ret;
1057 : }
1058 :
1059 : /*
1060 : * MemoryContextStrdup
1061 : * Like strdup(), but allocate from the specified context
1062 : */
1063 : char *
1064 1049299 : MemoryContextStrdup(MemoryContext context, const char *string)
1065 : {
1066 : char *nstr;
1067 1049299 : Size len = strlen(string) + 1;
1068 :
1069 1049299 : nstr = (char *) MemoryContextAlloc(context, len);
1070 :
1071 1049299 : memcpy(nstr, string, len);
1072 :
1073 1049299 : return nstr;
1074 : }
1075 :
1076 : char *
1077 1042317 : pstrdup(const char *in)
1078 : {
1079 1042317 : return MemoryContextStrdup(CurrentMemoryContext, in);
1080 : }
1081 :
1082 : /*
1083 : * pnstrdup
1084 : * Like pstrdup(), but append null byte to a
1085 : * not-necessarily-null-terminated input string.
1086 : */
1087 : char *
1088 8220 : pnstrdup(const char *in, Size len)
1089 : {
1090 8220 : char *out = palloc(len + 1);
1091 :
1092 8220 : memcpy(out, in, len);
1093 8220 : out[len] = '\0';
1094 8220 : return out;
1095 : }
1096 :
1097 : /*
1098 : * Make copy of string with all trailing newline characters removed.
1099 : */
1100 : char *
1101 0 : pchomp(const char *in)
1102 : {
1103 : size_t n;
1104 :
1105 0 : n = strlen(in);
1106 0 : while (n > 0 && in[n - 1] == '\n')
1107 0 : n--;
1108 0 : return pnstrdup(in, n);
1109 : }
|