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 27007516 : MemoryContextReset(MemoryContext context)
136 : {
137 27007516 : AssertArg(MemoryContextIsValid(context));
138 :
139 : /* save a function call in common case where there are no children */
140 27007516 : if (context->firstchild != NULL)
141 1366 : MemoryContextDeleteChildren(context);
142 :
143 : /* save a function call if no pallocs since startup or last reset */
144 27007516 : if (!context->isReset)
145 1258443 : MemoryContextResetOnly(context);
146 27007516 : }
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 1258443 : MemoryContextResetOnly(MemoryContext context)
155 : {
156 1258443 : AssertArg(MemoryContextIsValid(context));
157 :
158 : /* Nothing to do if no pallocs since startup or last reset */
159 1258443 : if (!context->isReset)
160 : {
161 1258443 : MemoryContextCallResetCallbacks(context);
162 1258443 : (*context->methods->reset) (context);
163 1258443 : context->isReset = true;
164 : VALGRIND_DESTROY_MEMPOOL(context);
165 : VALGRIND_CREATE_MEMPOOL(context, 0, false);
166 : }
167 1258443 : }
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 387615 : MemoryContextDelete(MemoryContext context)
201 : {
202 387615 : AssertArg(MemoryContextIsValid(context));
203 : /* We had better not be deleting TopMemoryContext ... */
204 387615 : Assert(context != TopMemoryContext);
205 : /* And not CurrentMemoryContext, either */
206 387615 : Assert(context != CurrentMemoryContext);
207 :
208 387615 : 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 387615 : 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 387615 : MemoryContextSetParent(context, NULL);
224 :
225 387615 : (*context->methods->delete_context) (context);
226 : VALGRIND_DESTROY_MEMPOOL(context);
227 387615 : pfree(context);
228 387615 : }
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 404695 : MemoryContextDeleteChildren(MemoryContext context)
237 : {
238 404695 : 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 837931 : while (context->firstchild != NULL)
245 28541 : MemoryContextDelete(context->firstchild);
246 404695 : }
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 1646058 : 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 3293577 : while ((cb = context->reset_cbs) != NULL)
292 : {
293 1461 : context->reset_cbs = cb->next;
294 1461 : (*cb->func) (cb->arg);
295 : }
296 1646058 : }
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 397182 : MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
318 : {
319 397182 : AssertArg(MemoryContextIsValid(context));
320 397182 : AssertArg(context != new_parent);
321 :
322 : /* Fast path if it's got correct parent already */
323 397182 : if (new_parent == context->parent)
324 397698 : return;
325 :
326 : /* Delink from existing parent, if any */
327 396666 : if (context->parent)
328 : {
329 396666 : MemoryContext parent = context->parent;
330 :
331 396666 : if (context->prevchild != NULL)
332 31229 : context->prevchild->nextchild = context->nextchild;
333 : else
334 : {
335 365437 : Assert(parent->firstchild == context);
336 365437 : parent->firstchild = context->nextchild;
337 : }
338 :
339 396666 : if (context->nextchild != NULL)
340 212277 : context->nextchild->prevchild = context->prevchild;
341 : }
342 :
343 : /* And relink */
344 396666 : if (new_parent)
345 : {
346 9051 : AssertArg(MemoryContextIsValid(new_parent));
347 9051 : context->parent = new_parent;
348 9051 : context->prevchild = NULL;
349 9051 : context->nextchild = new_parent->firstchild;
350 9051 : if (new_parent->firstchild != NULL)
351 8440 : new_parent->firstchild->prevchild = context;
352 9051 : new_parent->firstchild = context;
353 : }
354 : else
355 : {
356 387615 : context->parent = NULL;
357 387615 : context->prevchild = NULL;
358 387615 : 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 2187689 : GetMemoryChunkSpace(void *pointer)
391 : {
392 2187689 : MemoryContext context = GetMemoryChunkContext(pointer);
393 :
394 2187689 : 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 4744944 : MemoryContextCheck(MemoryContext context)
544 : {
545 : MemoryContext child;
546 :
547 4744944 : AssertArg(MemoryContextIsValid(context));
548 :
549 4744944 : (*context->methods->check) (context);
550 9465810 : for (child = context->firstchild; child != NULL; child = child->nextchild)
551 4720866 : MemoryContextCheck(child);
552 4744944 : }
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 4850 : 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 4850 : 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 4850 : ptr_context = *(MemoryContext *) (((char *) pointer) - sizeof(void *));
587 :
588 4850 : 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 420358 : MemoryContextCreate(NodeTag tag, Size size,
641 : MemoryContextMethods *methods,
642 : MemoryContext parent,
643 : const char *name)
644 : {
645 : MemoryContext node;
646 420358 : Size needed = size + strlen(name) + 1;
647 :
648 : /* creating new memory contexts is not allowed in a critical section */
649 420358 : Assert(CritSectionCount == 0);
650 :
651 : /* Get space for node and name */
652 420358 : if (TopMemoryContext != NULL)
653 : {
654 : /* Normal case: allocate the node in TopMemoryContext */
655 420352 : 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 420358 : MemSet(node, 0, size);
667 420358 : node->type = tag;
668 420358 : node->methods = methods;
669 420358 : node->parent = NULL; /* for the moment */
670 420358 : node->firstchild = NULL;
671 420358 : node->prevchild = NULL;
672 420358 : node->nextchild = NULL;
673 420358 : node->isReset = true;
674 420358 : node->name = ((char *) node) + size;
675 420358 : strcpy(node->name, name);
676 :
677 : /* Type-specific routine finishes any other essential initialization */
678 420358 : (*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 420358 : if (parent)
683 : {
684 420351 : node->parent = parent;
685 420351 : node->nextchild = parent->firstchild;
686 420351 : if (parent->firstchild != NULL)
687 238837 : parent->firstchild->prevchild = node;
688 420351 : parent->firstchild = node;
689 : /* inherit allowInCritSection flag from parent */
690 420351 : 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 420358 : 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 3717941 : MemoryContextAlloc(MemoryContext context, Size size)
708 : {
709 : void *ret;
710 :
711 3717941 : AssertArg(MemoryContextIsValid(context));
712 3717941 : AssertNotInCriticalSection(context);
713 :
714 3717941 : if (!AllocSizeIsValid(size))
715 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
716 :
717 3717941 : context->isReset = false;
718 :
719 3717941 : ret = (*context->methods->alloc) (context, size);
720 3717941 : 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 3717941 : 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 216326 : MemoryContextAllocZero(MemoryContext context, Size size)
743 : {
744 : void *ret;
745 :
746 216326 : AssertArg(MemoryContextIsValid(context));
747 216326 : AssertNotInCriticalSection(context);
748 :
749 216326 : if (!AllocSizeIsValid(size))
750 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
751 :
752 216326 : context->isReset = false;
753 :
754 216326 : ret = (*context->methods->alloc) (context, size);
755 216326 : 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 216326 : MemSetAligned(ret, 0, size);
767 :
768 216326 : 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 4196948 : MemoryContextAllocZeroAligned(MemoryContext context, Size size)
780 : {
781 : void *ret;
782 :
783 4196948 : AssertArg(MemoryContextIsValid(context));
784 4196948 : AssertNotInCriticalSection(context);
785 :
786 4196948 : if (!AllocSizeIsValid(size))
787 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
788 :
789 4196948 : context->isReset = false;
790 :
791 4196948 : ret = (*context->methods->alloc) (context, size);
792 4196948 : 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 4196948 : MemSetLoop(ret, 0, size);
804 :
805 4196948 : return ret;
806 : }
807 :
808 : /*
809 : * MemoryContextAllocExtended
810 : * Allocate space within the specified context using the given flags.
811 : */
812 : void *
813 1008 : MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
814 : {
815 : void *ret;
816 :
817 1008 : AssertArg(MemoryContextIsValid(context));
818 1008 : AssertNotInCriticalSection(context);
819 :
820 2016 : if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
821 1008 : ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
822 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
823 :
824 1008 : context->isReset = false;
825 :
826 1008 : ret = (*context->methods->alloc) (context, size);
827 1008 : 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 1008 : if ((flags & MCXT_ALLOC_ZERO) != 0)
843 1008 : MemSetAligned(ret, 0, size);
844 :
845 1008 : return ret;
846 : }
847 :
848 : void *
849 19840459 : palloc(Size size)
850 : {
851 : /* duplicates MemoryContextAlloc to avoid increased overhead */
852 : void *ret;
853 :
854 19840459 : AssertArg(MemoryContextIsValid(CurrentMemoryContext));
855 19840459 : AssertNotInCriticalSection(CurrentMemoryContext);
856 :
857 19840459 : if (!AllocSizeIsValid(size))
858 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
859 :
860 19840459 : CurrentMemoryContext->isReset = false;
861 :
862 19840459 : ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
863 19840459 : 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 19840459 : return ret;
875 : }
876 :
877 : void *
878 5130792 : palloc0(Size size)
879 : {
880 : /* duplicates MemoryContextAllocZero to avoid increased overhead */
881 : void *ret;
882 :
883 5130792 : AssertArg(MemoryContextIsValid(CurrentMemoryContext));
884 5130792 : AssertNotInCriticalSection(CurrentMemoryContext);
885 :
886 5130792 : if (!AllocSizeIsValid(size))
887 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
888 :
889 5130792 : CurrentMemoryContext->isReset = false;
890 :
891 5130792 : ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
892 5130792 : 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 5130792 : MemSetAligned(ret, 0, size);
904 :
905 5130792 : 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 10726987 : pfree(void *pointer)
951 : {
952 10726987 : MemoryContext context = GetMemoryChunkContext(pointer);
953 :
954 10726987 : (*context->methods->free_p) (context, pointer);
955 : VALGRIND_MEMPOOL_FREE(context, pointer);
956 10726987 : }
957 :
958 : /*
959 : * repalloc
960 : * Adjust the size of a previously allocated chunk.
961 : */
962 : void *
963 62489 : repalloc(void *pointer, Size size)
964 : {
965 62489 : MemoryContext context = GetMemoryChunkContext(pointer);
966 : void *ret;
967 :
968 62489 : if (!AllocSizeIsValid(size))
969 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
970 :
971 62489 : AssertNotInCriticalSection(context);
972 :
973 : /* isReset must be false already */
974 62489 : Assert(!context->isReset);
975 :
976 62489 : ret = (*context->methods->realloc) (context, pointer, size);
977 62489 : 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 62489 : 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 1051827 : MemoryContextStrdup(MemoryContext context, const char *string)
1065 : {
1066 : char *nstr;
1067 1051827 : Size len = strlen(string) + 1;
1068 :
1069 1051827 : nstr = (char *) MemoryContextAlloc(context, len);
1070 :
1071 1051827 : memcpy(nstr, string, len);
1072 :
1073 1051827 : return nstr;
1074 : }
1075 :
1076 : char *
1077 1044849 : pstrdup(const char *in)
1078 : {
1079 1044849 : 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 9744 : pnstrdup(const char *in, Size len)
1089 : {
1090 9744 : char *out = palloc(len + 1);
1091 :
1092 9744 : memcpy(out, in, len);
1093 9744 : out[len] = '\0';
1094 9744 : 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 : }
|