Age Owner TLA 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-2023, PostgreSQL Global Development Group
13 : * Portions Copyright (c) 1994, Regents of the University of California
14 : *
15 : *
16 : * IDENTIFICATION
17 : * src/backend/utils/mmgr/mcxt.c
18 : *
19 : *-------------------------------------------------------------------------
20 : */
21 :
22 : #include "postgres.h"
23 :
24 : #include "mb/pg_wchar.h"
25 : #include "miscadmin.h"
26 : #include "storage/proc.h"
27 : #include "storage/procarray.h"
28 : #include "storage/procsignal.h"
29 : #include "utils/fmgrprotos.h"
30 : #include "utils/memdebug.h"
31 : #include "utils/memutils.h"
32 : #include "utils/memutils_internal.h"
33 : #include "utils/memutils_memorychunk.h"
34 :
35 :
36 : static void BogusFree(void *pointer);
37 : static void *BogusRealloc(void *pointer, Size size);
38 : static MemoryContext BogusGetChunkContext(void *pointer);
39 : static Size BogusGetChunkSpace(void *pointer);
40 :
41 : /*****************************************************************************
42 : * GLOBAL MEMORY *
43 : *****************************************************************************/
44 :
45 : static const MemoryContextMethods mcxt_methods[] = {
46 : /* aset.c */
47 : [MCTX_ASET_ID].alloc = AllocSetAlloc,
48 : [MCTX_ASET_ID].free_p = AllocSetFree,
49 : [MCTX_ASET_ID].realloc = AllocSetRealloc,
50 : [MCTX_ASET_ID].reset = AllocSetReset,
51 : [MCTX_ASET_ID].delete_context = AllocSetDelete,
52 : [MCTX_ASET_ID].get_chunk_context = AllocSetGetChunkContext,
53 : [MCTX_ASET_ID].get_chunk_space = AllocSetGetChunkSpace,
54 : [MCTX_ASET_ID].is_empty = AllocSetIsEmpty,
55 : [MCTX_ASET_ID].stats = AllocSetStats,
56 : #ifdef MEMORY_CONTEXT_CHECKING
57 : [MCTX_ASET_ID].check = AllocSetCheck,
58 : #endif
59 :
60 : /* generation.c */
61 : [MCTX_GENERATION_ID].alloc = GenerationAlloc,
62 : [MCTX_GENERATION_ID].free_p = GenerationFree,
63 : [MCTX_GENERATION_ID].realloc = GenerationRealloc,
64 : [MCTX_GENERATION_ID].reset = GenerationReset,
65 : [MCTX_GENERATION_ID].delete_context = GenerationDelete,
66 : [MCTX_GENERATION_ID].get_chunk_context = GenerationGetChunkContext,
67 : [MCTX_GENERATION_ID].get_chunk_space = GenerationGetChunkSpace,
68 : [MCTX_GENERATION_ID].is_empty = GenerationIsEmpty,
69 : [MCTX_GENERATION_ID].stats = GenerationStats,
70 : #ifdef MEMORY_CONTEXT_CHECKING
71 : [MCTX_GENERATION_ID].check = GenerationCheck,
72 : #endif
73 :
74 : /* slab.c */
75 : [MCTX_SLAB_ID].alloc = SlabAlloc,
76 : [MCTX_SLAB_ID].free_p = SlabFree,
77 : [MCTX_SLAB_ID].realloc = SlabRealloc,
78 : [MCTX_SLAB_ID].reset = SlabReset,
79 : [MCTX_SLAB_ID].delete_context = SlabDelete,
80 : [MCTX_SLAB_ID].get_chunk_context = SlabGetChunkContext,
81 : [MCTX_SLAB_ID].get_chunk_space = SlabGetChunkSpace,
82 : [MCTX_SLAB_ID].is_empty = SlabIsEmpty,
83 : [MCTX_SLAB_ID].stats = SlabStats,
84 : #ifdef MEMORY_CONTEXT_CHECKING
85 : [MCTX_SLAB_ID].check = SlabCheck,
86 : #endif
87 :
88 : /* alignedalloc.c */
89 : [MCTX_ALIGNED_REDIRECT_ID].alloc = NULL, /* not required */
90 : [MCTX_ALIGNED_REDIRECT_ID].free_p = AlignedAllocFree,
91 : [MCTX_ALIGNED_REDIRECT_ID].realloc = AlignedAllocRealloc,
92 : [MCTX_ALIGNED_REDIRECT_ID].reset = NULL, /* not required */
93 : [MCTX_ALIGNED_REDIRECT_ID].delete_context = NULL, /* not required */
94 : [MCTX_ALIGNED_REDIRECT_ID].get_chunk_context = AlignedAllocGetChunkContext,
95 : [MCTX_ALIGNED_REDIRECT_ID].get_chunk_space = AlignedAllocGetChunkSpace,
96 : [MCTX_ALIGNED_REDIRECT_ID].is_empty = NULL, /* not required */
97 : [MCTX_ALIGNED_REDIRECT_ID].stats = NULL, /* not required */
98 : #ifdef MEMORY_CONTEXT_CHECKING
99 : [MCTX_ALIGNED_REDIRECT_ID].check = NULL, /* not required */
100 : #endif
101 :
102 :
103 : /*
104 : * Unused (as yet) IDs should have dummy entries here. This allows us to
105 : * fail cleanly if a bogus pointer is passed to pfree or the like. It
106 : * seems sufficient to provide routines for the methods that might get
107 : * invoked from inspection of a chunk (see MCXT_METHOD calls below).
108 : */
109 :
110 : [MCTX_UNUSED1_ID].free_p = BogusFree,
111 : [MCTX_UNUSED1_ID].realloc = BogusRealloc,
112 : [MCTX_UNUSED1_ID].get_chunk_context = BogusGetChunkContext,
113 : [MCTX_UNUSED1_ID].get_chunk_space = BogusGetChunkSpace,
114 :
115 : [MCTX_UNUSED2_ID].free_p = BogusFree,
116 : [MCTX_UNUSED2_ID].realloc = BogusRealloc,
117 : [MCTX_UNUSED2_ID].get_chunk_context = BogusGetChunkContext,
118 : [MCTX_UNUSED2_ID].get_chunk_space = BogusGetChunkSpace,
119 :
120 : [MCTX_UNUSED3_ID].free_p = BogusFree,
121 : [MCTX_UNUSED3_ID].realloc = BogusRealloc,
122 : [MCTX_UNUSED3_ID].get_chunk_context = BogusGetChunkContext,
123 : [MCTX_UNUSED3_ID].get_chunk_space = BogusGetChunkSpace,
124 :
125 : [MCTX_UNUSED4_ID].free_p = BogusFree,
126 : [MCTX_UNUSED4_ID].realloc = BogusRealloc,
127 : [MCTX_UNUSED4_ID].get_chunk_context = BogusGetChunkContext,
128 : [MCTX_UNUSED4_ID].get_chunk_space = BogusGetChunkSpace,
129 : };
130 :
131 : /*
132 : * CurrentMemoryContext
133 : * Default memory context for allocations.
134 : */
135 : MemoryContext CurrentMemoryContext = NULL;
136 :
137 : /*
138 : * Standard top-level contexts. For a description of the purpose of each
139 : * of these contexts, refer to src/backend/utils/mmgr/README
140 : */
141 : MemoryContext TopMemoryContext = NULL;
142 : MemoryContext ErrorContext = NULL;
143 : MemoryContext PostmasterContext = NULL;
144 : MemoryContext CacheMemoryContext = NULL;
145 : MemoryContext MessageContext = NULL;
146 : MemoryContext TopTransactionContext = NULL;
147 : MemoryContext CurTransactionContext = NULL;
148 :
149 : /* This is a transient link to the active portal's memory context: */
150 : MemoryContext PortalContext = NULL;
151 :
152 : static void MemoryContextCallResetCallbacks(MemoryContext context);
153 : static void MemoryContextStatsInternal(MemoryContext context, int level,
154 : bool print, int max_children,
155 : MemoryContextCounters *totals,
156 : bool print_to_stderr);
157 : static void MemoryContextStatsPrint(MemoryContext context, void *passthru,
158 : const char *stats_string,
159 : bool print_to_stderr);
160 :
161 : /*
162 : * You should not do memory allocations within a critical section, because
163 : * an out-of-memory error will be escalated to a PANIC. To enforce that
164 : * rule, the allocation functions Assert that.
165 : */
166 : #define AssertNotInCriticalSection(context) \
167 : Assert(CritSectionCount == 0 || (context)->allowInCritSection)
168 :
169 : /*
170 : * Call the given function in the MemoryContextMethods for the memory context
171 : * type that 'pointer' belongs to.
172 : */
173 : #define MCXT_METHOD(pointer, method) \
174 : mcxt_methods[GetMemoryChunkMethodID(pointer)].method
175 :
176 : /*
177 : * GetMemoryChunkMethodID
178 : * Return the MemoryContextMethodID from the uint64 chunk header which
179 : * directly precedes 'pointer'.
180 : */
181 : static inline MemoryContextMethodID
185 tgl 182 GNC 319569724 : GetMemoryChunkMethodID(const void *pointer)
183 : {
184 : uint64 header;
185 :
186 : /*
187 : * Try to detect bogus pointers handed to us, poorly though we can.
188 : * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
189 : * allocated chunk.
190 : */
191 319569724 : Assert(pointer == (const void *) MAXALIGN(pointer));
192 :
193 319569724 : header = *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
194 :
195 319569724 : return (MemoryContextMethodID) (header & MEMORY_CONTEXT_METHODID_MASK);
196 : }
197 :
198 : /*
199 : * GetMemoryChunkHeader
200 : * Return the uint64 chunk header which directly precedes 'pointer'.
201 : *
202 : * This is only used after GetMemoryChunkMethodID, so no need for error checks.
203 : */
204 : static inline uint64
185 tgl 205 UNC 0 : GetMemoryChunkHeader(const void *pointer)
206 : {
207 0 : return *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
208 : }
209 :
210 : /*
211 : * Support routines to trap use of invalid memory context method IDs
212 : * (from calling pfree or the like on a bogus pointer). As a possible
213 : * aid in debugging, we report the header word along with the pointer
214 : * address (if we got here, there must be an accessible header word).
215 : */
216 : static void
217 0 : BogusFree(void *pointer)
218 : {
219 0 : elog(ERROR, "pfree called with invalid pointer %p (header 0x%016llx)",
220 : pointer, (unsigned long long) GetMemoryChunkHeader(pointer));
221 : }
222 :
223 : static void *
224 0 : BogusRealloc(void *pointer, Size size)
225 : {
226 0 : elog(ERROR, "repalloc called with invalid pointer %p (header 0x%016llx)",
227 : pointer, (unsigned long long) GetMemoryChunkHeader(pointer));
228 : return NULL; /* keep compiler quiet */
229 : }
230 :
231 : static MemoryContext
232 0 : BogusGetChunkContext(void *pointer)
233 : {
234 0 : elog(ERROR, "GetMemoryChunkContext called with invalid pointer %p (header 0x%016llx)",
235 : pointer, (unsigned long long) GetMemoryChunkHeader(pointer));
236 : return NULL; /* keep compiler quiet */
237 : }
238 :
239 : static Size
240 0 : BogusGetChunkSpace(void *pointer)
241 : {
242 0 : elog(ERROR, "GetMemoryChunkSpace called with invalid pointer %p (header 0x%016llx)",
243 : pointer, (unsigned long long) GetMemoryChunkHeader(pointer));
244 : return 0; /* keep compiler quiet */
245 : }
246 :
247 :
248 : /*****************************************************************************
249 : * EXPORTED ROUTINES *
250 : *****************************************************************************/
251 :
252 :
253 : /*
254 : * MemoryContextInit
255 : * Start up the memory-context subsystem.
256 : *
257 : * This must be called before creating contexts or allocating memory in
258 : * contexts. TopMemoryContext and ErrorContext are initialized here;
259 : * other contexts must be created afterwards.
260 : *
261 : * In normal multi-backend operation, this is called once during
262 : * postmaster startup, and not at all by individual backend startup
263 : * (since the backends inherit an already-initialized context subsystem
264 : * by virtue of being forked off the postmaster). But in an EXEC_BACKEND
265 : * build, each process must do this for itself.
266 : *
267 : * In a standalone backend this must be called during backend startup.
268 : */
269 : void
8320 tgl 270 GIC 2619 : MemoryContextInit(void)
271 : {
163 peter 272 GNC 2619 : Assert(TopMemoryContext == NULL);
273 :
274 : /*
275 : * First, initialize TopMemoryContext, which is the parent of all others.
276 : */
8320 tgl 277 GIC 2619 : TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
278 : "TopMemoryContext",
279 : ALLOCSET_DEFAULT_SIZES);
280 :
281 : /*
282 : * Not having any other place to point CurrentMemoryContext, make it point
283 : * to TopMemoryContext. Caller should change this soon!
284 : */
285 2619 : CurrentMemoryContext = TopMemoryContext;
286 :
287 : /*
288 : * Initialize ErrorContext as an AllocSetContext with slow growth rate ---
289 : * we don't really expect much to be allocated in it. More to the point,
290 : * require it to contain at least 8K at all times. This is the only case
291 : * where retained memory in a context is *essential* --- we want to be
292 : * sure ErrorContext still has some memory even if we've run out
293 : * elsewhere! Also, allow allocations in ErrorContext within a critical
294 : * section. Otherwise a PANIC will cause an assertion failure in the error
295 : * reporting code, before printing out the real cause of the failure.
296 : *
297 : * This should be the last step in this function, as elog.c assumes memory
298 : * management works once ErrorContext is non-null.
299 : */
1640 300 2619 : ErrorContext = AllocSetContextCreate(TopMemoryContext,
301 : "ErrorContext",
302 : 8 * 1024,
303 : 8 * 1024,
304 : 8 * 1024);
3205 heikki.linnakangas 305 2619 : MemoryContextAllowInCriticalSection(ErrorContext, true);
9770 scrappy 306 2619 : }
307 :
308 : /*
309 : * MemoryContextReset
310 : * Release all space allocated within a context and delete all its
311 : * descendant contexts (but not the named context itself).
312 : */
313 : void
8320 tgl 314 158513146 : MemoryContextReset(MemoryContext context)
315 : {
163 peter 316 GNC 158513146 : Assert(MemoryContextIsValid(context));
317 :
318 : /* save a function call in common case where there are no children */
6539 tgl 319 GIC 158513146 : if (context->firstchild != NULL)
2963 320 212663 : MemoryContextDeleteChildren(context);
321 :
322 : /* save a function call if no pallocs since startup or last reset */
323 158513146 : if (!context->isReset)
324 21892436 : MemoryContextResetOnly(context);
325 158513146 : }
326 :
327 : /*
328 : * MemoryContextResetOnly
329 : * Release all space allocated within a context.
330 : * Nothing is done to the context's descendant contexts.
331 : */
332 : void
333 25273236 : MemoryContextResetOnly(MemoryContext context)
334 : {
163 peter 335 GNC 25273236 : Assert(MemoryContextIsValid(context));
336 :
337 : /* Nothing to do if no pallocs since startup or last reset */
4341 heikki.linnakangas 338 GIC 25273236 : if (!context->isReset)
339 : {
2963 tgl 340 25273107 : MemoryContextCallResetCallbacks(context);
341 :
342 : /*
343 : * If context->ident points into the context's memory, it will become
344 : * a dangling pointer. We could prevent that by setting it to NULL
345 : * here, but that would break valid coding patterns that keep the
346 : * ident elsewhere, e.g. in a parent context. So for now we assume
347 : * the programmer got it right.
348 : */
349 :
2040 peter_e 350 25273107 : context->methods->reset(context);
4341 heikki.linnakangas 351 CBC 25273107 : context->isReset = true;
352 : VALGRIND_DESTROY_MEMPOOL(context);
353 : VALGRIND_CREATE_MEMPOOL(context, 0, false);
354 : }
9770 scrappy 355 GIC 25273236 : }
356 :
357 : /*
358 : * MemoryContextResetChildren
359 : * Release all space allocated within a context's descendants,
8320 tgl 360 ECB : * but don't delete the contexts themselves. The named context
361 : * itself is not touched.
9770 scrappy 362 : */
363 : void
8320 tgl 364 LBC 0 : MemoryContextResetChildren(MemoryContext context)
365 : {
366 : MemoryContext child;
367 :
163 peter 368 UNC 0 : Assert(MemoryContextIsValid(context));
369 :
8320 tgl 370 UIC 0 : for (child = context->firstchild; child != NULL; child = child->nextchild)
371 : {
2963 372 0 : MemoryContextResetChildren(child);
373 0 : MemoryContextResetOnly(child);
2963 tgl 374 EUB : }
9770 scrappy 375 UIC 0 : }
9770 scrappy 376 EUB :
377 : /*
378 : * MemoryContextDelete
379 : * Delete a context and its descendants, and release all space
380 : * allocated therein.
381 : *
382 : * The type-specific delete routine removes all storage for the context,
383 : * but we have to recurse to handle the children.
384 : * We must also delink the context from its parent, if it has one.
385 : */
8320 tgl 386 : void
8320 tgl 387 GIC 5138013 : MemoryContextDelete(MemoryContext context)
9770 scrappy 388 EUB : {
163 peter 389 GNC 5138013 : Assert(MemoryContextIsValid(context));
390 : /* We had better not be deleting TopMemoryContext ... */
8320 tgl 391 GIC 5138013 : Assert(context != TopMemoryContext);
392 : /* And not CurrentMemoryContext, either */
8320 tgl 393 GBC 5138013 : Assert(context != CurrentMemoryContext);
394 :
1943 tgl 395 EUB : /* save a function call in common case where there are no children */
1943 tgl 396 GIC 5138013 : if (context->firstchild != NULL)
397 379181 : MemoryContextDeleteChildren(context);
398 :
399 : /*
400 : * It's not entirely clear whether 'tis better to do this before or after
2963 tgl 401 EUB : * delinking the context; but an error in a callback will likely result in
402 : * leaking the whole context (if it's not a root context) if we do it
403 : * after, so let's do it before.
404 : */
2963 tgl 405 GIC 5138013 : MemoryContextCallResetCallbacks(context);
406 :
407 : /*
408 : * We delink the context from its parent before deleting it, so that if
6385 bruce 409 EUB : * there's an error we won't have deleted/busted contexts still attached
410 : * to the context tree. Better a leak than a crash.
8320 tgl 411 : */
4228 tgl 412 GIC 5138013 : MemoryContextSetParent(context, NULL);
413 :
414 : /*
415 : * Also reset the context's ident pointer, in case it points into the
416 : * context. This would only matter if someone tries to get stats on the
417 : * (already unlinked) context, which is unlikely, but let's be safe.
418 : */
1839 419 5138013 : context->ident = NULL;
420 :
2040 peter_e 421 5138013 : context->methods->delete_context(context);
422 :
423 : VALGRIND_DESTROY_MEMPOOL(context);
9770 scrappy 424 5138013 : }
425 :
426 : /*
427 : * MemoryContextDeleteChildren
428 : * Delete all the descendants of the named context and release all
429 : * space allocated therein. The named context itself is not touched.
430 : */
431 : void
8320 tgl 432 972559 : MemoryContextDeleteChildren(MemoryContext context)
433 : {
163 peter 434 GNC 972559 : Assert(MemoryContextIsValid(context));
435 :
436 : /*
437 : * MemoryContextDelete will delink the child from me, so just iterate as
438 : * long as there is a child.
8320 tgl 439 ECB : */
8320 tgl 440 GIC 1638659 : while (context->firstchild != NULL)
8320 tgl 441 CBC 666100 : MemoryContextDelete(context->firstchild);
9770 scrappy 442 GIC 972559 : }
443 :
444 : /*
445 : * MemoryContextRegisterResetCallback
2963 tgl 446 ECB : * Register a function to be called before next context reset/delete.
447 : * Such callbacks will be called in reverse order of registration.
448 : *
449 : * The caller is responsible for allocating a MemoryContextCallback struct
450 : * to hold the info about this callback request, and for filling in the
451 : * "func" and "arg" fields in the struct to show what function to call with
452 : * what argument. Typically the callback struct should be allocated within
453 : * the specified context, since that means it will automatically be freed
454 : * when no longer needed.
455 : *
456 : * There is no API for deregistering a callback once registered. If you
457 : * want it to not do anything anymore, adjust the state pointed to by its
458 : * "arg" to indicate that.
459 : */
460 : void
2963 tgl 461 GIC 40683 : MemoryContextRegisterResetCallback(MemoryContext context,
462 : MemoryContextCallback *cb)
463 : {
163 peter 464 GNC 40683 : Assert(MemoryContextIsValid(context));
465 :
466 : /* Push onto head so this will be called before older registrants. */
2963 tgl 467 GIC 40683 : cb->next = context->reset_cbs;
468 40683 : context->reset_cbs = cb;
2963 tgl 469 ECB : /* Mark the context as non-reset (it probably is already). */
2963 tgl 470 GIC 40683 : context->isReset = false;
471 40683 : }
472 :
473 : /*
2963 tgl 474 ECB : * MemoryContextCallResetCallbacks
475 : * Internal function to call all registered callbacks for context.
476 : */
477 : static void
2963 tgl 478 GIC 30411120 : MemoryContextCallResetCallbacks(MemoryContext context)
479 : {
480 : MemoryContextCallback *cb;
481 :
482 : /*
2963 tgl 483 ECB : * We pop each callback from the list before calling. That way, if an
484 : * error occurs inside the callback, we won't try to call it a second time
485 : * in the likely event that we reset or delete the context later.
486 : */
2963 tgl 487 GIC 30451789 : while ((cb = context->reset_cbs) != NULL)
2963 tgl 488 ECB : {
2963 tgl 489 CBC 40669 : context->reset_cbs = cb->next;
2040 peter_e 490 GIC 40669 : cb->func(cb->arg);
491 : }
2963 tgl 492 CBC 30411120 : }
2963 tgl 493 ECB :
1839 494 : /*
495 : * MemoryContextSetIdentifier
496 : * Set the identifier string for a memory context.
497 : *
498 : * An identifier can be provided to help distinguish among different contexts
499 : * of the same kind in memory context stats dumps. The identifier string
500 : * must live at least as long as the context it is for; typically it is
501 : * allocated inside that context, so that it automatically goes away on
502 : * context deletion. Pass id = NULL to forget any old identifier.
503 : */
504 : void
1839 tgl 505 GIC 1928082 : MemoryContextSetIdentifier(MemoryContext context, const char *id)
506 : {
163 peter 507 GNC 1928082 : Assert(MemoryContextIsValid(context));
1839 tgl 508 GIC 1928082 : context->ident = id;
1839 tgl 509 CBC 1928082 : }
510 :
511 : /*
512 : * MemoryContextSetParent
513 : * Change a context to belong to a new parent (or no parent).
514 : *
515 : * We provide this as an API function because it is sometimes useful to
516 : * change a context's lifespan after creation. For example, a context
517 : * might be created underneath a transient context, filled with data,
518 : * and then reparented underneath CacheMemoryContext to make it long-lived.
4228 tgl 519 ECB : * In this way no special effort is needed to get rid of the context in case
520 : * a failure occurs before its contents are completely set up.
521 : *
522 : * Callers often assume that this function cannot fail, so don't put any
523 : * elog(ERROR) calls in it.
524 : *
525 : * A possible caller error is to reparent a context under itself, creating
526 : * a loop in the context graph. We assert here that context != new_parent,
527 : * but checking for multi-level loops seems more trouble than it's worth.
528 : */
529 : void
4228 tgl 530 GIC 5250313 : MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
531 : {
163 peter 532 GNC 5250313 : Assert(MemoryContextIsValid(context));
533 5250313 : Assert(context != new_parent);
534 :
535 : /* Fast path if it's got correct parent already */
2887 tgl 536 GIC 5250313 : if (new_parent == context->parent)
2887 tgl 537 GBC 4655 : return;
538 :
4228 tgl 539 EUB : /* Delink from existing parent, if any */
4228 tgl 540 GIC 5245658 : if (context->parent)
4228 tgl 541 EUB : {
4228 tgl 542 GBC 5245658 : MemoryContext parent = context->parent;
543 :
2679 kgrittn 544 5245658 : if (context->prevchild != NULL)
2679 kgrittn 545 GIC 405464 : context->prevchild->nextchild = context->nextchild;
546 : else
547 : {
548 4840194 : Assert(parent->firstchild == context);
549 4840194 : parent->firstchild = context->nextchild;
550 : }
551 :
552 5245658 : if (context->nextchild != NULL)
553 2190875 : context->nextchild->prevchild = context->prevchild;
554 : }
555 :
4228 tgl 556 ECB : /* And relink */
4228 tgl 557 GIC 5245658 : if (new_parent)
4228 tgl 558 ECB : {
163 peter 559 GNC 107645 : Assert(MemoryContextIsValid(new_parent));
4228 tgl 560 CBC 107645 : context->parent = new_parent;
2679 kgrittn 561 GIC 107645 : context->prevchild = NULL;
4228 tgl 562 CBC 107645 : context->nextchild = new_parent->firstchild;
2679 kgrittn 563 GIC 107645 : if (new_parent->firstchild != NULL)
564 98100 : new_parent->firstchild->prevchild = context;
4228 tgl 565 CBC 107645 : new_parent->firstchild = context;
4228 tgl 566 ECB : }
567 : else
568 : {
4228 tgl 569 GIC 5138013 : context->parent = NULL;
2679 kgrittn 570 5138013 : context->prevchild = NULL;
4228 tgl 571 5138013 : context->nextchild = NULL;
572 : }
573 : }
4228 tgl 574 ECB :
575 : /*
576 : * MemoryContextAllowInCriticalSection
577 : * Allow/disallow allocations in this memory context within a critical
578 : * section.
579 : *
580 : * Normally, memory allocations are not allowed within a critical section,
3205 heikki.linnakangas 581 : * because a failure would lead to PANIC. There are a few exceptions to
582 : * that, like allocations related to debugging code that is not supposed to
583 : * be enabled in production. This function can be used to exempt specific
584 : * memory contexts from the assertion in palloc().
585 : */
586 : void
3205 heikki.linnakangas 587 GIC 3593 : MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
3205 heikki.linnakangas 588 ECB : {
163 peter 589 GNC 3593 : Assert(MemoryContextIsValid(context));
2963 tgl 590 ECB :
3205 heikki.linnakangas 591 GIC 3593 : context->allowInCritSection = allow;
592 3593 : }
3205 heikki.linnakangas 593 ECB :
594 : /*
595 : * GetMemoryChunkContext
596 : * Given a currently-allocated chunk, determine the MemoryContext that
597 : * the chunk belongs to.
598 : */
599 : MemoryContext
223 drowley 600 GNC 4842066 : GetMemoryChunkContext(void *pointer)
601 : {
602 4842066 : return MCXT_METHOD(pointer, get_chunk_context) (pointer);
603 : }
604 :
605 : /*
606 : * GetMemoryChunkSpace
607 : * Given a currently-allocated chunk, determine the total space
608 : * it occupies (including all memory-allocation overhead).
609 : *
610 : * This is useful for measuring the total space occupied by a set of
611 : * allocated chunks.
7545 tgl 612 ECB : */
613 : Size
7545 tgl 614 CBC 39987266 : GetMemoryChunkSpace(void *pointer)
615 : {
223 drowley 616 GNC 39987266 : return MCXT_METHOD(pointer, get_chunk_space) (pointer);
617 : }
7419 tgl 618 ECB :
4223 619 : /*
620 : * MemoryContextGetParent
621 : * Get the parent context (if any) of the specified context
622 : */
623 : MemoryContext
4223 tgl 624 GIC 8424 : MemoryContextGetParent(MemoryContext context)
625 : {
163 peter 626 GNC 8424 : Assert(MemoryContextIsValid(context));
627 :
4223 tgl 628 GIC 8424 : return context->parent;
629 : }
630 :
631 : /*
632 : * MemoryContextIsEmpty
633 : * Is a memory context empty of any allocated space?
634 : */
635 : bool
6779 636 4332 : MemoryContextIsEmpty(MemoryContext context)
637 : {
163 peter 638 GNC 4332 : Assert(MemoryContextIsValid(context));
6779 tgl 639 ECB :
640 : /*
641 : * For now, we consider a memory context nonempty if it has any children;
642 : * perhaps this should be changed later.
643 : */
6779 tgl 644 GIC 4332 : if (context->firstchild != NULL)
6779 tgl 645 CBC 2 : return false;
6779 tgl 646 ECB : /* Otherwise use the type-specific inquiry */
2040 peter_e 647 GIC 4330 : return context->methods->is_empty(context);
6779 tgl 648 ECB : }
649 :
650 : /*
651 : * Find the memory allocated to blocks for this memory context. If recurse is
652 : * true, also include children.
653 : */
654 : Size
1286 tomas.vondra 655 GIC 1125110 : MemoryContextMemAllocated(MemoryContext context, bool recurse)
1286 tomas.vondra 656 ECB : {
1060 tgl 657 GIC 1125110 : Size total = context->mem_allocated;
658 :
163 peter 659 GNC 1125110 : Assert(MemoryContextIsValid(context));
660 :
1286 tomas.vondra 661 GIC 1125110 : if (recurse)
662 : {
663 : MemoryContext child;
664 :
1286 tomas.vondra 665 CBC 1125110 : for (child = context->firstchild;
1286 tomas.vondra 666 GIC 1603418 : child != NULL;
1286 tomas.vondra 667 CBC 478308 : child = child->nextchild)
668 478308 : total += MemoryContextMemAllocated(child, true);
669 : }
1286 tomas.vondra 670 ECB :
1286 tomas.vondra 671 GIC 1125110 : return total;
672 : }
673 :
674 : /*
675 : * MemoryContextStats
676 : * Print statistics about the named context and all its descendants.
677 : *
678 : * This is just a debugging utility, so it's not very fancy. However, we do
679 : * make some effort to summarize when the output would otherwise be very long.
680 : * The statistics are sent to stderr.
681 : */
682 : void
8320 tgl 683 LBC 0 : MemoryContextStats(MemoryContext context)
684 : {
2784 tgl 685 ECB : /* A hard-wired limit on the number of children is usually good enough */
733 fujii 686 LBC 0 : MemoryContextStatsDetail(context, 100, true);
5724 neilc 687 0 : }
688 :
689 : /*
690 : * MemoryContextStatsDetail
691 : *
692 : * Entry point for use if you want to vary the number of child contexts shown.
693 : *
694 : * If print_to_stderr is true, print statistics about the memory contexts
695 : * with fprintf(stderr), otherwise use ereport().
696 : */
697 : void
733 fujii 698 GIC 9 : MemoryContextStatsDetail(MemoryContext context, int max_children,
699 : bool print_to_stderr)
700 : {
701 : MemoryContextCounters grand_totals;
702 :
2784 tgl 703 9 : memset(&grand_totals, 0, sizeof(grand_totals));
704 :
733 fujii 705 9 : MemoryContextStatsInternal(context, 0, true, max_children, &grand_totals, print_to_stderr);
706 :
707 9 : if (print_to_stderr)
733 fujii 708 LBC 0 : fprintf(stderr,
709 : "Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used\n",
733 fujii 710 ECB : grand_totals.totalspace, grand_totals.nblocks,
711 : grand_totals.freespace, grand_totals.freechunks,
733 fujii 712 UIC 0 : grand_totals.totalspace - grand_totals.freespace);
713 : else
2784 tgl 714 ECB :
733 fujii 715 : /*
716 : * Use LOG_SERVER_ONLY to prevent the memory contexts from being sent
717 : * to the connected client.
718 : *
719 : * We don't buffer the information about all memory contexts in a
720 : * backend into StringInfo and log it as one message. That would
721 : * require the buffer to be enlarged, risking an OOM as there could
722 : * be a large number of memory contexts in a backend. Instead, we
723 : * log one message per memory context.
724 : */
733 fujii 725 GIC 9 : ereport(LOG_SERVER_ONLY,
733 fujii 726 ECB : (errhidestmt(true),
727 : errhidecontext(true),
728 : errmsg_internal("Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used",
729 : grand_totals.totalspace, grand_totals.nblocks,
730 : grand_totals.freespace, grand_totals.freechunks,
731 : grand_totals.totalspace - grand_totals.freespace)));
2784 tgl 732 GIC 9 : }
733 :
734 : /*
2784 tgl 735 ECB : * MemoryContextStatsInternal
736 : * One recursion level for MemoryContextStats
737 : *
738 : * Print this context if print is true, but in any case accumulate counts into
739 : * *totals (if given).
740 : */
5724 neilc 741 : static void
2784 tgl 742 CBC 767 : MemoryContextStatsInternal(MemoryContext context, int level,
2784 tgl 743 ECB : bool print, int max_children,
744 : MemoryContextCounters *totals,
745 : bool print_to_stderr)
746 : {
747 : MemoryContextCounters local_totals;
8053 bruce 748 : MemoryContext child;
2784 tgl 749 : int ichild;
750 :
163 peter 751 GNC 767 : Assert(MemoryContextIsValid(context));
752 :
753 : /* Examine the context itself */
1839 tgl 754 GIC 767 : context->methods->stats(context,
755 : print ? MemoryContextStatsPrint : NULL,
756 : (void *) &level,
757 : totals, print_to_stderr);
758 :
759 : /*
760 : * Examine children. If there are more than max_children of them, we do
761 : * not print the rest explicitly, but just summarize them.
762 : */
2784 763 767 : memset(&local_totals, 0, sizeof(local_totals));
764 :
2784 tgl 765 CBC 767 : for (child = context->firstchild, ichild = 0;
2784 tgl 766 GIC 1525 : child != NULL;
2784 tgl 767 CBC 758 : child = child->nextchild, ichild++)
768 : {
769 758 : if (ichild < max_children)
770 758 : MemoryContextStatsInternal(child, level + 1,
771 : print, max_children,
772 : totals,
773 : print_to_stderr);
774 : else
2784 tgl 775 UIC 0 : MemoryContextStatsInternal(child, level + 1,
776 : false, max_children,
777 : &local_totals,
733 fujii 778 ECB : print_to_stderr);
779 : }
2784 tgl 780 :
781 : /* Deal with excess children */
2784 tgl 782 GIC 767 : if (ichild > max_children)
783 : {
2784 tgl 784 UIC 0 : if (print)
785 : {
733 fujii 786 0 : if (print_to_stderr)
787 : {
788 : int i;
789 :
790 0 : for (i = 0; i <= level; i++)
791 0 : fprintf(stderr, " ");
733 fujii 792 LBC 0 : fprintf(stderr,
793 : "%d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used\n",
733 fujii 794 ECB : ichild - max_children,
795 : local_totals.totalspace,
796 : local_totals.nblocks,
797 : local_totals.freespace,
798 : local_totals.freechunks,
733 fujii 799 UIC 0 : local_totals.totalspace - local_totals.freespace);
800 : }
801 : else
733 fujii 802 LBC 0 : ereport(LOG_SERVER_ONLY,
803 : (errhidestmt(true),
733 fujii 804 ECB : errhidecontext(true),
805 : errmsg_internal("level: %d; %d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used",
806 : level,
807 : ichild - max_children,
808 : local_totals.totalspace,
809 : local_totals.nblocks,
810 : local_totals.freespace,
811 : local_totals.freechunks,
812 : local_totals.totalspace - local_totals.freespace)));
813 : }
2784 tgl 814 :
2784 tgl 815 UIC 0 : if (totals)
2784 tgl 816 ECB : {
2784 tgl 817 UIC 0 : totals->nblocks += local_totals.nblocks;
818 0 : totals->freechunks += local_totals.freechunks;
819 0 : totals->totalspace += local_totals.totalspace;
820 0 : totals->freespace += local_totals.freespace;
821 : }
2784 tgl 822 ECB : }
9770 scrappy 823 CBC 767 : }
824 :
1839 tgl 825 ECB : /*
826 : * MemoryContextStatsPrint
827 : * Print callback used by MemoryContextStatsInternal
828 : *
829 : * For now, the passthru pointer just points to "int level"; later we might
830 : * make that more complicated.
831 : */
832 : static void
1839 tgl 833 CBC 767 : MemoryContextStatsPrint(MemoryContext context, void *passthru,
834 : const char *stats_string,
733 fujii 835 ECB : bool print_to_stderr)
836 : {
1839 tgl 837 CBC 767 : int level = *(int *) passthru;
1839 tgl 838 GIC 767 : const char *name = context->name;
1839 tgl 839 CBC 767 : const char *ident = context->ident;
840 : char truncated_ident[110];
841 : int i;
842 :
1839 tgl 843 ECB : /*
844 : * It seems preferable to label dynahash contexts with just the hash table
845 : * name. Those are already unique enough, so the "dynahash" part isn't
846 : * very helpful, and this way is more consistent with pre-v11 practice.
847 : */
1839 tgl 848 GIC 767 : if (ident && strcmp(name, "dynahash") == 0)
1839 tgl 849 ECB : {
1839 tgl 850 GIC 89 : name = ident;
851 89 : ident = NULL;
852 : }
853 :
733 fujii 854 767 : truncated_ident[0] = '\0';
855 :
1839 tgl 856 767 : if (ident)
857 : {
858 : /*
859 : * Some contexts may have very long identifiers (e.g., SQL queries).
860 : * Arbitrarily truncate at 100 bytes, but be careful not to break
1839 tgl 861 EUB : * multibyte characters. Also, replace ASCII control characters, such
862 : * as newlines, with spaces.
863 : */
1839 tgl 864 GBC 549 : int idlen = strlen(ident);
865 549 : bool truncated = false;
866 :
733 fujii 867 GIC 549 : strcpy(truncated_ident, ": ");
868 549 : i = strlen(truncated_ident);
869 :
1839 tgl 870 549 : if (idlen > 100)
871 : {
1839 tgl 872 UIC 0 : idlen = pg_mbcliplen(ident, idlen, 100);
873 0 : truncated = true;
874 : }
875 :
1839 tgl 876 CBC 15171 : while (idlen-- > 0)
877 : {
1839 tgl 878 GIC 14622 : unsigned char c = *ident++;
879 :
880 14622 : if (c < ' ')
1839 tgl 881 LBC 0 : c = ' ';
733 fujii 882 GIC 14622 : truncated_ident[i++] = c;
1839 tgl 883 ECB : }
733 fujii 884 GIC 549 : truncated_ident[i] = '\0';
733 fujii 885 ECB :
1839 tgl 886 GBC 549 : if (truncated)
733 fujii 887 UIC 0 : strcat(truncated_ident, "...");
888 : }
889 :
733 fujii 890 GBC 767 : if (print_to_stderr)
891 : {
733 fujii 892 UIC 0 : for (i = 0; i < level; i++)
893 0 : fprintf(stderr, " ");
894 0 : fprintf(stderr, "%s: %s%s\n", name, stats_string, truncated_ident);
895 : }
896 : else
733 fujii 897 GIC 767 : ereport(LOG_SERVER_ONLY,
898 : (errhidestmt(true),
899 : errhidecontext(true),
900 : errmsg_internal("level: %d; %s: %s%s",
901 : level, name, stats_string, truncated_ident)));
1839 tgl 902 767 : }
1839 tgl 903 ECB :
904 : /*
905 : * MemoryContextCheck
906 : * Check all chunks in the named context.
907 : *
908 : * This is just a debugging utility, so it's not fancy.
909 : */
8307 bruce 910 : #ifdef MEMORY_CONTEXT_CHECKING
911 : void
8307 bruce 912 GIC 68467717 : MemoryContextCheck(MemoryContext context)
913 : {
914 : MemoryContext child;
915 :
163 peter 916 GNC 68467717 : Assert(MemoryContextIsValid(context));
917 :
2040 peter_e 918 GIC 68467717 : context->methods->check(context);
8307 bruce 919 136499958 : for (child = context->firstchild; child != NULL; child = child->nextchild)
8307 bruce 920 CBC 68032241 : MemoryContextCheck(child);
8307 bruce 921 GIC 68467717 : }
922 : #endif
923 :
1943 tgl 924 ECB : /*
925 : * MemoryContextCreate
8320 tgl 926 EUB : * Context-type-independent part of context creation.
927 : *
928 : * This is only intended to be called by context-type-specific
929 : * context creation routines, not by the unwashed masses.
930 : *
931 : * The memory context creation procedure goes like this:
1943 932 : * 1. Context-type-specific routine makes some initial space allocation,
933 : * including enough space for the context header. If it fails,
934 : * it can ereport() with no damage done.
935 : * 2. Context-type-specific routine sets up all type-specific fields of
936 : * the header (those beyond MemoryContextData proper), as well as any
937 : * other management fields it needs to have a fully valid context.
938 : * Usually, failure in this step is impossible, but if it's possible
939 : * the initial space allocation should be freed before ereport'ing.
940 : * 3. Context-type-specific routine calls MemoryContextCreate() to fill in
941 : * the generic header fields and link the context into the context tree.
942 : * 4. We return to the context-type-specific routine, which finishes
943 : * up type-specific initialization. This routine can now do things
8320 944 : * that might fail (like allocate more memory), so long as it's
945 : * sure the node is left in a state that delete will handle.
946 : *
947 : * node: the as-yet-uninitialized common part of the context header node.
948 : * tag: NodeTag code identifying the memory context type.
949 : * method_id: MemoryContextMethodID of the context-type being created.
950 : * parent: parent context, or NULL if this will be a top-level context.
951 : * name: name of context (must be statically allocated).
952 : *
953 : * Context routines generally assume that MemoryContextCreate can't fail,
954 : * so this can contain Assert but not elog/ereport.
955 : */
956 : void
1943 tgl 957 GBC 6280971 : MemoryContextCreate(MemoryContext node,
958 : NodeTag tag,
959 : MemoryContextMethodID method_id,
8320 tgl 960 EUB : MemoryContext parent,
1839 961 : const char *name)
9770 scrappy 962 : {
963 : /* Creating new memory contexts is not allowed in a critical section */
3292 heikki.linnakangas 964 GIC 6280971 : Assert(CritSectionCount == 0);
3292 heikki.linnakangas 965 ECB :
966 : /* Initialize all standard fields of memory context header */
8320 tgl 967 GIC 6280971 : node->type = tag;
1943 968 6280971 : node->isReset = true;
223 drowley 969 GNC 6280971 : node->methods = &mcxt_methods[method_id];
1943 tgl 970 GIC 6280971 : node->parent = parent;
8320 971 6280971 : node->firstchild = NULL;
1116 jdavis 972 6280971 : node->mem_allocated = 0;
2679 kgrittn 973 6280971 : node->prevchild = NULL;
1839 tgl 974 6280971 : node->name = name;
1839 tgl 975 CBC 6280971 : node->ident = NULL;
1943 tgl 976 GIC 6280971 : node->reset_cbs = NULL;
977 :
978 : /* OK to link node into context tree */
8320 tgl 979 CBC 6280971 : if (parent)
8320 tgl 980 ECB : {
8320 tgl 981 CBC 6278047 : node->nextchild = parent->firstchild;
2679 kgrittn 982 GIC 6278047 : if (parent->firstchild != NULL)
983 3264151 : parent->firstchild->prevchild = node;
8320 tgl 984 6278047 : parent->firstchild = node;
985 : /* inherit allowInCritSection flag from parent */
3205 heikki.linnakangas 986 6278047 : node->allowInCritSection = parent->allowInCritSection;
987 : }
988 : else
989 : {
1943 tgl 990 CBC 2924 : node->nextchild = NULL;
1943 tgl 991 GIC 2924 : node->allowInCritSection = false;
1943 tgl 992 ECB : }
9770 scrappy 993 :
994 : VALGRIND_CREATE_MEMPOOL(node, 0, false);
9770 scrappy 995 GIC 6280971 : }
9770 scrappy 996 ECB :
997 : /*
8320 tgl 998 : * MemoryContextAlloc
999 : * Allocate space within the specified context.
1000 : *
1001 : * This could be turned into a macro, but we'd have to import
1002 : * nodes/memnodes.h into postgres.h which seems a bad idea.
1003 : */
1004 : void *
8320 tgl 1005 GIC 115848245 : MemoryContextAlloc(MemoryContext context, Size size)
9770 scrappy 1006 ECB : {
3574 noah 1007 : void *ret;
1008 :
163 peter 1009 GNC 115848245 : Assert(MemoryContextIsValid(context));
3292 heikki.linnakangas 1010 CBC 115848245 : AssertNotInCriticalSection(context);
1011 :
8097 tgl 1012 115848245 : if (!AllocSizeIsValid(size))
3363 tgl 1013 UIC 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
8320 tgl 1014 EUB :
4341 heikki.linnakangas 1015 GBC 115848245 : context->isReset = false;
1016 :
2040 peter_e 1017 GIC 115848245 : ret = context->methods->alloc(context, size);
1836 tgl 1018 CBC 115848245 : if (unlikely(ret == NULL))
1019 : {
2992 rhaas 1020 LBC 0 : MemoryContextStats(TopMemoryContext);
1021 :
1836 tgl 1022 ECB : /*
1836 tgl 1023 EUB : * Here, and elsewhere in this module, we show the target context's
1836 tgl 1024 ECB : * "name" but not its "ident" (if any) in user-visible error messages.
1025 : * The "ident" string might contain security-sensitive data, such as
1026 : * values in SQL commands.
1027 : */
2992 rhaas 1028 LBC 0 : ereport(ERROR,
2992 rhaas 1029 EUB : (errcode(ERRCODE_OUT_OF_MEMORY),
1030 : errmsg("out of memory"),
1031 : errdetail("Failed on request of size %zu in memory context \"%s\".",
1836 tgl 1032 ECB : size, context->name)));
1033 : }
2992 rhaas 1034 EUB :
3574 noah 1035 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1036 :
3574 noah 1037 GIC 115848245 : return ret;
1038 : }
9770 scrappy 1039 ECB :
1040 : /*
1041 : * MemoryContextAllocZero
1042 : * Like MemoryContextAlloc, but clears allocated memory
1043 : *
7455 bruce 1044 : * We could just call MemoryContextAlloc then clear the memory, but this
1045 : * is a very common combination, so we provide the combined operation.
1046 : */
1047 : void *
7419 tgl 1048 GIC 30821341 : MemoryContextAllocZero(MemoryContext context, Size size)
1049 : {
1050 : void *ret;
1051 :
163 peter 1052 GNC 30821341 : Assert(MemoryContextIsValid(context));
3292 heikki.linnakangas 1053 GIC 30821341 : AssertNotInCriticalSection(context);
7455 bruce 1054 ECB :
7455 bruce 1055 GIC 30821341 : if (!AllocSizeIsValid(size))
3363 tgl 1056 UIC 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
1057 :
4338 tgl 1058 CBC 30821341 : context->isReset = false;
1059 :
2040 peter_e 1060 30821341 : ret = context->methods->alloc(context, size);
1836 tgl 1061 30821341 : if (unlikely(ret == NULL))
2992 rhaas 1062 ECB : {
2992 rhaas 1063 LBC 0 : MemoryContextStats(TopMemoryContext);
2992 rhaas 1064 UIC 0 : ereport(ERROR,
1065 : (errcode(ERRCODE_OUT_OF_MEMORY),
1066 : errmsg("out of memory"),
1067 : errdetail("Failed on request of size %zu in memory context \"%s\".",
1068 : size, context->name)));
1069 : }
1070 :
1071 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1072 :
7419 tgl 1073 GIC 271268768 : MemSetAligned(ret, 0, size);
1074 :
1075 30821341 : return ret;
1076 : }
1077 :
1078 : /*
1079 : * MemoryContextAllocZeroAligned
1080 : * MemoryContextAllocZero where length is suitable for MemSetLoop
1081 : *
1082 : * This might seem overly specialized, but it's not because newNode()
1083 : * is so often called with compile-time-constant sizes.
1084 : */
1085 : void *
1086 82397508 : MemoryContextAllocZeroAligned(MemoryContext context, Size size)
1087 : {
1088 : void *ret;
1089 :
163 peter 1090 GNC 82397508 : Assert(MemoryContextIsValid(context));
3292 heikki.linnakangas 1091 GIC 82397508 : AssertNotInCriticalSection(context);
1092 :
7419 tgl 1093 82397508 : if (!AllocSizeIsValid(size))
3363 tgl 1094 UIC 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
1095 :
4338 tgl 1096 GIC 82397508 : context->isReset = false;
1097 :
2040 peter_e 1098 82397508 : ret = context->methods->alloc(context, size);
1836 tgl 1099 CBC 82397508 : if (unlikely(ret == NULL))
1100 : {
2992 rhaas 1101 UIC 0 : MemoryContextStats(TopMemoryContext);
1102 0 : ereport(ERROR,
1103 : (errcode(ERRCODE_OUT_OF_MEMORY),
1104 : errmsg("out of memory"),
1105 : errdetail("Failed on request of size %zu in memory context \"%s\".",
1836 tgl 1106 ECB : size, context->name)));
1107 : }
1108 :
3574 noah 1109 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
7419 tgl 1110 :
7452 bruce 1111 CBC 887554798 : MemSetLoop(ret, 0, size);
7419 tgl 1112 ECB :
7455 bruce 1113 CBC 82397508 : return ret;
7455 bruce 1114 ECB : }
1115 :
2991 rhaas 1116 : /*
1117 : * MemoryContextAllocExtended
1118 : * Allocate space within the specified context using the given flags.
1119 : */
1120 : void *
2991 rhaas 1121 CBC 3024507 : MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
1122 : {
2991 rhaas 1123 ECB : void *ret;
1124 :
163 peter 1125 GNC 3024507 : Assert(MemoryContextIsValid(context));
2991 rhaas 1126 CBC 3024507 : AssertNotInCriticalSection(context);
1127 :
177 tgl 1128 GNC 3024507 : if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) :
1129 : AllocSizeIsValid(size)))
2991 rhaas 1130 UIC 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
1131 :
2991 rhaas 1132 CBC 3024507 : context->isReset = false;
2991 rhaas 1133 ECB :
2040 peter_e 1134 GIC 3024507 : ret = context->methods->alloc(context, size);
1836 tgl 1135 3024507 : if (unlikely(ret == NULL))
1136 : {
2991 rhaas 1137 LBC 0 : if ((flags & MCXT_ALLOC_NO_OOM) == 0)
1138 : {
2991 rhaas 1139 UIC 0 : MemoryContextStats(TopMemoryContext);
1140 0 : ereport(ERROR,
1141 : (errcode(ERRCODE_OUT_OF_MEMORY),
1142 : errmsg("out of memory"),
1143 : errdetail("Failed on request of size %zu in memory context \"%s\".",
1144 : size, context->name)));
1145 : }
1146 0 : return NULL;
2991 rhaas 1147 ECB : }
1148 :
1149 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1150 :
2991 rhaas 1151 CBC 3024507 : if ((flags & MCXT_ALLOC_ZERO) != 0)
1152 1086951 : MemSetAligned(ret, 0, size);
1153 :
1154 3024507 : return ret;
2991 rhaas 1155 EUB : }
1156 :
733 fujii 1157 ECB : /*
1158 : * HandleLogMemoryContextInterrupt
1159 : * Handle receipt of an interrupt indicating logging of memory
1160 : * contexts.
1161 : *
733 fujii 1162 EUB : * All the actual work is deferred to ProcessLogMemoryContextInterrupt(),
1163 : * because we cannot safely emit a log message inside the signal handler.
1164 : */
1165 : void
733 fujii 1166 GIC 9 : HandleLogMemoryContextInterrupt(void)
1167 : {
1168 9 : InterruptPending = true;
1169 9 : LogMemoryContextPending = true;
733 fujii 1170 EUB : /* latch will be set by procsignal_sigusr1_handler */
733 fujii 1171 GIC 9 : }
1172 :
1173 : /*
1174 : * ProcessLogMemoryContextInterrupt
1175 : * Perform logging of memory contexts of this backend process.
1176 : *
1177 : * Any backend that participates in ProcSignal signaling must arrange
1178 : * to call this function if we see LogMemoryContextPending set.
733 fujii 1179 ECB : * It is called from CHECK_FOR_INTERRUPTS(), which is enough because
1180 : * the target process for logging of memory contexts is a backend.
1181 : */
1182 : void
733 fujii 1183 GIC 9 : ProcessLogMemoryContextInterrupt(void)
1184 : {
1185 9 : LogMemoryContextPending = false;
1186 :
1187 : /*
1188 : * Use LOG_SERVER_ONLY to prevent this message from being sent to the
1189 : * connected client.
436 fujii 1190 ECB : */
436 fujii 1191 GIC 9 : ereport(LOG_SERVER_ONLY,
1192 : (errhidestmt(true),
1193 : errhidecontext(true),
436 fujii 1194 ECB : errmsg("logging memory contexts of PID %d", MyProcPid)));
733 1195 :
1196 : /*
1197 : * When a backend process is consuming huge memory, logging all its memory
733 fujii 1198 EUB : * contexts might overrun available disk space. To prevent this, we limit
1199 : * the number of child contexts to log per parent to 100.
733 fujii 1200 ECB : *
1201 : * As with MemoryContextStats(), we suppose that practical cases where the
1202 : * dump gets long will typically be huge numbers of siblings under the
1203 : * same parent context; while the additional debugging value from seeing
1204 : * details about individual siblings beyond 100 will not be large.
733 fujii 1205 EUB : */
733 fujii 1206 GBC 9 : MemoryContextStatsDetail(TopMemoryContext, 100, false);
733 fujii 1207 GIC 9 : }
1208 :
1209 : void *
3708 alvherre 1210 301409001 : palloc(Size size)
1211 : {
1212 : /* duplicates MemoryContextAlloc to avoid increased overhead */
1213 : void *ret;
1836 tgl 1214 301409001 : MemoryContext context = CurrentMemoryContext;
3574 noah 1215 ECB :
163 peter 1216 GNC 301409001 : Assert(MemoryContextIsValid(context));
1836 tgl 1217 CBC 301409001 : AssertNotInCriticalSection(context);
1218 :
3708 alvherre 1219 GIC 301409001 : if (!AllocSizeIsValid(size))
3363 tgl 1220 UIC 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
1221 :
1836 tgl 1222 GIC 301409001 : context->isReset = false;
1223 :
1224 301409001 : ret = context->methods->alloc(context, size);
1225 301409001 : if (unlikely(ret == NULL))
1226 : {
2992 rhaas 1227 UIC 0 : MemoryContextStats(TopMemoryContext);
2992 rhaas 1228 LBC 0 : ereport(ERROR,
1229 : (errcode(ERRCODE_OUT_OF_MEMORY),
1230 : errmsg("out of memory"),
1231 : errdetail("Failed on request of size %zu in memory context \"%s\".",
1836 tgl 1232 ECB : size, context->name)));
2992 rhaas 1233 : }
1234 :
1836 tgl 1235 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
3574 noah 1236 EUB :
3574 noah 1237 GIC 301409001 : return ret;
3708 alvherre 1238 ECB : }
1239 :
1240 : void *
3708 alvherre 1241 CBC 109784122 : palloc0(Size size)
1242 : {
3708 alvherre 1243 EUB : /* duplicates MemoryContextAllocZero to avoid increased overhead */
1244 : void *ret;
1836 tgl 1245 GIC 109784122 : MemoryContext context = CurrentMemoryContext;
1246 :
163 peter 1247 GNC 109784122 : Assert(MemoryContextIsValid(context));
1836 tgl 1248 GIC 109784122 : AssertNotInCriticalSection(context);
1249 :
3708 alvherre 1250 109784122 : if (!AllocSizeIsValid(size))
3363 tgl 1251 UIC 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
1252 :
1836 tgl 1253 CBC 109784122 : context->isReset = false;
1254 :
1255 109784122 : ret = context->methods->alloc(context, size);
1836 tgl 1256 GIC 109784122 : if (unlikely(ret == NULL))
1257 : {
2992 rhaas 1258 UIC 0 : MemoryContextStats(TopMemoryContext);
1259 0 : ereport(ERROR,
1260 : (errcode(ERRCODE_OUT_OF_MEMORY),
1261 : errmsg("out of memory"),
1262 : errdetail("Failed on request of size %zu in memory context \"%s\".",
1836 tgl 1263 ECB : size, context->name)));
1264 : }
1265 :
1266 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
3708 alvherre 1267 :
3708 alvherre 1268 CBC 1138658472 : MemSetAligned(ret, 0, size);
1269 :
1270 109784122 : return ret;
1271 : }
3708 alvherre 1272 EUB :
1273 : void *
2928 fujii 1274 CBC 712983 : palloc_extended(Size size, int flags)
1275 : {
2928 fujii 1276 ECB : /* duplicates MemoryContextAllocExtended to avoid increased overhead */
1277 : void *ret;
1836 tgl 1278 GIC 712983 : MemoryContext context = CurrentMemoryContext;
2928 fujii 1279 EUB :
163 peter 1280 GNC 712983 : Assert(MemoryContextIsValid(context));
1836 tgl 1281 GBC 712983 : AssertNotInCriticalSection(context);
2928 fujii 1282 EUB :
177 tgl 1283 GNC 712983 : if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) :
1284 : AllocSizeIsValid(size)))
2928 fujii 1285 UIC 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
1286 :
1836 tgl 1287 GIC 712983 : context->isReset = false;
2928 fujii 1288 EUB :
1836 tgl 1289 GIC 712983 : ret = context->methods->alloc(context, size);
1290 712983 : if (unlikely(ret == NULL))
1291 : {
2928 fujii 1292 UIC 0 : if ((flags & MCXT_ALLOC_NO_OOM) == 0)
2928 fujii 1293 ECB : {
2928 fujii 1294 LBC 0 : MemoryContextStats(TopMemoryContext);
2928 fujii 1295 UIC 0 : ereport(ERROR,
2928 fujii 1296 ECB : (errcode(ERRCODE_OUT_OF_MEMORY),
1297 : errmsg("out of memory"),
1298 : errdetail("Failed on request of size %zu in memory context \"%s\".",
1299 : size, context->name)));
1300 : }
2928 fujii 1301 UIC 0 : return NULL;
1302 : }
1303 :
1304 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1305 :
2928 fujii 1306 GIC 712983 : if ((flags & MCXT_ALLOC_ZERO) != 0)
1307 2637 : MemSetAligned(ret, 0, size);
2928 fujii 1308 ECB :
2928 fujii 1309 GIC 712983 : return ret;
2928 fujii 1310 ECB : }
1311 :
1312 : /*
1313 : * MemoryContextAllocAligned
1314 : * Allocate 'size' bytes of memory in 'context' aligned to 'alignto'
1315 : * bytes.
1316 : *
1317 : * Currently, we align addresses by requesting additional bytes from the
1318 : * MemoryContext's standard allocator function and then aligning the returned
1319 : * address by the required alignment. This means that the given MemoryContext
1320 : * must support providing us with a chunk of memory that's larger than 'size'.
1321 : * For allocators such as Slab, that's not going to work, as slab only allows
1322 : * chunks of the size that's specified when the context is created.
1323 : *
1324 : * 'alignto' must be a power of 2.
1325 : * 'flags' may be 0 or set the same as MemoryContextAllocExtended().
1326 : */
1327 : void *
108 drowley 1328 GNC 1214613 : MemoryContextAllocAligned(MemoryContext context,
1329 : Size size, Size alignto, int flags)
1330 : {
1331 : MemoryChunk *alignedchunk;
1332 : Size alloc_size;
1333 : void *unaligned;
1334 : void *aligned;
1335 :
1336 : /* wouldn't make much sense to waste that much space */
1337 1214613 : Assert(alignto < (128 * 1024 * 1024));
1338 :
1339 : /* ensure alignto is a power of 2 */
1340 1214613 : Assert((alignto & (alignto - 1)) == 0);
1341 :
1342 : /*
1343 : * If the alignment requirements are less than what we already guarantee
1344 : * then just use the standard allocation function.
1345 : */
1346 1214613 : if (unlikely(alignto <= MAXIMUM_ALIGNOF))
108 drowley 1347 UNC 0 : return MemoryContextAllocExtended(context, size, flags);
1348 :
1349 : /*
1350 : * We implement aligned pointers by simply allocating enough memory for
1351 : * the requested size plus the alignment and an additional "redirection"
1352 : * MemoryChunk. This additional MemoryChunk is required for operations
1353 : * such as pfree when used on the pointer returned by this function. We
1354 : * use this redirection MemoryChunk in order to find the pointer to the
1355 : * memory that was returned by the MemoryContextAllocExtended call below.
1356 : * We do that by "borrowing" the block offset field and instead of using
1357 : * that to find the offset into the owning block, we use it to find the
1358 : * original allocated address.
1359 : *
1360 : * Here we must allocate enough extra memory so that we can still align
1361 : * the pointer returned by MemoryContextAllocExtended and also have enough
1362 : * space for the redirection MemoryChunk. Since allocations will already
1363 : * be at least aligned by MAXIMUM_ALIGNOF, we can subtract that amount
1364 : * from the allocation size to save a little memory.
1365 : */
108 drowley 1366 GNC 1214613 : alloc_size = size + PallocAlignedExtraBytes(alignto);
1367 :
1368 : #ifdef MEMORY_CONTEXT_CHECKING
1369 : /* ensure there's space for a sentinal byte */
1370 1214613 : alloc_size += 1;
1371 : #endif
1372 :
1373 : /* perform the actual allocation */
1374 1214613 : unaligned = MemoryContextAllocExtended(context, alloc_size, flags);
1375 :
1376 : /* set the aligned pointer */
1377 1214613 : aligned = (void *) TYPEALIGN(alignto, (char *) unaligned +
1378 : sizeof(MemoryChunk));
1379 :
1380 1214613 : alignedchunk = PointerGetMemoryChunk(aligned);
1381 :
1382 : /*
1383 : * We set the redirect MemoryChunk so that the block offset calculation is
1384 : * used to point back to the 'unaligned' allocated chunk. This allows us
1385 : * to use MemoryChunkGetBlock() to find the unaligned chunk when we need
1386 : * to perform operations such as pfree() and repalloc().
1387 : *
1388 : * We store 'alignto' in the MemoryChunk's 'value' so that we know what
1389 : * the alignment was set to should we ever be asked to realloc this
1390 : * pointer.
1391 : */
1392 1214613 : MemoryChunkSetHdrMask(alignedchunk, unaligned, alignto,
1393 : MCTX_ALIGNED_REDIRECT_ID);
1394 :
1395 : /* double check we produced a correctly aligned pointer */
1396 1214613 : Assert((void *) TYPEALIGN(alignto, aligned) == aligned);
1397 :
1398 : #ifdef MEMORY_CONTEXT_CHECKING
1399 1214613 : alignedchunk->requested_size = size;
1400 : /* set mark to catch clobber of "unused" space */
1401 1214613 : set_sentinel(aligned, size);
1402 : #endif
1403 :
1404 : /* Mark the bytes before the redirection header as noaccess */
1405 : VALGRIND_MAKE_MEM_NOACCESS(unaligned,
1406 : (char *) alignedchunk - (char *) unaligned);
1407 1214613 : return aligned;
1408 : }
1409 :
1410 : /*
1411 : * palloc_aligned
1412 : * Allocate 'size' bytes returning a pointer that's aligned to the
1413 : * 'alignto' boundary.
1414 : *
1415 : * Currently, we align addresses by requesting additional bytes from the
1416 : * MemoryContext's standard allocator function and then aligning the returned
1417 : * address by the required alignment. This means that the given MemoryContext
1418 : * must support providing us with a chunk of memory that's larger than 'size'.
1419 : * For allocators such as Slab, that's not going to work, as slab only allows
1420 : * chunks of the size that's specified when the context is created.
1421 : *
1422 : * 'alignto' must be a power of 2.
1423 : * 'flags' may be 0 or set the same as MemoryContextAllocExtended().
1424 : */
1425 : void *
1426 1214603 : palloc_aligned(Size size, Size alignto, int flags)
1427 : {
1428 1214603 : return MemoryContextAllocAligned(CurrentMemoryContext, size, alignto, flags);
1429 : }
1430 :
1431 : /*
8320 tgl 1432 ECB : * pfree
1433 : * Release an allocated chunk.
1434 : */
1435 : void
8320 tgl 1436 GIC 271884542 : pfree(void *pointer)
1437 : {
1438 : #ifdef USE_VALGRIND
1439 : MemoryContextMethodID method = GetMemoryChunkMethodID(pointer);
1440 : MemoryContext context = GetMemoryChunkContext(pointer);
1441 : #endif
1442 :
223 drowley 1443 GNC 271884542 : MCXT_METHOD(pointer, free_p) (pointer);
1444 :
1445 : #ifdef USE_VALGRIND
1446 : if (method != MCTX_ALIGNED_REDIRECT_ID)
1447 : VALGRIND_MEMPOOL_FREE(context, pointer);
1448 : #endif
9770 scrappy 1449 GIC 271884542 : }
1450 :
9770 scrappy 1451 ECB : /*
1452 : * repalloc
6882 tgl 1453 : * Adjust the size of a previously allocated chunk.
1454 : */
1455 : void *
8320 tgl 1456 GIC 2810796 : repalloc(void *pointer, Size size)
1457 : {
1458 : #ifdef USE_VALGRIND
1459 : MemoryContextMethodID method = GetMemoryChunkMethodID(pointer);
1460 : #endif
1461 : #if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
2232 andres 1462 2810796 : MemoryContext context = GetMemoryChunkContext(pointer);
1463 : #endif
3574 noah 1464 ECB : void *ret;
1465 :
3574 noah 1466 GIC 2810796 : if (!AllocSizeIsValid(size))
3363 tgl 1467 UIC 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
1468 :
3292 heikki.linnakangas 1469 GIC 2810796 : AssertNotInCriticalSection(context);
1470 :
1471 : /* isReset must be false already */
3573 noah 1472 2810796 : Assert(!context->isReset);
1473 :
223 drowley 1474 GNC 2810796 : ret = MCXT_METHOD(pointer, realloc) (pointer, size);
1836 tgl 1475 GIC 2810796 : if (unlikely(ret == NULL))
1476 : {
223 drowley 1477 UNC 0 : MemoryContext cxt = GetMemoryChunkContext(pointer);
1478 :
2583 tgl 1479 UIC 0 : MemoryContextStats(TopMemoryContext);
2992 rhaas 1480 0 : ereport(ERROR,
2992 rhaas 1481 ECB : (errcode(ERRCODE_OUT_OF_MEMORY),
1482 : errmsg("out of memory"),
1483 : errdetail("Failed on request of size %zu in memory context \"%s\".",
1484 : size, cxt->name)));
1485 : }
1486 :
1487 : #ifdef USE_VALGRIND
1488 : if (method != MCTX_ALIGNED_REDIRECT_ID)
1489 : VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1490 : #endif
1491 :
3573 noah 1492 GNC 2810796 : return ret;
1493 : }
1494 :
1495 : /*
1496 : * repalloc_extended
1497 : * Adjust the size of a previously allocated chunk,
1498 : * with HUGE and NO_OOM options.
1499 : */
1500 : void *
177 tgl 1501 45054 : repalloc_extended(void *pointer, Size size, int flags)
1502 : {
1503 : #if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
1504 45054 : MemoryContext context = GetMemoryChunkContext(pointer);
1505 : #endif
1506 : void *ret;
1507 :
1508 45054 : if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) :
1509 : AllocSizeIsValid(size)))
177 tgl 1510 UNC 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
1511 :
177 tgl 1512 GNC 45054 : AssertNotInCriticalSection(context);
1513 :
1514 : /* isReset must be false already */
1515 45054 : Assert(!context->isReset);
1516 :
1517 45054 : ret = MCXT_METHOD(pointer, realloc) (pointer, size);
1518 45054 : if (unlikely(ret == NULL))
1519 : {
177 tgl 1520 UNC 0 : if ((flags & MCXT_ALLOC_NO_OOM) == 0)
1521 : {
1522 0 : MemoryContext cxt = GetMemoryChunkContext(pointer);
1523 :
1524 0 : MemoryContextStats(TopMemoryContext);
1525 0 : ereport(ERROR,
1526 : (errcode(ERRCODE_OUT_OF_MEMORY),
1527 : errmsg("out of memory"),
1528 : errdetail("Failed on request of size %zu in memory context \"%s\".",
1529 : size, cxt->name)));
1530 : }
1531 0 : return NULL;
177 tgl 1532 ECB : }
1533 :
1534 : VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1535 :
177 tgl 1536 CBC 45054 : return ret;
1537 : }
148 peter 1538 ECB :
1539 : /*
1540 : * repalloc0
1541 : * Adjust the size of a previously allocated chunk and zero out the added
1542 : * space.
1543 : */
1544 : void *
148 peter 1545 GNC 91465 : repalloc0(void *pointer, Size oldsize, Size size)
1546 : {
1547 : void *ret;
1548 :
1549 : /* catch wrong argument order */
1550 91465 : if (unlikely(oldsize > size))
148 peter 1551 UNC 0 : elog(ERROR, "invalid repalloc0 call: oldsize %zu, new size %zu",
1552 : oldsize, size);
1553 :
148 peter 1554 GNC 91465 : ret = repalloc(pointer, size);
1555 91465 : memset((char *) ret + oldsize, 0, (size - oldsize));
1556 91465 : return ret;
1557 : }
1558 :
3573 noah 1559 ECB : /*
1560 : * MemoryContextAllocHuge
1561 : * Allocate (possibly-expansive) space within the specified context.
3573 noah 1562 EUB : *
1563 : * See considerations in comment at MaxAllocHugeSize.
3573 noah 1564 ECB : */
1565 : void *
3573 noah 1566 CBC 1249 : MemoryContextAllocHuge(MemoryContext context, Size size)
3573 noah 1567 ECB : {
1568 : void *ret;
3573 noah 1569 EUB :
163 peter 1570 GNC 1249 : Assert(MemoryContextIsValid(context));
3292 heikki.linnakangas 1571 GIC 1249 : AssertNotInCriticalSection(context);
1572 :
3573 noah 1573 1249 : if (!AllocHugeSizeIsValid(size))
3363 tgl 1574 UIC 0 : elog(ERROR, "invalid memory alloc request size %zu", size);
1575 :
3573 noah 1576 GIC 1249 : context->isReset = false;
1577 :
2040 peter_e 1578 1249 : ret = context->methods->alloc(context, size);
1836 tgl 1579 CBC 1249 : if (unlikely(ret == NULL))
1580 : {
2992 rhaas 1581 UIC 0 : MemoryContextStats(TopMemoryContext);
1582 0 : ereport(ERROR,
2992 rhaas 1583 ECB : (errcode(ERRCODE_OUT_OF_MEMORY),
1584 : errmsg("out of memory"),
1585 : errdetail("Failed on request of size %zu in memory context \"%s\".",
1586 : size, context->name)));
1587 : }
1588 :
3573 noah 1589 : VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1590 :
3573 noah 1591 GIC 1249 : return ret;
3573 noah 1592 ECB : }
3573 noah 1593 EUB :
1594 : /*
3573 noah 1595 ECB : * repalloc_huge
1596 : * Adjust the size of a previously allocated chunk, permitting a large
1597 : * value. The previous allocation need not have been "huge".
1598 : */
1599 : void *
3573 noah 1600 GBC 44665 : repalloc_huge(void *pointer, Size size)
3573 noah 1601 EUB : {
1602 : /* this one seems not worth its own implementation */
177 tgl 1603 GNC 44665 : return repalloc_extended(pointer, size, MCXT_ALLOC_HUGE);
9770 scrappy 1604 EUB : }
1605 :
8358 tgl 1606 ECB : /*
1607 : * MemoryContextStrdup
8320 1608 : * Like strdup(), but allocate from the specified context
8358 1609 : */
1610 : char *
8320 tgl 1611 GBC 58261563 : MemoryContextStrdup(MemoryContext context, const char *string)
1612 : {
8320 tgl 1613 EUB : char *nstr;
8320 tgl 1614 GBC 58261563 : Size len = strlen(string) + 1;
1615 :
8320 tgl 1616 GIC 58261563 : nstr = (char *) MemoryContextAlloc(context, len);
1617 :
1618 58261563 : memcpy(nstr, string, len);
1619 :
8320 tgl 1620 GBC 58261563 : return nstr;
1621 : }
1622 :
1623 : char *
3708 alvherre 1624 GIC 57001627 : pstrdup(const char *in)
3708 alvherre 1625 ECB : {
3708 alvherre 1626 CBC 57001627 : return MemoryContextStrdup(CurrentMemoryContext, in);
1627 : }
3708 alvherre 1628 ECB :
1629 : /*
1630 : * pnstrdup
1631 : * Like pstrdup(), but append null byte to a
1632 : * not-necessarily-null-terminated input string.
1633 : */
1634 : char *
5398 tgl 1635 GIC 214524 : pnstrdup(const char *in, Size len)
1636 : {
1637 : char *out;
1638 :
2007 andres 1639 214524 : len = strnlen(in, len);
1640 :
2008 1641 214524 : out = palloc(len + 1);
5398 tgl 1642 214524 : memcpy(out, in, len);
1643 214524 : out[len] = '\0';
1644 :
1645 214524 : return out;
1646 : }
2232 peter_e 1647 ECB :
1648 : /*
1649 : * Make copy of string with all trailing newline characters removed.
1650 : */
1651 : char *
2232 peter_e 1652 GIC 163 : pchomp(const char *in)
1653 : {
1654 : size_t n;
1655 :
2232 peter_e 1656 CBC 163 : n = strlen(in);
2232 peter_e 1657 GIC 326 : while (n > 0 && in[n - 1] == '\n')
1658 163 : n--;
2232 peter_e 1659 CBC 163 : return pnstrdup(in, n);
1660 : }
|