Coverage Report

Created: 2026-09-28 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/utils/mmgr/mcxt.c
Line
Count
Source
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
 * A note about Valgrind support: when USE_VALGRIND is defined, we provide
12
 * support for memory leak tracking at the allocation-unit level.  Valgrind
13
 * does leak detection by tracking allocated "chunks", which can be grouped
14
 * into "pools".  The "chunk" terminology is overloaded, since we use that
15
 * word for our allocation units, and it's sometimes important to distinguish
16
 * those from the Valgrind objects that describe them.  To reduce confusion,
17
 * let's use the terms "vchunk" and "vpool" for the Valgrind objects.
18
 *
19
 * We use a separate vpool for each memory context.  The context-type-specific
20
 * code is responsible for creating and deleting the vpools, and also for
21
 * creating vchunks to cover its management data structures such as block
22
 * headers.  (There must be a vchunk that includes every pointer we want
23
 * Valgrind to consider for leak-tracking purposes.)  This module creates
24
 * and deletes the vchunks that cover the caller-visible allocated chunks.
25
 * However, the context-type-specific code must handle cleaning up those
26
 * vchunks too during memory context reset operations.
27
 *
28
 *
29
 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
30
 * Portions Copyright (c) 1994, Regents of the University of California
31
 *
32
 *
33
 * IDENTIFICATION
34
 *    src/backend/utils/mmgr/mcxt.c
35
 *
36
 *-------------------------------------------------------------------------
37
 */
38
39
#include "postgres.h"
40
41
#include "common/int.h"
42
#include "mb/pg_wchar.h"
43
#include "miscadmin.h"
44
#include "utils/memdebug.h"
45
#include "utils/memutils.h"
46
#include "utils/memutils_internal.h"
47
#include "utils/memutils_memorychunk.h"
48
49
50
static void BogusFree(void *pointer);
51
static void *BogusRealloc(void *pointer, Size size, int flags);
52
static MemoryContext BogusGetChunkContext(void *pointer);
53
static Size BogusGetChunkSpace(void *pointer);
54
55
/*****************************************************************************
56
 *    GLOBAL MEMORY                              *
57
 *****************************************************************************/
58
#define BOGUS_MCTX(id) \
59
  [id].free_p = BogusFree, \
60
  [id].realloc = BogusRealloc, \
61
  [id].get_chunk_context = BogusGetChunkContext, \
62
  [id].get_chunk_space = BogusGetChunkSpace
63
64
static const MemoryContextMethods mcxt_methods[] = {
65
  /* aset.c */
66
  [MCTX_ASET_ID].alloc = AllocSetAlloc,
67
  [MCTX_ASET_ID].free_p = AllocSetFree,
68
  [MCTX_ASET_ID].realloc = AllocSetRealloc,
69
  [MCTX_ASET_ID].reset = AllocSetReset,
70
  [MCTX_ASET_ID].delete_context = AllocSetDelete,
71
  [MCTX_ASET_ID].get_chunk_context = AllocSetGetChunkContext,
72
  [MCTX_ASET_ID].get_chunk_space = AllocSetGetChunkSpace,
73
  [MCTX_ASET_ID].is_empty = AllocSetIsEmpty,
74
  [MCTX_ASET_ID].stats = AllocSetStats,
75
#ifdef MEMORY_CONTEXT_CHECKING
76
  [MCTX_ASET_ID].check = AllocSetCheck,
77
#endif
78
79
  /* generation.c */
80
  [MCTX_GENERATION_ID].alloc = GenerationAlloc,
81
  [MCTX_GENERATION_ID].free_p = GenerationFree,
82
  [MCTX_GENERATION_ID].realloc = GenerationRealloc,
83
  [MCTX_GENERATION_ID].reset = GenerationReset,
84
  [MCTX_GENERATION_ID].delete_context = GenerationDelete,
85
  [MCTX_GENERATION_ID].get_chunk_context = GenerationGetChunkContext,
86
  [MCTX_GENERATION_ID].get_chunk_space = GenerationGetChunkSpace,
87
  [MCTX_GENERATION_ID].is_empty = GenerationIsEmpty,
88
  [MCTX_GENERATION_ID].stats = GenerationStats,
89
#ifdef MEMORY_CONTEXT_CHECKING
90
  [MCTX_GENERATION_ID].check = GenerationCheck,
91
#endif
92
93
  /* slab.c */
94
  [MCTX_SLAB_ID].alloc = SlabAlloc,
95
  [MCTX_SLAB_ID].free_p = SlabFree,
96
  [MCTX_SLAB_ID].realloc = SlabRealloc,
97
  [MCTX_SLAB_ID].reset = SlabReset,
98
  [MCTX_SLAB_ID].delete_context = SlabDelete,
99
  [MCTX_SLAB_ID].get_chunk_context = SlabGetChunkContext,
100
  [MCTX_SLAB_ID].get_chunk_space = SlabGetChunkSpace,
101
  [MCTX_SLAB_ID].is_empty = SlabIsEmpty,
102
  [MCTX_SLAB_ID].stats = SlabStats,
103
#ifdef MEMORY_CONTEXT_CHECKING
104
  [MCTX_SLAB_ID].check = SlabCheck,
105
#endif
106
107
  /* alignedalloc.c */
108
  [MCTX_ALIGNED_REDIRECT_ID].alloc = NULL,  /* not required */
109
  [MCTX_ALIGNED_REDIRECT_ID].free_p = AlignedAllocFree,
110
  [MCTX_ALIGNED_REDIRECT_ID].realloc = AlignedAllocRealloc,
111
  [MCTX_ALIGNED_REDIRECT_ID].reset = NULL,  /* not required */
112
  [MCTX_ALIGNED_REDIRECT_ID].delete_context = NULL, /* not required */
113
  [MCTX_ALIGNED_REDIRECT_ID].get_chunk_context = AlignedAllocGetChunkContext,
114
  [MCTX_ALIGNED_REDIRECT_ID].get_chunk_space = AlignedAllocGetChunkSpace,
115
  [MCTX_ALIGNED_REDIRECT_ID].is_empty = NULL, /* not required */
116
  [MCTX_ALIGNED_REDIRECT_ID].stats = NULL,  /* not required */
117
#ifdef MEMORY_CONTEXT_CHECKING
118
  [MCTX_ALIGNED_REDIRECT_ID].check = NULL,  /* not required */
119
#endif
120
121
  /* bump.c */
122
  [MCTX_BUMP_ID].alloc = BumpAlloc,
123
  [MCTX_BUMP_ID].free_p = BumpFree,
124
  [MCTX_BUMP_ID].realloc = BumpRealloc,
125
  [MCTX_BUMP_ID].reset = BumpReset,
126
  [MCTX_BUMP_ID].delete_context = BumpDelete,
127
  [MCTX_BUMP_ID].get_chunk_context = BumpGetChunkContext,
128
  [MCTX_BUMP_ID].get_chunk_space = BumpGetChunkSpace,
129
  [MCTX_BUMP_ID].is_empty = BumpIsEmpty,
130
  [MCTX_BUMP_ID].stats = BumpStats,
131
#ifdef MEMORY_CONTEXT_CHECKING
132
  [MCTX_BUMP_ID].check = BumpCheck,
133
#endif
134
135
136
  /*
137
   * Reserved and unused IDs should have dummy entries here.  This allows us
138
   * to fail cleanly if a bogus pointer is passed to pfree or the like.  It
139
   * seems sufficient to provide routines for the methods that might get
140
   * invoked from inspection of a chunk (see MCXT_METHOD calls below).
141
   */
142
  BOGUS_MCTX(MCTX_1_RESERVED_GLIBC_ID),
143
  BOGUS_MCTX(MCTX_2_RESERVED_GLIBC_ID),
144
  BOGUS_MCTX(MCTX_8_UNUSED_ID),
145
  BOGUS_MCTX(MCTX_9_UNUSED_ID),
146
  BOGUS_MCTX(MCTX_10_UNUSED_ID),
147
  BOGUS_MCTX(MCTX_11_UNUSED_ID),
148
  BOGUS_MCTX(MCTX_12_UNUSED_ID),
149
  BOGUS_MCTX(MCTX_13_UNUSED_ID),
150
  BOGUS_MCTX(MCTX_14_UNUSED_ID),
151
  BOGUS_MCTX(MCTX_0_RESERVED_UNUSEDMEM_ID),
152
  BOGUS_MCTX(MCTX_15_RESERVED_WIPEDMEM_ID)
153
};
154
155
#undef BOGUS_MCTX
156
157
/*
158
 * CurrentMemoryContext
159
 *    Default memory context for allocations.
160
 */
161
MemoryContext CurrentMemoryContext = NULL;
162
163
/*
164
 * Standard top-level contexts. For a description of the purpose of each
165
 * of these contexts, refer to src/backend/utils/mmgr/README
166
 */
167
MemoryContext TopMemoryContext = NULL;
168
MemoryContext ErrorContext = NULL;
169
MemoryContext PostmasterContext = NULL;
170
MemoryContext CacheMemoryContext = NULL;
171
MemoryContext MessageContext = NULL;
172
MemoryContext TopTransactionContext = NULL;
173
MemoryContext CurTransactionContext = NULL;
174
175
/* This is a transient link to the active portal's memory context: */
176
MemoryContext PortalContext = NULL;
177
178
/* Is memory context logging currently in progress? */
179
static bool LogMemoryContextInProgress = false;
180
181
static void MemoryContextDeleteOnly(MemoryContext context);
182
static void MemoryContextCallResetCallbacks(MemoryContext context);
183
static void MemoryContextStatsInternal(MemoryContext context, int level,
184
                     int max_level, int max_children,
185
                     MemoryContextCounters *totals,
186
                     bool print_to_stderr);
187
static void MemoryContextStatsPrint(MemoryContext context, void *passthru,
188
                  const char *stats_string,
189
                  bool print_to_stderr);
190
pg_noreturn static pg_noinline void add_size_error(Size s1, Size s2);
191
pg_noreturn static pg_noinline void mul_size_error(Size s1, Size s2);
192
193
/*
194
 * You should not do memory allocations within a critical section, because
195
 * an out-of-memory error will be escalated to a PANIC. To enforce that
196
 * rule, the allocation functions Assert that.
197
 */
198
#define AssertNotInCriticalSection(context) \
199
12.3M
  Assert(CritSectionCount == 0 || (context)->allowInCritSection)
200
201
/*
202
 * Call the given function in the MemoryContextMethods for the memory context
203
 * type that 'pointer' belongs to.
204
 */
205
#define MCXT_METHOD(pointer, method) \
206
598k
  mcxt_methods[GetMemoryChunkMethodID(pointer)].method
207
208
/*
209
 * GetMemoryChunkMethodID
210
 *    Return the MemoryContextMethodID from the uint64 chunk header which
211
 *    directly precedes 'pointer'.
212
 */
213
static inline MemoryContextMethodID
214
GetMemoryChunkMethodID(const void *pointer)
215
598k
{
216
598k
  uint64    header;
217
218
  /*
219
   * Try to detect bogus pointers handed to us, poorly though we can.
220
   * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
221
   * allocated chunk.
222
   */
223
598k
  Assert(pointer == (const void *) MAXALIGN(pointer));
224
225
  /* Allow access to the uint64 header */
226
598k
  VALGRIND_MAKE_MEM_DEFINED((char *) pointer - sizeof(uint64), sizeof(uint64));
227
228
598k
  header = *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
229
230
  /* Disallow access to the uint64 header */
231
598k
  VALGRIND_MAKE_MEM_NOACCESS((char *) pointer - sizeof(uint64), sizeof(uint64));
232
233
598k
  return (MemoryContextMethodID) (header & MEMORY_CONTEXT_METHODID_MASK);
234
598k
}
235
236
/*
237
 * GetMemoryChunkHeader
238
 *    Return the uint64 chunk header which directly precedes 'pointer'.
239
 *
240
 * This is only used after GetMemoryChunkMethodID, so no need for error checks.
241
 */
242
static inline uint64
243
GetMemoryChunkHeader(const void *pointer)
244
0
{
245
0
  uint64    header;
246
247
  /* Allow access to the uint64 header */
248
0
  VALGRIND_MAKE_MEM_DEFINED((char *) pointer - sizeof(uint64), sizeof(uint64));
249
250
0
  header = *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
251
252
  /* Disallow access to the uint64 header */
253
0
  VALGRIND_MAKE_MEM_NOACCESS((char *) pointer - sizeof(uint64), sizeof(uint64));
254
255
0
  return header;
256
0
}
257
258
/*
259
 * MemoryContextTraverseNext
260
 *    Helper function to traverse all descendants of a memory context
261
 *    without recursion.
262
 *
263
 * Recursion could lead to out-of-stack errors with deep context hierarchies,
264
 * which would be unpleasant in error cleanup code paths.
265
 *
266
 * To process 'context' and all its descendants, use a loop like this:
267
 *
268
 *     <process 'context'>
269
 *     for (MemoryContext curr = context->firstchild;
270
 *          curr != NULL;
271
 *          curr = MemoryContextTraverseNext(curr, context))
272
 *     {
273
 *         <process 'curr'>
274
 *     }
275
 *
276
 * This visits all the contexts in pre-order, that is a node is visited
277
 * before its children.
278
 */
279
static MemoryContext
280
MemoryContextTraverseNext(MemoryContext curr, MemoryContext top)
281
0
{
282
  /* After processing a node, traverse to its first child if any */
283
0
  if (curr->firstchild != NULL)
284
0
    return curr->firstchild;
285
286
  /*
287
   * After processing a childless node, traverse to its next sibling if
288
   * there is one.  If there isn't, traverse back up to the parent (which
289
   * has already been visited, and now so have all its descendants).  We're
290
   * done if that is "top", otherwise traverse to its next sibling if any,
291
   * otherwise repeat moving up.
292
   */
293
0
  while (curr->nextchild == NULL)
294
0
  {
295
0
    curr = curr->parent;
296
0
    if (curr == top)
297
0
      return NULL;
298
0
  }
299
0
  return curr->nextchild;
300
0
}
301
302
/*
303
 * Support routines to trap use of invalid memory context method IDs
304
 * (from calling pfree or the like on a bogus pointer).  As a possible
305
 * aid in debugging, we report the header word along with the pointer
306
 * address (if we got here, there must be an accessible header word).
307
 */
308
static void
309
BogusFree(void *pointer)
310
0
{
311
0
  elog(ERROR, "pfree called with invalid pointer %p (header 0x%016" PRIx64 ")",
312
0
     pointer, GetMemoryChunkHeader(pointer));
313
0
}
314
315
static void *
316
BogusRealloc(void *pointer, Size size, int flags)
317
0
{
318
0
  elog(ERROR, "repalloc called with invalid pointer %p (header 0x%016" PRIx64 ")",
319
0
     pointer, GetMemoryChunkHeader(pointer));
320
0
  return NULL;       /* keep compiler quiet */
321
0
}
322
323
static MemoryContext
324
BogusGetChunkContext(void *pointer)
325
0
{
326
0
  elog(ERROR, "GetMemoryChunkContext called with invalid pointer %p (header 0x%016" PRIx64 ")",
327
0
     pointer, GetMemoryChunkHeader(pointer));
328
0
  return NULL;       /* keep compiler quiet */
329
0
}
330
331
static Size
332
BogusGetChunkSpace(void *pointer)
333
0
{
334
0
  elog(ERROR, "GetMemoryChunkSpace called with invalid pointer %p (header 0x%016" PRIx64 ")",
335
0
     pointer, GetMemoryChunkHeader(pointer));
336
0
  return 0;         /* keep compiler quiet */
337
0
}
338
339
340
/*****************************************************************************
341
 *    EXPORTED ROUTINES                            *
342
 *****************************************************************************/
343
344
345
/*
346
 * MemoryContextInit
347
 *    Start up the memory-context subsystem.
348
 *
349
 * This must be called before creating contexts or allocating memory in
350
 * contexts.  TopMemoryContext and ErrorContext are initialized here;
351
 * other contexts must be created afterwards.
352
 *
353
 * In normal multi-backend operation, this is called once during
354
 * postmaster startup, and not at all by individual backend startup
355
 * (since the backends inherit an already-initialized context subsystem
356
 * by virtue of being forked off the postmaster).  But in an EXEC_BACKEND
357
 * build, each process must do this for itself.
358
 *
359
 * In a standalone backend this must be called during backend startup.
360
 */
361
void
362
MemoryContextInit(void)
363
2.03k
{
364
2.03k
  Assert(TopMemoryContext == NULL);
365
366
  /*
367
   * First, initialize TopMemoryContext, which is the parent of all others.
368
   */
369
2.03k
  TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
370
2.03k
                       "TopMemoryContext",
371
2.03k
                       ALLOCSET_DEFAULT_SIZES);
372
373
  /*
374
   * Not having any other place to point CurrentMemoryContext, make it point
375
   * to TopMemoryContext.  Caller should change this soon!
376
   */
377
2.03k
  CurrentMemoryContext = TopMemoryContext;
378
379
  /*
380
   * Initialize ErrorContext as an AllocSetContext with slow growth rate ---
381
   * we don't really expect much to be allocated in it. More to the point,
382
   * require it to contain at least 8K at all times. This is the only case
383
   * where retained memory in a context is *essential* --- we want to be
384
   * sure ErrorContext still has some memory even if we've run out
385
   * elsewhere! Also, allow allocations in ErrorContext within a critical
386
   * section. Otherwise a PANIC will cause an assertion failure in the error
387
   * reporting code, before printing out the real cause of the failure.
388
   *
389
   * This should be the last step in this function, as elog.c assumes memory
390
   * management works once ErrorContext is non-null.
391
   */
392
2.03k
  ErrorContext = AllocSetContextCreate(TopMemoryContext,
393
2.03k
                     "ErrorContext",
394
2.03k
                     8 * 1024,
395
2.03k
                     8 * 1024,
396
2.03k
                     8 * 1024);
397
2.03k
  MemoryContextAllowInCriticalSection(ErrorContext, true);
398
2.03k
}
399
400
/*
401
 * MemoryContextReset
402
 *    Release all space allocated within a context and delete all its
403
 *    descendant contexts (but not the named context itself).
404
 */
405
void
406
MemoryContextReset(MemoryContext context)
407
14.9k
{
408
14.9k
  Assert(MemoryContextIsValid(context));
409
410
  /* save a function call in common case where there are no children */
411
14.9k
  if (context->firstchild != NULL)
412
2.03k
    MemoryContextDeleteChildren(context);
413
414
  /* save a function call if no pallocs since startup or last reset */
415
14.9k
  if (!context->isReset)
416
12.4k
    MemoryContextResetOnly(context);
417
14.9k
}
418
419
/*
420
 * MemoryContextResetOnly
421
 *    Release all space allocated within a context.
422
 *    Nothing is done to the context's descendant contexts.
423
 */
424
void
425
MemoryContextResetOnly(MemoryContext context)
426
12.4k
{
427
12.4k
  Assert(MemoryContextIsValid(context));
428
429
  /* Nothing to do if no pallocs since startup or last reset */
430
12.4k
  if (!context->isReset)
431
12.4k
  {
432
12.4k
    MemoryContextCallResetCallbacks(context);
433
434
    /*
435
     * If context->ident points into the context's memory, it will become
436
     * a dangling pointer.  We could prevent that by setting it to NULL
437
     * here, but that would break valid coding patterns that keep the
438
     * ident elsewhere, e.g. in a parent context.  So for now we assume
439
     * the programmer got it right.
440
     */
441
442
12.4k
    context->methods->reset(context);
443
12.4k
    context->isReset = true;
444
12.4k
  }
445
12.4k
}
446
447
/*
448
 * MemoryContextResetChildren
449
 *    Release all space allocated within a context's descendants,
450
 *    but don't delete the contexts themselves.  The named context
451
 *    itself is not touched.
452
 */
453
void
454
MemoryContextResetChildren(MemoryContext context)
455
0
{
456
0
  Assert(MemoryContextIsValid(context));
457
458
0
  for (MemoryContext curr = context->firstchild;
459
0
     curr != NULL;
460
0
     curr = MemoryContextTraverseNext(curr, context))
461
0
  {
462
0
    MemoryContextResetOnly(curr);
463
0
  }
464
0
}
465
466
/*
467
 * MemoryContextDelete
468
 *    Delete a context and its descendants, and release all space
469
 *    allocated therein.
470
 *
471
 * The type-specific delete routine removes all storage for the context,
472
 * but we have to deal with descendant nodes here.
473
 */
474
void
475
MemoryContextDelete(MemoryContext context)
476
2.03k
{
477
2.03k
  MemoryContext curr;
478
479
2.03k
  Assert(MemoryContextIsValid(context));
480
481
  /*
482
   * Delete subcontexts from the bottom up.
483
   *
484
   * Note: Do not use recursion here.  A "stack depth limit exceeded" error
485
   * would be unpleasant if we're already in the process of cleaning up from
486
   * transaction abort.  We also cannot use MemoryContextTraverseNext() here
487
   * because we modify the tree as we go.
488
   */
489
2.03k
  curr = context;
490
2.03k
  for (;;)
491
2.03k
  {
492
2.03k
    MemoryContext parent;
493
494
    /* Descend down until we find a leaf context with no children */
495
2.03k
    while (curr->firstchild != NULL)
496
0
      curr = curr->firstchild;
497
498
    /*
499
     * We're now at a leaf with no children. Free it and continue from the
500
     * parent.  Or if this was the original node, we're all done.
501
     */
502
2.03k
    parent = curr->parent;
503
2.03k
    MemoryContextDeleteOnly(curr);
504
505
2.03k
    if (curr == context)
506
2.03k
      break;
507
0
    curr = parent;
508
0
  }
509
2.03k
}
510
511
/*
512
 * Subroutine of MemoryContextDelete,
513
 * to delete a context that has no children.
514
 * We must also delink the context from its parent, if it has one.
515
 */
516
static void
517
MemoryContextDeleteOnly(MemoryContext context)
518
2.03k
{
519
2.03k
  Assert(MemoryContextIsValid(context));
520
  /* We had better not be deleting TopMemoryContext ... */
521
2.03k
  Assert(context != TopMemoryContext);
522
  /* And not CurrentMemoryContext, either */
523
2.03k
  Assert(context != CurrentMemoryContext);
524
  /* All the children should've been deleted already */
525
2.03k
  Assert(context->firstchild == NULL);
526
527
  /*
528
   * It's not entirely clear whether 'tis better to do this before or after
529
   * delinking the context; but an error in a callback will likely result in
530
   * leaking the whole context (if it's not a root context) if we do it
531
   * after, so let's do it before.
532
   */
533
2.03k
  MemoryContextCallResetCallbacks(context);
534
535
  /*
536
   * We delink the context from its parent before deleting it, so that if
537
   * there's an error we won't have deleted/busted contexts still attached
538
   * to the context tree.  Better a leak than a crash.
539
   */
540
2.03k
  MemoryContextSetParent(context, NULL);
541
542
  /*
543
   * Also reset the context's ident pointer, in case it points into the
544
   * context.  This would only matter if someone tries to get stats on the
545
   * (already unlinked) context, which is unlikely, but let's be safe.
546
   */
547
2.03k
  context->ident = NULL;
548
549
2.03k
  context->methods->delete_context(context);
550
2.03k
}
551
552
/*
553
 * MemoryContextDeleteChildren
554
 *    Delete all the descendants of the named context and release all
555
 *    space allocated therein.  The named context itself is not touched.
556
 */
557
void
558
MemoryContextDeleteChildren(MemoryContext context)
559
2.03k
{
560
2.03k
  Assert(MemoryContextIsValid(context));
561
562
  /*
563
   * MemoryContextDelete will delink the child from me, so just iterate as
564
   * long as there is a child.
565
   */
566
4.07k
  while (context->firstchild != NULL)
567
2.03k
    MemoryContextDelete(context->firstchild);
568
2.03k
}
569
570
/*
571
 * MemoryContextRegisterResetCallback
572
 *    Register a function to be called before next context reset/delete.
573
 *    Such callbacks will be called in reverse order of registration.
574
 *
575
 * The caller is responsible for allocating a MemoryContextCallback struct
576
 * to hold the info about this callback request, and for filling in the
577
 * "func" and "arg" fields in the struct to show what function to call with
578
 * what argument.  Typically the callback struct should be allocated within
579
 * the specified context, since that means it will automatically be freed
580
 * when no longer needed.
581
 *
582
 * Note that callers can assume this cannot fail.
583
 */
584
void
585
MemoryContextRegisterResetCallback(MemoryContext context,
586
                   MemoryContextCallback *cb)
587
0
{
588
0
  Assert(MemoryContextIsValid(context));
589
590
  /* Push onto head so this will be called before older registrants. */
591
0
  cb->next = context->reset_cbs;
592
0
  context->reset_cbs = cb;
593
  /* Mark the context as non-reset (it probably is already). */
594
0
  context->isReset = false;
595
0
}
596
597
/*
598
 * MemoryContextUnregisterResetCallback
599
 *    Undo the effects of MemoryContextRegisterResetCallback.
600
 *
601
 * This can be used if a callback's effects are no longer required
602
 * at some point before the context has been reset/deleted.  It is the
603
 * caller's responsibility to pfree the callback struct (if needed).
604
 *
605
 * An assertion failure occurs if the callback was not registered.
606
 * We could alternatively define that case as a no-op, but that seems too
607
 * likely to mask programming errors such as passing the wrong context.
608
 */
609
void
610
MemoryContextUnregisterResetCallback(MemoryContext context,
611
                   MemoryContextCallback *cb)
612
0
{
613
0
  MemoryContextCallback *prev,
614
0
         *cur;
615
616
0
  Assert(MemoryContextIsValid(context));
617
618
0
  for (prev = NULL, cur = context->reset_cbs; cur != NULL;
619
0
     prev = cur, cur = cur->next)
620
0
  {
621
0
    if (cur != cb)
622
0
      continue;
623
0
    if (prev)
624
0
      prev->next = cur->next;
625
0
    else
626
0
      context->reset_cbs = cur->next;
627
0
    return;
628
0
  }
629
0
  Assert(false);
630
0
}
631
632
/*
633
 * MemoryContextCallResetCallbacks
634
 *    Internal function to call all registered callbacks for context.
635
 */
636
static void
637
MemoryContextCallResetCallbacks(MemoryContext context)
638
14.5k
{
639
14.5k
  MemoryContextCallback *cb;
640
641
  /*
642
   * We pop each callback from the list before calling.  That way, if an
643
   * error occurs inside the callback, we won't try to call it a second time
644
   * in the likely event that we reset or delete the context later.
645
   */
646
14.5k
  while ((cb = context->reset_cbs) != NULL)
647
0
  {
648
0
    context->reset_cbs = cb->next;
649
0
    cb->func(cb->arg);
650
0
  }
651
14.5k
}
652
653
/*
654
 * MemoryContextSetIdentifier
655
 *    Set the identifier string for a memory context.
656
 *
657
 * An identifier can be provided to help distinguish among different contexts
658
 * of the same kind in memory context stats dumps.  The identifier string
659
 * must live at least as long as the context it is for; typically it is
660
 * allocated inside that context, so that it automatically goes away on
661
 * context deletion.  Pass id = NULL to forget any old identifier.
662
 */
663
void
664
MemoryContextSetIdentifier(MemoryContext context, const char *id)
665
4
{
666
4
  Assert(MemoryContextIsValid(context));
667
4
  context->ident = id;
668
4
}
669
670
/*
671
 * MemoryContextSetParent
672
 *    Change a context to belong to a new parent (or no parent).
673
 *
674
 * We provide this as an API function because it is sometimes useful to
675
 * change a context's lifespan after creation.  For example, a context
676
 * might be created underneath a transient context, filled with data,
677
 * and then reparented underneath CacheMemoryContext to make it long-lived.
678
 * In this way no special effort is needed to get rid of the context in case
679
 * a failure occurs before its contents are completely set up.
680
 *
681
 * Callers often assume that this function cannot fail, so don't put any
682
 * elog(ERROR) calls in it.
683
 *
684
 * A possible caller error is to reparent a context under itself, creating
685
 * a loop in the context graph.  We assert here that context != new_parent,
686
 * but checking for multi-level loops seems more trouble than it's worth.
687
 */
688
void
689
MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
690
2.03k
{
691
2.03k
  Assert(MemoryContextIsValid(context));
692
2.03k
  Assert(context != new_parent);
693
694
  /* Fast path if it's got correct parent already */
695
2.03k
  if (new_parent == context->parent)
696
0
    return;
697
698
  /* Delink from existing parent, if any */
699
2.03k
  if (context->parent)
700
2.03k
  {
701
2.03k
    MemoryContext parent = context->parent;
702
703
2.03k
    if (context->prevchild != NULL)
704
0
      context->prevchild->nextchild = context->nextchild;
705
2.03k
    else
706
2.03k
    {
707
2.03k
      Assert(parent->firstchild == context);
708
2.03k
      parent->firstchild = context->nextchild;
709
2.03k
    }
710
711
2.03k
    if (context->nextchild != NULL)
712
0
      context->nextchild->prevchild = context->prevchild;
713
2.03k
  }
714
715
  /* And relink */
716
2.03k
  if (new_parent)
717
0
  {
718
0
    Assert(MemoryContextIsValid(new_parent));
719
0
    context->parent = new_parent;
720
0
    context->prevchild = NULL;
721
0
    context->nextchild = new_parent->firstchild;
722
0
    if (new_parent->firstchild != NULL)
723
0
      new_parent->firstchild->prevchild = context;
724
0
    new_parent->firstchild = context;
725
0
  }
726
2.03k
  else
727
2.03k
  {
728
2.03k
    context->parent = NULL;
729
2.03k
    context->prevchild = NULL;
730
2.03k
    context->nextchild = NULL;
731
2.03k
  }
732
2.03k
}
733
734
/*
735
 * MemoryContextAllowInCriticalSection
736
 *    Allow/disallow allocations in this memory context within a critical
737
 *    section.
738
 *
739
 * Normally, memory allocations are not allowed within a critical section,
740
 * because a failure would lead to PANIC.  There are a few exceptions to
741
 * that, like allocations related to debugging code that is not supposed to
742
 * be enabled in production.  This function can be used to exempt specific
743
 * memory contexts from the assertion in palloc().
744
 */
745
void
746
MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
747
2.03k
{
748
2.03k
  Assert(MemoryContextIsValid(context));
749
750
2.03k
  context->allowInCritSection = allow;
751
2.03k
}
752
753
/*
754
 * GetMemoryChunkContext
755
 *    Given a currently-allocated chunk, determine the MemoryContext that
756
 *    the chunk belongs to.
757
 */
758
MemoryContext
759
GetMemoryChunkContext(void *pointer)
760
3.90k
{
761
3.90k
  return MCXT_METHOD(pointer, get_chunk_context) (pointer);
762
3.90k
}
763
764
/*
765
 * GetMemoryChunkSpace
766
 *    Given a currently-allocated chunk, determine the total space
767
 *    it occupies (including all memory-allocation overhead).
768
 *
769
 * This is useful for measuring the total space occupied by a set of
770
 * allocated chunks.
771
 */
772
Size
773
GetMemoryChunkSpace(void *pointer)
774
0
{
775
0
  return MCXT_METHOD(pointer, get_chunk_space) (pointer);
776
0
}
777
778
/*
779
 * MemoryContextGetParent
780
 *    Get the parent context (if any) of the specified context
781
 */
782
MemoryContext
783
MemoryContextGetParent(MemoryContext context)
784
0
{
785
0
  Assert(MemoryContextIsValid(context));
786
787
0
  return context->parent;
788
0
}
789
790
/*
791
 * MemoryContextIsEmpty
792
 *    Is a memory context empty of any allocated space?
793
 */
794
bool
795
MemoryContextIsEmpty(MemoryContext context)
796
0
{
797
0
  Assert(MemoryContextIsValid(context));
798
799
  /*
800
   * For now, we consider a memory context nonempty if it has any children;
801
   * perhaps this should be changed later.
802
   */
803
0
  if (context->firstchild != NULL)
804
0
    return false;
805
  /* Otherwise use the type-specific inquiry */
806
0
  return context->methods->is_empty(context);
807
0
}
808
809
/*
810
 * Find the memory allocated to blocks for this memory context. If recurse is
811
 * true, also include children.
812
 */
813
Size
814
MemoryContextMemAllocated(MemoryContext context, bool recurse)
815
0
{
816
0
  Size    total = context->mem_allocated;
817
818
0
  Assert(MemoryContextIsValid(context));
819
820
0
  if (recurse)
821
0
  {
822
0
    for (MemoryContext curr = context->firstchild;
823
0
       curr != NULL;
824
0
       curr = MemoryContextTraverseNext(curr, context))
825
0
    {
826
0
      total += curr->mem_allocated;
827
0
    }
828
0
  }
829
830
0
  return total;
831
0
}
832
833
/*
834
 * Return the memory consumption statistics about the given context and its
835
 * children.
836
 */
837
void
838
MemoryContextMemConsumed(MemoryContext context,
839
             MemoryContextCounters *consumed)
840
0
{
841
0
  Assert(MemoryContextIsValid(context));
842
843
0
  memset(consumed, 0, sizeof(*consumed));
844
845
  /* Examine the context itself */
846
0
  context->methods->stats(context, NULL, NULL, consumed, false);
847
848
  /* Examine children, using iteration not recursion */
849
0
  for (MemoryContext curr = context->firstchild;
850
0
     curr != NULL;
851
0
     curr = MemoryContextTraverseNext(curr, context))
852
0
  {
853
0
    curr->methods->stats(curr, NULL, NULL, consumed, false);
854
0
  }
855
0
}
856
857
/*
858
 * MemoryContextStats
859
 *    Print statistics about the named context and all its descendants.
860
 *
861
 * This is just a debugging utility, so it's not very fancy.  However, we do
862
 * make some effort to summarize when the output would otherwise be very long.
863
 * The statistics are sent to stderr.
864
 */
865
void
866
MemoryContextStats(MemoryContext context)
867
0
{
868
  /* Hard-wired limits are usually good enough */
869
0
  MemoryContextStatsDetail(context, 100, 100, true);
870
0
}
871
872
/*
873
 * MemoryContextStatsDetail
874
 *
875
 * Entry point for use if you want to vary the number of child contexts shown.
876
 *
877
 * If print_to_stderr is true, print statistics about the memory contexts
878
 * with fprintf(stderr), otherwise use ereport().
879
 */
880
void
881
MemoryContextStatsDetail(MemoryContext context,
882
             int max_level, int max_children,
883
             bool print_to_stderr)
884
{
885
  MemoryContextCounters grand_totals;
886
887
  memset(&grand_totals, 0, sizeof(grand_totals));
888
889
  MemoryContextStatsInternal(context, 1, max_level, max_children,
890
                 &grand_totals, print_to_stderr);
891
892
  if (print_to_stderr)
893
    fprintf(stderr,
894
        "Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used\n",
895
        grand_totals.totalspace, grand_totals.nblocks,
896
        grand_totals.freespace, grand_totals.freechunks,
897
        grand_totals.totalspace - grand_totals.freespace);
898
  else
899
  {
900
    /*
901
     * Use LOG_SERVER_ONLY to prevent the memory contexts from being sent
902
     * to the connected client.
903
     *
904
     * We don't buffer the information about all memory contexts in a
905
     * backend into StringInfo and log it as one message.  That would
906
     * require the buffer to be enlarged, risking an OOM as there could be
907
     * a large number of memory contexts in a backend.  Instead, we log
908
     * one message per memory context.
909
     */
910
    ereport(LOG_SERVER_ONLY,
911
        (errhidestmt(true),
912
         errhidecontext(true),
913
         errmsg_internal("Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used",
914
                 grand_totals.totalspace, grand_totals.nblocks,
915
                 grand_totals.freespace, grand_totals.freechunks,
916
                 grand_totals.totalspace - grand_totals.freespace)));
917
  }
918
}
919
920
/*
921
 * MemoryContextStatsInternal
922
 *    One recursion level for MemoryContextStats
923
 *
924
 * Print stats for this context if possible, but in any case accumulate counts
925
 * into *totals (if not NULL).
926
 */
927
static void
928
MemoryContextStatsInternal(MemoryContext context, int level,
929
               int max_level, int max_children,
930
               MemoryContextCounters *totals,
931
               bool print_to_stderr)
932
0
{
933
0
  MemoryContext child;
934
0
  int     ichild;
935
936
0
  Assert(MemoryContextIsValid(context));
937
938
  /* Examine the context itself */
939
0
  context->methods->stats(context,
940
0
              MemoryContextStatsPrint,
941
0
              &level,
942
0
              totals, print_to_stderr);
943
944
  /*
945
   * Examine children.
946
   *
947
   * If we are past the recursion depth limit or already running low on
948
   * stack, do not print them explicitly but just summarize them. Similarly,
949
   * if there are more than max_children of them, we do not print the rest
950
   * explicitly, but just summarize them.
951
   */
952
0
  child = context->firstchild;
953
0
  ichild = 0;
954
0
  if (level <= max_level && !stack_is_too_deep())
955
0
  {
956
0
    for (; child != NULL && ichild < max_children;
957
0
       child = child->nextchild, ichild++)
958
0
    {
959
0
      MemoryContextStatsInternal(child, level + 1,
960
0
                     max_level, max_children,
961
0
                     totals,
962
0
                     print_to_stderr);
963
0
    }
964
0
  }
965
966
0
  if (child != NULL)
967
0
  {
968
    /* Summarize the rest of the children, avoiding recursion. */
969
0
    MemoryContextCounters local_totals;
970
971
0
    memset(&local_totals, 0, sizeof(local_totals));
972
973
0
    ichild = 0;
974
0
    while (child != NULL)
975
0
    {
976
0
      child->methods->stats(child, NULL, NULL, &local_totals, false);
977
0
      ichild++;
978
0
      child = MemoryContextTraverseNext(child, context);
979
0
    }
980
981
0
    if (print_to_stderr)
982
0
    {
983
0
      for (int i = 0; i < level; i++)
984
0
        fprintf(stderr, "  ");
985
0
      fprintf(stderr,
986
0
          "%d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used\n",
987
0
          ichild,
988
0
          local_totals.totalspace,
989
0
          local_totals.nblocks,
990
0
          local_totals.freespace,
991
0
          local_totals.freechunks,
992
0
          local_totals.totalspace - local_totals.freespace);
993
0
    }
994
0
    else
995
0
      ereport(LOG_SERVER_ONLY,
996
0
          (errhidestmt(true),
997
0
           errhidecontext(true),
998
0
           errmsg_internal("level: %d; %d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used",
999
0
                   level,
1000
0
                   ichild,
1001
0
                   local_totals.totalspace,
1002
0
                   local_totals.nblocks,
1003
0
                   local_totals.freespace,
1004
0
                   local_totals.freechunks,
1005
0
                   local_totals.totalspace - local_totals.freespace)));
1006
1007
0
    if (totals)
1008
0
    {
1009
0
      totals->nblocks += local_totals.nblocks;
1010
0
      totals->freechunks += local_totals.freechunks;
1011
0
      totals->totalspace += local_totals.totalspace;
1012
0
      totals->freespace += local_totals.freespace;
1013
0
    }
1014
0
  }
1015
0
}
1016
1017
/*
1018
 * MemoryContextStatsPrint
1019
 *    Print callback used by MemoryContextStatsInternal
1020
 *
1021
 * For now, the passthru pointer just points to "int level"; later we might
1022
 * make that more complicated.
1023
 */
1024
static void
1025
MemoryContextStatsPrint(MemoryContext context, void *passthru,
1026
            const char *stats_string,
1027
            bool print_to_stderr)
1028
{
1029
  int     level = *(int *) passthru;
1030
  const char *name = context->name;
1031
  const char *ident = context->ident;
1032
  char    truncated_ident[110];
1033
  int     i;
1034
1035
  /*
1036
   * It seems preferable to label dynahash contexts with just the hash table
1037
   * name.  Those are already unique enough, so the "dynahash" part isn't
1038
   * very helpful, and this way is more consistent with pre-v11 practice.
1039
   */
1040
  if (ident && strcmp(name, "dynahash") == 0)
1041
  {
1042
    name = ident;
1043
    ident = NULL;
1044
  }
1045
1046
  truncated_ident[0] = '\0';
1047
1048
  if (ident)
1049
  {
1050
    /*
1051
     * Some contexts may have very long identifiers (e.g., SQL queries).
1052
     * Arbitrarily truncate at 100 bytes, but be careful not to break
1053
     * multibyte characters.  Also, replace ASCII control characters, such
1054
     * as newlines, with spaces.
1055
     */
1056
    int     idlen = strlen(ident);
1057
    bool    truncated = false;
1058
1059
    strcpy(truncated_ident, ": ");
1060
    i = strlen(truncated_ident);
1061
1062
    if (idlen > 100)
1063
    {
1064
      idlen = pg_mbcliplen(ident, idlen, 100);
1065
      truncated = true;
1066
    }
1067
1068
    while (idlen-- > 0)
1069
    {
1070
      unsigned char c = *ident++;
1071
1072
      if (c < ' ')
1073
        c = ' ';
1074
      truncated_ident[i++] = c;
1075
    }
1076
    truncated_ident[i] = '\0';
1077
1078
    if (truncated)
1079
      strcat(truncated_ident, "...");
1080
  }
1081
1082
  if (print_to_stderr)
1083
  {
1084
    for (i = 1; i < level; i++)
1085
      fprintf(stderr, "  ");
1086
    fprintf(stderr, "%s: %s%s\n", name, stats_string, truncated_ident);
1087
  }
1088
  else
1089
    ereport(LOG_SERVER_ONLY,
1090
        (errhidestmt(true),
1091
         errhidecontext(true),
1092
         errmsg_internal("level: %d; %s: %s%s",
1093
                 level, name, stats_string, truncated_ident)));
1094
}
1095
1096
/*
1097
 * MemoryContextCheck
1098
 *    Check all chunks in the named context and its children.
1099
 *
1100
 * This is just a debugging utility, so it's not fancy.
1101
 */
1102
#ifdef MEMORY_CONTEXT_CHECKING
1103
void
1104
MemoryContextCheck(MemoryContext context)
1105
{
1106
  Assert(MemoryContextIsValid(context));
1107
  context->methods->check(context);
1108
1109
  for (MemoryContext curr = context->firstchild;
1110
     curr != NULL;
1111
     curr = MemoryContextTraverseNext(curr, context))
1112
  {
1113
    Assert(MemoryContextIsValid(curr));
1114
    curr->methods->check(curr);
1115
  }
1116
}
1117
#endif
1118
1119
/*
1120
 * MemoryContextCreate
1121
 *    Context-type-independent part of context creation.
1122
 *
1123
 * This is only intended to be called by context-type-specific
1124
 * context creation routines, not by the unwashed masses.
1125
 *
1126
 * The memory context creation procedure goes like this:
1127
 *  1.  Context-type-specific routine makes some initial space allocation,
1128
 *    including enough space for the context header.  If it fails,
1129
 *    it can ereport() with no damage done.
1130
 *  2.  Context-type-specific routine sets up all type-specific fields of
1131
 *    the header (those beyond MemoryContextData proper), as well as any
1132
 *    other management fields it needs to have a fully valid context.
1133
 *    Usually, failure in this step is impossible, but if it's possible
1134
 *    the initial space allocation should be freed before ereport'ing.
1135
 *  3.  Context-type-specific routine calls MemoryContextCreate() to fill in
1136
 *    the generic header fields and link the context into the context tree.
1137
 *  4.  We return to the context-type-specific routine, which finishes
1138
 *    up type-specific initialization.  This routine can now do things
1139
 *    that might fail (like allocate more memory), so long as it's
1140
 *    sure the node is left in a state that delete will handle.
1141
 *
1142
 * node: the as-yet-uninitialized common part of the context header node.
1143
 * tag: NodeTag code identifying the memory context type.
1144
 * method_id: MemoryContextMethodID of the context-type being created.
1145
 * parent: parent context, or NULL if this will be a top-level context.
1146
 * name: name of context (must be statically allocated).
1147
 *
1148
 * Context routines generally assume that MemoryContextCreate can't fail,
1149
 * so this can contain Assert but not elog/ereport.
1150
 */
1151
void
1152
MemoryContextCreate(MemoryContext node,
1153
          NodeTag tag,
1154
          MemoryContextMethodID method_id,
1155
          MemoryContext parent,
1156
          const char *name)
1157
4.08k
{
1158
  /* Creating new memory contexts is not allowed in a critical section */
1159
4.08k
  Assert(CritSectionCount == 0);
1160
1161
  /* Validate parent, to help prevent crazy context linkages */
1162
4.08k
  Assert(parent == NULL || MemoryContextIsValid(parent));
1163
4.08k
  Assert(node != parent);
1164
1165
  /* Initialize all standard fields of memory context header */
1166
4.08k
  node->type = tag;
1167
4.08k
  node->isReset = true;
1168
4.08k
  node->methods = &mcxt_methods[method_id];
1169
4.08k
  node->parent = parent;
1170
4.08k
  node->firstchild = NULL;
1171
4.08k
  node->mem_allocated = 0;
1172
4.08k
  node->prevchild = NULL;
1173
4.08k
  node->name = name;
1174
4.08k
  node->ident = NULL;
1175
4.08k
  node->reset_cbs = NULL;
1176
1177
  /* OK to link node into context tree */
1178
4.08k
  if (parent)
1179
2.04k
  {
1180
2.04k
    node->nextchild = parent->firstchild;
1181
2.04k
    if (parent->firstchild != NULL)
1182
6
      parent->firstchild->prevchild = node;
1183
2.04k
    parent->firstchild = node;
1184
    /* inherit allowInCritSection flag from parent */
1185
2.04k
    node->allowInCritSection = parent->allowInCritSection;
1186
2.04k
  }
1187
2.03k
  else
1188
2.03k
  {
1189
2.03k
    node->nextchild = NULL;
1190
2.03k
    node->allowInCritSection = false;
1191
2.03k
  }
1192
4.08k
}
1193
1194
/*
1195
 * MemoryContextAllocationFailure
1196
 *    For use by MemoryContextMethods implementations to handle when malloc
1197
 *    returns NULL.  The behavior is specific to whether MCXT_ALLOC_NO_OOM
1198
 *    is in 'flags'.
1199
 */
1200
void *
1201
MemoryContextAllocationFailure(MemoryContext context, Size size, int flags)
1202
0
{
1203
0
  if ((flags & MCXT_ALLOC_NO_OOM) == 0)
1204
0
  {
1205
0
    if (TopMemoryContext)
1206
0
      MemoryContextStats(TopMemoryContext);
1207
0
    ereport(ERROR,
1208
0
        (errcode(ERRCODE_OUT_OF_MEMORY),
1209
0
         errmsg("out of memory"),
1210
0
         errdetail("Failed on request of size %zu in memory context \"%s\".",
1211
0
               size, context->name)));
1212
0
  }
1213
0
  return NULL;
1214
0
}
1215
1216
/*
1217
 * MemoryContextSizeFailure
1218
 *    For use by MemoryContextMethods implementations to handle invalid
1219
 *    memory allocation request sizes.
1220
 */
1221
void
1222
MemoryContextSizeFailure(MemoryContext context, Size size, int flags)
1223
0
{
1224
0
  elog(ERROR, "invalid memory alloc request size %zu", size);
1225
0
}
1226
1227
/*
1228
 * MemoryContextAlloc
1229
 *    Allocate space within the specified context.
1230
 *
1231
 * This could be turned into a macro, but we'd have to import
1232
 * nodes/memnodes.h into postgres.h which seems a bad idea.
1233
 */
1234
void *
1235
MemoryContextAlloc(MemoryContext context, Size size)
1236
36.0k
{
1237
36.0k
  void     *ret;
1238
1239
36.0k
  Assert(MemoryContextIsValid(context));
1240
36.0k
  AssertNotInCriticalSection(context);
1241
1242
36.0k
  context->isReset = false;
1243
1244
  /*
1245
   * For efficiency reasons, we purposefully offload the handling of
1246
   * allocation failures to the MemoryContextMethods implementation as this
1247
   * allows these checks to be performed only when an actual malloc needs to
1248
   * be done to request more memory from the OS.  Additionally, not having
1249
   * to execute any instructions after this call allows the compiler to use
1250
   * the sibling call optimization.  If you're considering adding code after
1251
   * this call, consider making it the responsibility of the 'alloc'
1252
   * function instead.
1253
   */
1254
36.0k
  ret = context->methods->alloc(context, size, 0);
1255
1256
36.0k
  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1257
1258
36.0k
  return ret;
1259
36.0k
}
1260
1261
/*
1262
 * MemoryContextAllocZero
1263
 *    Like MemoryContextAlloc, but clears allocated memory
1264
 *
1265
 *  We could just call MemoryContextAlloc then clear the memory, but this
1266
 *  is a very common combination, so we provide the combined operation.
1267
 */
1268
void *
1269
MemoryContextAllocZero(MemoryContext context, Size size)
1270
0
{
1271
0
  void     *ret;
1272
1273
0
  Assert(MemoryContextIsValid(context));
1274
0
  AssertNotInCriticalSection(context);
1275
1276
0
  context->isReset = false;
1277
1278
0
  ret = context->methods->alloc(context, size, 0);
1279
1280
0
  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1281
1282
0
  MemSetAligned(ret, 0, size);
1283
1284
0
  return ret;
1285
0
}
1286
1287
/*
1288
 * MemoryContextAllocExtended
1289
 *    Allocate space within the specified context using the given flags.
1290
 */
1291
void *
1292
MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
1293
226
{
1294
226
  void     *ret;
1295
1296
226
  Assert(MemoryContextIsValid(context));
1297
226
  AssertNotInCriticalSection(context);
1298
1299
226
  if (!((flags & MCXT_ALLOC_HUGE) != 0 ? AllocHugeSizeIsValid(size) :
1300
226
      AllocSizeIsValid(size)))
1301
226
    elog(ERROR, "invalid memory alloc request size %zu", size);
1302
1303
226
  context->isReset = false;
1304
1305
226
  ret = context->methods->alloc(context, size, flags);
1306
226
  if (unlikely(ret == NULL))
1307
0
    return NULL;
1308
1309
226
  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1310
1311
226
  if ((flags & MCXT_ALLOC_ZERO) != 0)
1312
0
    MemSetAligned(ret, 0, size);
1313
1314
226
  return ret;
1315
226
}
1316
1317
/*
1318
 * HandleLogMemoryContextInterrupt
1319
 *    Handle receipt of an interrupt indicating logging of memory
1320
 *    contexts.
1321
 *
1322
 * All the actual work is deferred to ProcessLogMemoryContextInterrupt(),
1323
 * because we cannot safely emit a log message inside the signal handler.
1324
 */
1325
void
1326
HandleLogMemoryContextInterrupt(void)
1327
0
{
1328
0
  InterruptPending = true;
1329
0
  LogMemoryContextPending = true;
1330
  /* latch will be set by procsignal_sigusr1_handler */
1331
0
}
1332
1333
/*
1334
 * ProcessLogMemoryContextInterrupt
1335
 *    Perform logging of memory contexts of this backend process.
1336
 *
1337
 * Any backend that participates in ProcSignal signaling must arrange
1338
 * to call this function if we see LogMemoryContextPending set.
1339
 * It is called from CHECK_FOR_INTERRUPTS(), which is enough because
1340
 * the target process for logging of memory contexts is a backend.
1341
 */
1342
void
1343
ProcessLogMemoryContextInterrupt(void)
1344
0
{
1345
0
  LogMemoryContextPending = false;
1346
1347
  /*
1348
   * Exit immediately if memory context logging is already in progress. This
1349
   * prevents recursive calls, which could occur if logging is requested
1350
   * repeatedly and rapidly, potentially leading to infinite recursion and a
1351
   * crash.
1352
   */
1353
0
  if (LogMemoryContextInProgress)
1354
0
    return;
1355
0
  LogMemoryContextInProgress = true;
1356
1357
0
  PG_TRY();
1358
0
  {
1359
    /*
1360
     * Use LOG_SERVER_ONLY to prevent this message from being sent to the
1361
     * connected client.
1362
     */
1363
0
    ereport(LOG_SERVER_ONLY,
1364
0
        (errhidestmt(true),
1365
0
         errhidecontext(true),
1366
0
         errmsg("logging memory contexts of PID %d", MyProcPid)));
1367
1368
    /*
1369
     * When a backend process is consuming huge memory, logging all its
1370
     * memory contexts might overrun available disk space. To prevent
1371
     * this, we limit the depth of the hierarchy, as well as the number of
1372
     * child contexts to log per parent to 100.
1373
     *
1374
     * As with MemoryContextStats(), we suppose that practical cases where
1375
     * the dump gets long will typically be huge numbers of siblings under
1376
     * the same parent context; while the additional debugging value from
1377
     * seeing details about individual siblings beyond 100 will not be
1378
     * large.
1379
     */
1380
0
    MemoryContextStatsDetail(TopMemoryContext, 100, 100, false);
1381
0
  }
1382
0
  PG_FINALLY();
1383
0
  {
1384
0
    LogMemoryContextInProgress = false;
1385
0
  }
1386
0
  PG_END_TRY();
1387
0
}
1388
1389
void *
1390
palloc(Size size)
1391
6.37M
{
1392
  /* duplicates MemoryContextAlloc to avoid increased overhead */
1393
6.37M
  void     *ret;
1394
6.37M
  MemoryContext context = CurrentMemoryContext;
1395
1396
6.37M
  Assert(MemoryContextIsValid(context));
1397
6.37M
  AssertNotInCriticalSection(context);
1398
1399
6.37M
  context->isReset = false;
1400
1401
  /*
1402
   * For efficiency reasons, we purposefully offload the handling of
1403
   * allocation failures to the MemoryContextMethods implementation as this
1404
   * allows these checks to be performed only when an actual malloc needs to
1405
   * be done to request more memory from the OS.  Additionally, not having
1406
   * to execute any instructions after this call allows the compiler to use
1407
   * the sibling call optimization.  If you're considering adding code after
1408
   * this call, consider making it the responsibility of the 'alloc'
1409
   * function instead.
1410
   */
1411
6.37M
  ret = context->methods->alloc(context, size, 0);
1412
  /* We expect OOM to be handled by the alloc function */
1413
6.37M
  Assert(ret != NULL);
1414
6.37M
  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1415
1416
6.37M
  return ret;
1417
6.37M
}
1418
1419
void *
1420
palloc0(Size size)
1421
5.89M
{
1422
  /* duplicates MemoryContextAllocZero to avoid increased overhead */
1423
5.89M
  void     *ret;
1424
5.89M
  MemoryContext context = CurrentMemoryContext;
1425
1426
5.89M
  Assert(MemoryContextIsValid(context));
1427
5.89M
  AssertNotInCriticalSection(context);
1428
1429
5.89M
  context->isReset = false;
1430
1431
5.89M
  ret = context->methods->alloc(context, size, 0);
1432
  /* We expect OOM to be handled by the alloc function */
1433
5.89M
  Assert(ret != NULL);
1434
5.89M
  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1435
1436
5.89M
  MemSetAligned(ret, 0, size);
1437
1438
5.89M
  return ret;
1439
5.89M
}
1440
1441
void *
1442
palloc_extended(Size size, int flags)
1443
4
{
1444
  /* duplicates MemoryContextAllocExtended to avoid increased overhead */
1445
4
  void     *ret;
1446
4
  MemoryContext context = CurrentMemoryContext;
1447
1448
4
  Assert(MemoryContextIsValid(context));
1449
4
  AssertNotInCriticalSection(context);
1450
1451
4
  context->isReset = false;
1452
1453
4
  ret = context->methods->alloc(context, size, flags);
1454
4
  if (unlikely(ret == NULL))
1455
0
  {
1456
    /* NULL can be returned only when using MCXT_ALLOC_NO_OOM */
1457
0
    Assert(flags & MCXT_ALLOC_NO_OOM);
1458
0
    return NULL;
1459
0
  }
1460
1461
4
  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1462
1463
4
  if ((flags & MCXT_ALLOC_ZERO) != 0)
1464
0
    MemSetAligned(ret, 0, size);
1465
1466
4
  return ret;
1467
4
}
1468
1469
/*
1470
 * MemoryContextAllocAligned
1471
 *    Allocate 'size' bytes of memory in 'context' aligned to 'alignto'
1472
 *    bytes.
1473
 *
1474
 * Currently, we align addresses by requesting additional bytes from the
1475
 * MemoryContext's standard allocator function and then aligning the returned
1476
 * address by the required alignment.  This means that the given MemoryContext
1477
 * must support providing us with a chunk of memory that's larger than 'size'.
1478
 * For allocators such as Slab, that's not going to work, as slab only allows
1479
 * chunks of the size that's specified when the context is created.
1480
 *
1481
 * 'alignto' must be a power of 2.
1482
 * 'flags' may be 0 or set the same as MemoryContextAllocExtended().
1483
 */
1484
void *
1485
MemoryContextAllocAligned(MemoryContext context,
1486
              Size size, Size alignto, int flags)
1487
0
{
1488
0
  MemoryChunk *alignedchunk;
1489
0
  Size    alloc_size;
1490
0
  void     *unaligned;
1491
0
  void     *aligned;
1492
1493
  /*
1494
   * Restrict alignto to ensure that it can fit into the "value" field of
1495
   * the redirection MemoryChunk, and that the distance back to the start of
1496
   * the unaligned chunk will fit into the space available for that.  This
1497
   * isn't a limitation in practice, since it wouldn't make much sense to
1498
   * waste that much space.
1499
   */
1500
0
  Assert(alignto < (128 * 1024 * 1024));
1501
1502
  /* ensure alignto is a power of 2 */
1503
0
  Assert((alignto & (alignto - 1)) == 0);
1504
1505
  /*
1506
   * If the alignment requirements are less than what we already guarantee
1507
   * then just use the standard allocation function.
1508
   */
1509
0
  if (unlikely(alignto <= MAXIMUM_ALIGNOF))
1510
0
    return MemoryContextAllocExtended(context, size, flags);
1511
1512
  /*
1513
   * We implement aligned pointers by simply allocating enough memory for
1514
   * the requested size plus the alignment and an additional "redirection"
1515
   * MemoryChunk.  This additional MemoryChunk is required for operations
1516
   * such as pfree when used on the pointer returned by this function.  We
1517
   * use this redirection MemoryChunk in order to find the pointer to the
1518
   * memory that was returned by the MemoryContextAllocExtended call below.
1519
   * We do that by "borrowing" the block offset field and instead of using
1520
   * that to find the offset into the owning block, we use it to find the
1521
   * original allocated address.
1522
   *
1523
   * Here we must allocate enough extra memory so that we can still align
1524
   * the pointer returned by MemoryContextAllocExtended and also have enough
1525
   * space for the redirection MemoryChunk.  Since allocations will already
1526
   * be at least aligned by MAXIMUM_ALIGNOF, we can subtract that amount
1527
   * from the allocation size to save a little memory.
1528
   */
1529
0
  alloc_size = size + PallocAlignedExtraBytes(alignto);
1530
1531
#ifdef MEMORY_CONTEXT_CHECKING
1532
  /* ensure there's space for a sentinel byte */
1533
  alloc_size += 1;
1534
#endif
1535
1536
  /*
1537
   * Perform the actual allocation, but do not pass down MCXT_ALLOC_ZERO.
1538
   * This ensures that wasted bytes beyond the aligned chunk do not become
1539
   * DEFINED.
1540
   */
1541
0
  unaligned = MemoryContextAllocExtended(context, alloc_size,
1542
0
                       flags & ~MCXT_ALLOC_ZERO);
1543
1544
0
  if (unlikely(unaligned == NULL))
1545
0
  {
1546
    /* NULL can be returned only when using MCXT_ALLOC_NO_OOM */
1547
0
    Assert(flags & MCXT_ALLOC_NO_OOM);
1548
0
    return NULL;
1549
0
  }
1550
1551
  /* compute the aligned pointer */
1552
0
  aligned = (void *) TYPEALIGN(alignto, (char *) unaligned +
1553
0
                 sizeof(MemoryChunk));
1554
1555
0
  alignedchunk = PointerGetMemoryChunk(aligned);
1556
1557
  /*
1558
   * We set the redirect MemoryChunk so that the block offset calculation is
1559
   * used to point back to the 'unaligned' allocated chunk.  This allows us
1560
   * to use MemoryChunkGetBlock() to find the unaligned chunk when we need
1561
   * to perform operations such as pfree() and repalloc().
1562
   *
1563
   * We store 'alignto' in the MemoryChunk's 'value' so that we know what
1564
   * the alignment was set to should we ever be asked to realloc this
1565
   * pointer.
1566
   */
1567
0
  MemoryChunkSetHdrMask(alignedchunk, unaligned, alignto,
1568
0
              MCTX_ALIGNED_REDIRECT_ID);
1569
1570
  /* double check we produced a correctly aligned pointer */
1571
0
  Assert((void *) TYPEALIGN(alignto, aligned) == aligned);
1572
1573
#ifdef MEMORY_CONTEXT_CHECKING
1574
  alignedchunk->requested_size = size;
1575
  /* set mark to catch clobber of "unused" space */
1576
  set_sentinel(aligned, size);
1577
#endif
1578
1579
  /*
1580
   * MemoryContextAllocExtended marked the whole unaligned chunk as a
1581
   * vchunk.  Undo that, instead making just the aligned chunk be a vchunk.
1582
   * This prevents Valgrind from complaining that the vchunk is possibly
1583
   * leaked, since only pointers to the aligned chunk will exist.
1584
   *
1585
   * After these calls, the aligned chunk will be marked UNDEFINED, and all
1586
   * the rest of the unaligned chunk (the redirection chunk header, the
1587
   * padding bytes before it, and any wasted trailing bytes) will be marked
1588
   * NOACCESS, which is what we want.
1589
   */
1590
0
  VALGRIND_MEMPOOL_FREE(context, unaligned);
1591
0
  VALGRIND_MEMPOOL_ALLOC(context, aligned, size);
1592
1593
  /* Now zero (and make DEFINED) just the aligned chunk, if requested */
1594
0
  if ((flags & MCXT_ALLOC_ZERO) != 0)
1595
0
    MemSetAligned(aligned, 0, size);
1596
1597
0
  return aligned;
1598
0
}
1599
1600
/*
1601
 * palloc_aligned
1602
 *    Allocate 'size' bytes returning a pointer that's aligned to the
1603
 *    'alignto' boundary.
1604
 *
1605
 * Currently, we align addresses by requesting additional bytes from the
1606
 * MemoryContext's standard allocator function and then aligning the returned
1607
 * address by the required alignment.  This means that the given MemoryContext
1608
 * must support providing us with a chunk of memory that's larger than 'size'.
1609
 * For allocators such as Slab, that's not going to work, as slab only allows
1610
 * chunks of the size that's specified when the context is created.
1611
 *
1612
 * 'alignto' must be a power of 2.
1613
 * 'flags' may be 0 or set the same as MemoryContextAllocExtended().
1614
 */
1615
void *
1616
palloc_aligned(Size size, Size alignto, int flags)
1617
0
{
1618
0
  return MemoryContextAllocAligned(CurrentMemoryContext, size, alignto, flags);
1619
0
}
1620
1621
/*
1622
 * pfree
1623
 *    Release an allocated chunk.
1624
 */
1625
void
1626
pfree(void *pointer)
1627
583k
{
1628
#ifdef USE_VALGRIND
1629
  MemoryContext context = GetMemoryChunkContext(pointer);
1630
#endif
1631
1632
583k
  MCXT_METHOD(pointer, free_p) (pointer);
1633
1634
583k
  VALGRIND_MEMPOOL_FREE(context, pointer);
1635
583k
}
1636
1637
/*
1638
 * repalloc
1639
 *    Adjust the size of a previously allocated chunk.
1640
 */
1641
void *
1642
repalloc(void *pointer, Size size)
1643
10.8k
{
1644
#if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
1645
  MemoryContext context = GetMemoryChunkContext(pointer);
1646
#endif
1647
10.8k
  void     *ret;
1648
1649
10.8k
  AssertNotInCriticalSection(context);
1650
1651
  /* isReset must be false already */
1652
10.8k
  Assert(!context->isReset);
1653
1654
  /*
1655
   * For efficiency reasons, we purposefully offload the handling of
1656
   * allocation failures to the MemoryContextMethods implementation as this
1657
   * allows these checks to be performed only when an actual malloc needs to
1658
   * be done to request more memory from the OS.  Additionally, not having
1659
   * to execute any instructions after this call allows the compiler to use
1660
   * the sibling call optimization.  If you're considering adding code after
1661
   * this call, consider making it the responsibility of the 'realloc'
1662
   * function instead.
1663
   */
1664
10.8k
  ret = MCXT_METHOD(pointer, realloc) (pointer, size, 0);
1665
1666
10.8k
  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1667
1668
10.8k
  return ret;
1669
10.8k
}
1670
1671
/*
1672
 * repalloc_extended
1673
 *    Adjust the size of a previously allocated chunk,
1674
 *    with HUGE and NO_OOM options.
1675
 */
1676
void *
1677
repalloc_extended(void *pointer, Size size, int flags)
1678
0
{
1679
#if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
1680
  MemoryContext context = GetMemoryChunkContext(pointer);
1681
#endif
1682
0
  void     *ret;
1683
1684
0
  AssertNotInCriticalSection(context);
1685
1686
  /* isReset must be false already */
1687
0
  Assert(!context->isReset);
1688
1689
  /*
1690
   * For efficiency reasons, we purposefully offload the handling of
1691
   * allocation failures to the MemoryContextMethods implementation as this
1692
   * allows these checks to be performed only when an actual malloc needs to
1693
   * be done to request more memory from the OS.  Additionally, not having
1694
   * to execute any instructions after this call allows the compiler to use
1695
   * the sibling call optimization.  If you're considering adding code after
1696
   * this call, consider making it the responsibility of the 'realloc'
1697
   * function instead.
1698
   */
1699
0
  ret = MCXT_METHOD(pointer, realloc) (pointer, size, flags);
1700
0
  if (unlikely(ret == NULL))
1701
0
    return NULL;
1702
1703
0
  VALGRIND_MEMPOOL_CHANGE(context, pointer, ret, size);
1704
1705
0
  return ret;
1706
0
}
1707
1708
/*
1709
 * repalloc0
1710
 *    Adjust the size of a previously allocated chunk and zero out the added
1711
 *    space.
1712
 */
1713
void *
1714
repalloc0(void *pointer, Size oldsize, Size size)
1715
0
{
1716
0
  void     *ret;
1717
1718
  /* catch wrong argument order */
1719
0
  if (unlikely(oldsize > size))
1720
0
    elog(ERROR, "invalid repalloc0 call: oldsize %zu, new size %zu",
1721
0
       oldsize, size);
1722
1723
0
  ret = repalloc(pointer, size);
1724
0
  memset((char *) ret + oldsize, 0, (size - oldsize));
1725
0
  return ret;
1726
0
}
1727
1728
/*
1729
 * Support for safe calculation of memory request sizes
1730
 *
1731
 * These functions perform the requested calculation, but throw error if the
1732
 * result overflows.
1733
 *
1734
 * An important property of these functions is that if an argument was a
1735
 * negative signed int before promotion (implying overflow in calculating it)
1736
 * we will detect that as an error.  That happens because we reject results
1737
 * larger than SIZE_MAX / 2 later on, in the actual allocation step.
1738
 */
1739
Size
1740
add_size(Size s1, Size s2)
1741
0
{
1742
0
  Size    result;
1743
1744
0
  if (unlikely(pg_add_size_overflow(s1, s2, &result)))
1745
0
    add_size_error(s1, s2);
1746
0
  return result;
1747
0
}
1748
1749
pg_noreturn static pg_noinline void
1750
add_size_error(Size s1, Size s2)
1751
0
{
1752
0
  ereport(ERROR,
1753
0
      (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1754
0
       errmsg("invalid memory allocation request size %zu + %zu",
1755
0
          s1, s2)));
1756
0
}
1757
1758
Size
1759
mul_size(Size s1, Size s2)
1760
0
{
1761
0
  Size    result;
1762
1763
0
  if (unlikely(pg_mul_size_overflow(s1, s2, &result)))
1764
0
    mul_size_error(s1, s2);
1765
0
  return result;
1766
0
}
1767
1768
pg_noreturn static pg_noinline void
1769
mul_size_error(Size s1, Size s2)
1770
0
{
1771
0
  ereport(ERROR,
1772
0
      (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1773
0
       errmsg("invalid memory allocation request size %zu * %zu",
1774
0
          s1, s2)));
1775
0
}
1776
1777
/*
1778
 * palloc_mul
1779
 *    Equivalent to palloc(mul_size(s1, s2)).
1780
 */
1781
void *
1782
palloc_mul(Size s1, Size s2)
1783
0
{
1784
  /* inline mul_size() for efficiency */
1785
0
  Size    req;
1786
1787
0
  if (unlikely(pg_mul_size_overflow(s1, s2, &req)))
1788
0
    mul_size_error(s1, s2);
1789
0
  return palloc(req);
1790
0
}
1791
1792
/*
1793
 * palloc0_mul
1794
 *    Equivalent to palloc0(mul_size(s1, s2)).
1795
 *
1796
 * This is comparable to standard calloc's behavior.
1797
 */
1798
void *
1799
palloc0_mul(Size s1, Size s2)
1800
0
{
1801
  /* inline mul_size() for efficiency */
1802
0
  Size    req;
1803
1804
0
  if (unlikely(pg_mul_size_overflow(s1, s2, &req)))
1805
0
    mul_size_error(s1, s2);
1806
0
  return palloc0(req);
1807
0
}
1808
1809
/*
1810
 * palloc_mul_extended
1811
 *    Equivalent to palloc_extended(mul_size(s1, s2), flags).
1812
 */
1813
void *
1814
palloc_mul_extended(Size s1, Size s2, int flags)
1815
0
{
1816
  /* inline mul_size() for efficiency */
1817
0
  Size    req;
1818
1819
0
  if (unlikely(pg_mul_size_overflow(s1, s2, &req)))
1820
0
    mul_size_error(s1, s2);
1821
0
  return palloc_extended(req, flags);
1822
0
}
1823
1824
/*
1825
 * repalloc_mul
1826
 *    Equivalent to repalloc(p, mul_size(s1, s2)).
1827
 */
1828
void *
1829
repalloc_mul(void *p, Size s1, Size s2)
1830
6.43k
{
1831
  /* inline mul_size() for efficiency */
1832
6.43k
  Size    req;
1833
1834
6.43k
  if (unlikely(pg_mul_size_overflow(s1, s2, &req)))
1835
0
    mul_size_error(s1, s2);
1836
6.43k
  return repalloc(p, req);
1837
6.43k
}
1838
1839
/*
1840
 * repalloc_mul_extended
1841
 *    Equivalent to repalloc_extended(p, mul_size(s1, s2), flags).
1842
 */
1843
void *
1844
repalloc_mul_extended(void *p, Size s1, Size s2, int flags)
1845
0
{
1846
  /* inline mul_size() for efficiency */
1847
0
  Size    req;
1848
1849
0
  if (unlikely(pg_mul_size_overflow(s1, s2, &req)))
1850
0
    mul_size_error(s1, s2);
1851
0
  return repalloc_extended(p, req, flags);
1852
0
}
1853
1854
/*
1855
 * MemoryContextAllocHuge
1856
 *    Allocate (possibly-expansive) space within the specified context.
1857
 *
1858
 * See considerations in comment at MaxAllocHugeSize.
1859
 */
1860
void *
1861
MemoryContextAllocHuge(MemoryContext context, Size size)
1862
0
{
1863
0
  void     *ret;
1864
1865
0
  Assert(MemoryContextIsValid(context));
1866
0
  AssertNotInCriticalSection(context);
1867
1868
0
  context->isReset = false;
1869
1870
  /*
1871
   * For efficiency reasons, we purposefully offload the handling of
1872
   * allocation failures to the MemoryContextMethods implementation as this
1873
   * allows these checks to be performed only when an actual malloc needs to
1874
   * be done to request more memory from the OS.  Additionally, not having
1875
   * to execute any instructions after this call allows the compiler to use
1876
   * the sibling call optimization.  If you're considering adding code after
1877
   * this call, consider making it the responsibility of the 'alloc'
1878
   * function instead.
1879
   */
1880
0
  ret = context->methods->alloc(context, size, MCXT_ALLOC_HUGE);
1881
1882
0
  VALGRIND_MEMPOOL_ALLOC(context, ret, size);
1883
1884
0
  return ret;
1885
0
}
1886
1887
/*
1888
 * repalloc_huge
1889
 *    Adjust the size of a previously allocated chunk, permitting a large
1890
 *    value.  The previous allocation need not have been "huge".
1891
 */
1892
void *
1893
repalloc_huge(void *pointer, Size size)
1894
0
{
1895
  /* this one seems not worth its own implementation */
1896
0
  return repalloc_extended(pointer, size, MCXT_ALLOC_HUGE);
1897
0
}
1898
1899
/*
1900
 * MemoryContextStrdup
1901
 *    Like strdup(), but allocate from the specified context
1902
 */
1903
char *
1904
MemoryContextStrdup(MemoryContext context, const char *string)
1905
32.1k
{
1906
32.1k
  char     *nstr;
1907
32.1k
  Size    len = strlen(string) + 1;
1908
1909
32.1k
  nstr = (char *) MemoryContextAlloc(context, len);
1910
1911
32.1k
  memcpy(nstr, string, len);
1912
1913
32.1k
  return nstr;
1914
32.1k
}
1915
1916
char *
1917
pstrdup(const char *in)
1918
32.1k
{
1919
32.1k
  return MemoryContextStrdup(CurrentMemoryContext, in);
1920
32.1k
}
1921
1922
/*
1923
 * pnstrdup
1924
 *    Like pstrdup(), but append null byte to a
1925
 *    not-necessarily-null-terminated input string.
1926
 */
1927
char *
1928
pnstrdup(const char *in, Size len)
1929
0
{
1930
0
  char     *out;
1931
1932
0
  len = strnlen(in, len);
1933
1934
0
  out = palloc(len + 1);
1935
0
  memcpy(out, in, len);
1936
0
  out[len] = '\0';
1937
1938
0
  return out;
1939
0
}
1940
1941
/*
1942
 * Make copy of string with all trailing newline characters removed.
1943
 */
1944
char *
1945
pchomp(const char *in)
1946
0
{
1947
0
  size_t    n;
1948
1949
0
  n = strlen(in);
1950
0
  while (n > 0 && in[n - 1] == '\n')
1951
0
    n--;
1952
0
  return pnstrdup(in, n);
1953
0
}