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