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 main loop iteration of a process */
49 MemoryContext CacheMemoryContext = NULL;
50 MemoryContext MessageContext = NULL;
51 MemoryContext QueryContext = NULL;
52
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
MemoryContextInit(void)89 MemoryContextInit(void)
90 {
91 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 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 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 ErrorContext = AllocSetContextCreate(TopMemoryContext,
122 "ErrorContext",
123 8 * 1024,
124 8 * 1024,
125 8 * 1024);
126 MemoryContextAllowInCriticalSection(ErrorContext, true);
127 }
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
MemoryContextReset(MemoryContext context)135 MemoryContextReset(MemoryContext context)
136 {
137 AssertArg(MemoryContextIsValid(context));
138
139 /* save a function call in common case where there are no children */
140 if (context->firstchild != NULL)
141 MemoryContextDeleteChildren(context);
142
143 /* save a function call if no pallocs since startup or last reset */
144 if (!context->isReset)
145 MemoryContextResetOnly(context);
146 }
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
MemoryContextResetOnly(MemoryContext context)154 MemoryContextResetOnly(MemoryContext context)
155 {
156 AssertArg(MemoryContextIsValid(context));
157
158 /* Nothing to do if no pallocs since startup or last reset */
159 if (!context->isReset)
160 {
161 MemoryContextCallResetCallbacks(context);
162 (*context->methods->reset) (context);
163 context->isReset = true;
164 VALGRIND_DESTROY_MEMPOOL(context);
165 VALGRIND_CREATE_MEMPOOL(context, 0, false);
166 }
167 }
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
MemoryContextResetChildren(MemoryContext context)176 MemoryContextResetChildren(MemoryContext context)
177 {
178 MemoryContext child;
179
180 AssertArg(MemoryContextIsValid(context));
181
182 for (child = context->firstchild; child != NULL; child = child->nextchild)
183 {
184 MemoryContextResetChildren(child);
185 MemoryContextResetOnly(child);
186 }
187 }
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
MemoryContextDelete(MemoryContext context)200 MemoryContextDelete(MemoryContext context)
201 {
202 AssertArg(MemoryContextIsValid(context));
203 /* We had better not be deleting TopMemoryContext ... */
204 Assert(context != TopMemoryContext);
205 /* And not CurrentMemoryContext, either */
206 Assert(context != CurrentMemoryContext);
207
208 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 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 MemoryContextSetParent(context, NULL);
224
225 (*context->methods->delete_context) (context);
226 VALGRIND_DESTROY_MEMPOOL(context);
227 pfree(context);
228 }
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
MemoryContextDeleteChildren(MemoryContext context)236 MemoryContextDeleteChildren(MemoryContext context)
237 {
238 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 while (context->firstchild != NULL)
245 MemoryContextDelete(context->firstchild);
246 }
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
MemoryContextRegisterResetCallback(MemoryContext context,MemoryContextCallback * cb)265 MemoryContextRegisterResetCallback(MemoryContext context,
266 MemoryContextCallback *cb)
267 {
268 AssertArg(MemoryContextIsValid(context));
269
270 /* Push onto head so this will be called before older registrants. */
271 cb->next = context->reset_cbs;
272 context->reset_cbs = cb;
273 /* Mark the context as non-reset (it probably is already). */
274 context->isReset = false;
275 }
276
277 /*
278 * MemoryContextCallResetCallbacks
279 * Internal function to call all registered callbacks for context.
280 */
281 static void
MemoryContextCallResetCallbacks(MemoryContext context)282 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 while ((cb = context->reset_cbs) != NULL)
292 {
293 context->reset_cbs = cb->next;
294 (*cb->func) (cb->arg);
295 }
296 }
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
MemoryContextSetParent(MemoryContext context,MemoryContext new_parent)317 MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
318 {
319 AssertArg(MemoryContextIsValid(context));
320 AssertArg(context != new_parent);
321
322 /* Fast path if it's got correct parent already */
323 if (new_parent == context->parent)
324 return;
325
326 /* Delink from existing parent, if any */
327 if (context->parent)
328 {
329 MemoryContext parent = context->parent;
330
331 if (context->prevchild != NULL)
332 context->prevchild->nextchild = context->nextchild;
333 else
334 {
335 Assert(parent->firstchild == context);
336 parent->firstchild = context->nextchild;
337 }
338
339 if (context->nextchild != NULL)
340 context->nextchild->prevchild = context->prevchild;
341 }
342
343 /* And relink */
344 if (new_parent)
345 {
346 AssertArg(MemoryContextIsValid(new_parent));
347 context->parent = new_parent;
348 context->prevchild = NULL;
349 context->nextchild = new_parent->firstchild;
350 if (new_parent->firstchild != NULL)
351 new_parent->firstchild->prevchild = context;
352 new_parent->firstchild = context;
353 }
354 else
355 {
356 context->parent = NULL;
357 context->prevchild = NULL;
358 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
MemoryContextAllowInCriticalSection(MemoryContext context,bool allow)374 MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
375 {
376 AssertArg(MemoryContextIsValid(context));
377
378 context->allowInCritSection = allow;
379 }
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
GetMemoryChunkSpace(void * pointer)390 GetMemoryChunkSpace(void *pointer)
391 {
392 MemoryContext context = GetMemoryChunkContext(pointer);
393
394 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
MemoryContextGetParent(MemoryContext context)403 MemoryContextGetParent(MemoryContext context)
404 {
405 AssertArg(MemoryContextIsValid(context));
406
407 return context->parent;
408 }
409
410 /*
411 * MemoryContextIsEmpty
412 * Is a memory context empty of any allocated space?
413 */
414 bool
MemoryContextIsEmpty(MemoryContext context)415 MemoryContextIsEmpty(MemoryContext context)
416 {
417 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 if (context->firstchild != NULL)
424 return false;
425 /* Otherwise use the type-specific inquiry */
426 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
MemoryContextStats(MemoryContext context)438 MemoryContextStats(MemoryContext context)
439 {
440 /* A hard-wired limit on the number of children is usually good enough */
441 MemoryContextStatsDetail(context, 100);
442 }
443
444 /*
445 * MemoryContextStatsDetail
446 *
447 * Entry point for use if you want to vary the number of child contexts shown.
448 */
449 void
MemoryContextStatsDetail(MemoryContext context,int max_children)450 MemoryContextStatsDetail(MemoryContext context, int max_children)
451 {
452 MemoryContextCounters grand_totals;
453
454 memset(&grand_totals, 0, sizeof(grand_totals));
455
456 MemoryContextStatsInternal(context, 0, true, max_children, &grand_totals);
457
458 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 grand_totals.totalspace - grand_totals.freespace);
463 }
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
MemoryContextStatsInternal(MemoryContext context,int level,bool print,int max_children,MemoryContextCounters * totals)473 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 AssertArg(MemoryContextIsValid(context));
482
483 /* Examine the context itself */
484 (*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 memset(&local_totals, 0, sizeof(local_totals));
491
492 for (child = context->firstchild, ichild = 0;
493 child != NULL;
494 child = child->nextchild, ichild++)
495 {
496 if (ichild < max_children)
497 MemoryContextStatsInternal(child, level + 1,
498 print, max_children,
499 totals);
500 else
501 MemoryContextStatsInternal(child, level + 1,
502 false, max_children,
503 &local_totals);
504 }
505
506 /* Deal with excess children */
507 if (ichild > max_children)
508 {
509 if (print)
510 {
511 int i;
512
513 for (i = 0; i <= level; i++)
514 fprintf(stderr, " ");
515 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 local_totals.totalspace - local_totals.freespace);
523 }
524
525 if (totals)
526 {
527 totals->nblocks += local_totals.nblocks;
528 totals->freechunks += local_totals.freechunks;
529 totals->totalspace += local_totals.totalspace;
530 totals->freespace += local_totals.freespace;
531 }
532 }
533 }
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
MemoryContextCheck(MemoryContext context)543 MemoryContextCheck(MemoryContext context)
544 {
545 MemoryContext child;
546
547 AssertArg(MemoryContextIsValid(context));
548
549 (*context->methods->check) (context);
550 for (child = context->firstchild; child != NULL; child = child->nextchild)
551 MemoryContextCheck(child);
552 }
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
MemoryContextContains(MemoryContext context,void * pointer)567 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 if (pointer == NULL || pointer != (void *) MAXALIGN(pointer))
581 return false;
582
583 /*
584 * OK, it's probably safe to look at the context.
585 */
586 ptr_context = *(MemoryContext *) (((char *) pointer) - sizeof(void *));
587
588 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
MemoryContextCreate(NodeTag tag,Size size,MemoryContextMethods * methods,MemoryContext parent,const char * name)640 MemoryContextCreate(NodeTag tag, Size size,
641 MemoryContextMethods *methods,
642 MemoryContext parent,
643 const char *name)
644 {
645 MemoryContext node;
646 Size needed = size + strlen(name) + 1;
647
648 /* creating new memory contexts is not allowed in a critical section */
649 Assert(CritSectionCount == 0);
650
651 /* Get space for node and name */
652 if (TopMemoryContext != NULL)
653 {
654 /* Normal case: allocate the node in TopMemoryContext */
655 node = (MemoryContext) MemoryContextAlloc(TopMemoryContext,
656 needed);
657 }
658 else
659 {
660 /* Special case for startup: use good ol' malloc */
661 node = (MemoryContext) malloc(needed);
662 Assert(node != NULL);
663 }
664
665 /* Initialize the node as best we can */
666 MemSet(node, 0, size);
667 node->type = tag;
668 node->methods = methods;
669 node->parent = NULL; /* for the moment */
670 node->firstchild = NULL;
671 node->prevchild = NULL;
672 node->nextchild = NULL;
673 node->isReset = true;
674 node->name = ((char *) node) + size;
675 strcpy(node->name, name);
676
677 /* Type-specific routine finishes any other essential initialization */
678 (*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 if (parent)
683 {
684 node->parent = parent;
685 node->nextchild = parent->firstchild;
686 if (parent->firstchild != NULL)
687 parent->firstchild->prevchild = node;
688 parent->firstchild = node;
689 /* inherit allowInCritSection flag from parent */
690 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 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 *
MemoryContextAlloc(MemoryContext context,Size size)707 MemoryContextAlloc(MemoryContext context, Size size)
708 {
709 void *ret;
710
711 AssertArg(MemoryContextIsValid(context));
712 AssertNotInCriticalSection(context);
713
714 if (!AllocSizeIsValid(size))
715 elog(ERROR, "invalid memory alloc request size %zu", size);
716
717 context->isReset = false;
718
719 ret = (*context->methods->alloc) (context, size);
720 if (ret == NULL)
721 {
722 MemoryContextStats(TopMemoryContext);
723 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 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 *
MemoryContextAllocZero(MemoryContext context,Size size)742 MemoryContextAllocZero(MemoryContext context, Size size)
743 {
744 void *ret;
745
746 AssertArg(MemoryContextIsValid(context));
747 AssertNotInCriticalSection(context);
748
749 if (!AllocSizeIsValid(size))
750 elog(ERROR, "invalid memory alloc request size %zu", size);
751
752 context->isReset = false;
753
754 ret = (*context->methods->alloc) (context, size);
755 if (ret == NULL)
756 {
757 MemoryContextStats(TopMemoryContext);
758 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 MemSetAligned(ret, 0, size);
767
768 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 *
MemoryContextAllocZeroAligned(MemoryContext context,Size size)779 MemoryContextAllocZeroAligned(MemoryContext context, Size size)
780 {
781 void *ret;
782
783 AssertArg(MemoryContextIsValid(context));
784 AssertNotInCriticalSection(context);
785
786 if (!AllocSizeIsValid(size))
787 elog(ERROR, "invalid memory alloc request size %zu", size);
788
789 context->isReset = false;
790
791 ret = (*context->methods->alloc) (context, size);
792 if (ret == NULL)
793 {
794 MemoryContextStats(TopMemoryContext);
795 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 MemSetLoop(ret, 0, size);
804
805 return ret;
806 }
807
808 /*
809 * MemoryContextAllocExtended
810 * Allocate space within the specified context using the given flags.
811 */
812 void *
MemoryContextAllocExtended(MemoryContext context,Size size,int flags)813 MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
814 {
815 void *ret;
816
817 AssertArg(MemoryContextIsValid(context));
818 AssertNotInCriticalSection(context);
819
820 if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
821 ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
822 elog(ERROR, "invalid memory alloc request size %zu", size);
823
824 context->isReset = false;
825
826 ret = (*context->methods->alloc) (context, size);
827 if (ret == NULL)
828 {
829 if ((flags & MCXT_ALLOC_NO_OOM) == 0)
830 {
831 MemoryContextStats(TopMemoryContext);
832 ereport(ERROR,
833 (errcode(ERRCODE_OUT_OF_MEMORY),
834 errmsg("out of memory"),
835 errdetail("Failed on request of size %zu.", size)));
836 }
837 return NULL;
838 }
839
840 VALGRIND_MEMPOOL_ALLOC(context, ret, size);
841
842 if ((flags & MCXT_ALLOC_ZERO) != 0)
843 MemSetAligned(ret, 0, size);
844
845 return ret;
846 }
847
848 void *
palloc(Size size)849 palloc(Size size)
850 {
851 /* duplicates MemoryContextAlloc to avoid increased overhead */
852 void *ret;
853
854 AssertArg(MemoryContextIsValid(CurrentMemoryContext));
855 AssertNotInCriticalSection(CurrentMemoryContext);
856
857 if (!AllocSizeIsValid(size))
858 elog(ERROR, "invalid memory alloc request size %zu", size);
859
860 CurrentMemoryContext->isReset = false;
861
862 ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
863 if (ret == NULL)
864 {
865 MemoryContextStats(TopMemoryContext);
866 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 return ret;
875 }
876
877 void *
palloc0(Size size)878 palloc0(Size size)
879 {
880 /* duplicates MemoryContextAllocZero to avoid increased overhead */
881 void *ret;
882
883 AssertArg(MemoryContextIsValid(CurrentMemoryContext));
884 AssertNotInCriticalSection(CurrentMemoryContext);
885
886 if (!AllocSizeIsValid(size))
887 elog(ERROR, "invalid memory alloc request size %zu", size);
888
889 CurrentMemoryContext->isReset = false;
890
891 ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
892 if (ret == NULL)
893 {
894 MemoryContextStats(TopMemoryContext);
895 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 MemSetAligned(ret, 0, size);
904
905 return ret;
906 }
907
908 void *
palloc_extended(Size size,int flags)909 palloc_extended(Size size, int flags)
910 {
911 /* duplicates MemoryContextAllocExtended to avoid increased overhead */
912 void *ret;
913
914 AssertArg(MemoryContextIsValid(CurrentMemoryContext));
915 AssertNotInCriticalSection(CurrentMemoryContext);
916
917 if (((flags & MCXT_ALLOC_HUGE) != 0 && !AllocHugeSizeIsValid(size)) ||
918 ((flags & MCXT_ALLOC_HUGE) == 0 && !AllocSizeIsValid(size)))
919 elog(ERROR, "invalid memory alloc request size %zu", size);
920
921 CurrentMemoryContext->isReset = false;
922
923 ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
924 if (ret == NULL)
925 {
926 if ((flags & MCXT_ALLOC_NO_OOM) == 0)
927 {
928 MemoryContextStats(TopMemoryContext);
929 ereport(ERROR,
930 (errcode(ERRCODE_OUT_OF_MEMORY),
931 errmsg("out of memory"),
932 errdetail("Failed on request of size %zu.", size)));
933 }
934 return NULL;
935 }
936
937 VALGRIND_MEMPOOL_ALLOC(CurrentMemoryContext, ret, size);
938
939 if ((flags & MCXT_ALLOC_ZERO) != 0)
940 MemSetAligned(ret, 0, size);
941
942 return ret;
943 }
944
945 /*
946 * pfree
947 * Release an allocated chunk.
948 */
949 void
pfree(void * pointer)950 pfree(void *pointer)
951 {
952 MemoryContext context = GetMemoryChunkContext(pointer);
953
954 (*context->methods->free_p) (context, pointer);
955 VALGRIND_MEMPOOL_FREE(context, pointer);
956 }
957
958 /*
959 * repalloc
960 * Adjust the size of a previously allocated chunk.
961 */
962 void *
repalloc(void * pointer,Size size)963 repalloc(void *pointer, Size size)
964 {
965 MemoryContext context;
966 void *ret;
967
968 if (!AllocSizeIsValid(size))
969 elog(ERROR, "invalid memory alloc request size %zu", size);
970
971 /* pgpool hack by Muhammad Usama <m.usama@gmail.com> */
972 if(pointer == NULL)
973 return palloc(size);
974
975 context = GetMemoryChunkContext(pointer);
976
977 AssertNotInCriticalSection(context);
978
979 /* isReset must be false already */
980 Assert(!context->isReset);
981
982 ret = (*context->methods->realloc) (context, pointer, size);
983 if (ret == NULL)
984 {
985 MemoryContextStats(TopMemoryContext);
986 ereport(ERROR,
987 (errcode(ERRCODE_OUT_OF_MEMORY),
988 errmsg("out of memory"),
989 errdetail("Failed on request of size %zu.", size)));
990 }
991
992 VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
993
994 return ret;
995 }
996
997 /*
998 * MemoryContextAllocHuge
999 * Allocate (possibly-expansive) space within the specified context.
1000 *
1001 * See considerations in comment at MaxAllocHugeSize.
1002 */
1003 void *
MemoryContextAllocHuge(MemoryContext context,Size size)1004 MemoryContextAllocHuge(MemoryContext context, Size size)
1005 {
1006 void *ret;
1007
1008 AssertArg(MemoryContextIsValid(context));
1009 AssertNotInCriticalSection(context);
1010
1011 if (!AllocHugeSizeIsValid(size))
1012 elog(ERROR, "invalid memory alloc request size %zu", size);
1013
1014 context->isReset = false;
1015
1016 ret = (*context->methods->alloc) (context, size);
1017 if (ret == NULL)
1018 {
1019 MemoryContextStats(TopMemoryContext);
1020 ereport(ERROR,
1021 (errcode(ERRCODE_OUT_OF_MEMORY),
1022 errmsg("out of memory"),
1023 errdetail("Failed on request of size %zu.", size)));
1024 }
1025
1026 VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1027
1028 return ret;
1029 }
1030
1031 /*
1032 * repalloc_huge
1033 * Adjust the size of a previously allocated chunk, permitting a large
1034 * value. The previous allocation need not have been "huge".
1035 */
1036 void *
repalloc_huge(void * pointer,Size size)1037 repalloc_huge(void *pointer, Size size)
1038 {
1039 MemoryContext context = GetMemoryChunkContext(pointer);
1040 void *ret;
1041
1042 if (!AllocHugeSizeIsValid(size))
1043 elog(ERROR, "invalid memory alloc request size %zu", size);
1044
1045 AssertNotInCriticalSection(context);
1046
1047 /* isReset must be false already */
1048 Assert(!context->isReset);
1049
1050 ret = (*context->methods->realloc) (context, pointer, size);
1051 if (ret == NULL)
1052 {
1053 MemoryContextStats(TopMemoryContext);
1054 ereport(ERROR,
1055 (errcode(ERRCODE_OUT_OF_MEMORY),
1056 errmsg("out of memory"),
1057 errdetail("Failed on request of size %zu.", size)));
1058 }
1059
1060 VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1061
1062 return ret;
1063 }
1064
1065 /*
1066 * MemoryContextStrdup
1067 * Like strdup(), but allocate from the specified context
1068 */
1069 char *
MemoryContextStrdup(MemoryContext context,const char * string)1070 MemoryContextStrdup(MemoryContext context, const char *string)
1071 {
1072 char *nstr;
1073 Size len = strlen(string) + 1;
1074
1075 nstr = (char *) MemoryContextAlloc(context, len);
1076
1077 memcpy(nstr, string, len);
1078
1079 return nstr;
1080 }
1081
1082 char *
pstrdup(const char * in)1083 pstrdup(const char *in)
1084 {
1085 return MemoryContextStrdup(CurrentMemoryContext, in);
1086 }
1087
1088 /*
1089 * pnstrdup
1090 * Like pstrdup(), but append null byte to a
1091 * not-necessarily-null-terminated input string.
1092 */
1093 char *
pnstrdup(const char * in,Size len)1094 pnstrdup(const char *in, Size len)
1095 {
1096 char *out = palloc(len + 1);
1097
1098 memcpy(out, in, len);
1099 out[len] = '\0';
1100 return out;
1101 }
1102
1103 /*
1104 * Make copy of string with all trailing newline characters removed.
1105 */
1106 char *
pchomp(const char * in)1107 pchomp(const char *in)
1108 {
1109 size_t n;
1110
1111 n = strlen(in);
1112 while (n > 0 && in[n - 1] == '\n')
1113 n--;
1114 return pnstrdup(in, n);
1115 }
1116