1 /*-------------------------------------------------------------------------
4 * POSTGRES memory context management code.
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.
12 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
13 * Portions Copyright (c) 1994, Regents of the University of California
17 * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.27 2001/02/06 01:53:53 tgl Exp $
19 *-------------------------------------------------------------------------
24 #include "nodes/memnodes.h"
25 #include "utils/excid.h"
26 #include "utils/memutils.h"
29 /*****************************************************************************
31 *****************************************************************************/
34 * CurrentMemoryContext
35 * Default memory context for allocations.
37 MemoryContext CurrentMemoryContext = NULL;
40 * Standard top-level contexts
42 MemoryContext TopMemoryContext = NULL;
43 MemoryContext ErrorContext = NULL;
44 MemoryContext PostmasterContext = NULL;
45 MemoryContext CacheMemoryContext = NULL;
46 MemoryContext QueryContext = NULL;
47 MemoryContext TopTransactionContext = NULL;
48 MemoryContext TransactionCommandContext = NULL;
51 /*****************************************************************************
53 *****************************************************************************/
58 * Start up the memory-context subsystem.
60 * This must be called before creating contexts or allocating memory in
61 * contexts. TopMemoryContext and ErrorContext are initialized here;
62 * other contexts must be created afterwards.
64 * In normal multi-backend operation, this is called once during
65 * postmaster startup, and not at all by individual backend startup
66 * (since the backends inherit an already-initialized context subsystem
67 * by virtue of being forked off the postmaster).
69 * In a standalone backend this must be called during backend startup.
72 MemoryContextInit(void)
74 AssertState(TopMemoryContext == NULL);
76 * Initialize TopMemoryContext as an AllocSetContext with slow
77 * growth rate --- we don't really expect much to be allocated in it.
79 * (There is special-case code in MemoryContextCreate() for this call.)
81 TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
87 * Not having any other place to point CurrentMemoryContext,
88 * make it point to TopMemoryContext. Caller should change this soon!
90 CurrentMemoryContext = TopMemoryContext;
92 * Initialize ErrorContext as an AllocSetContext with slow
93 * growth rate --- we don't really expect much to be allocated in it.
94 * More to the point, require it to contain at least 8K at all times.
95 * This is the only case where retained memory in a context is
96 * *essential* --- we want to be sure ErrorContext still has some
97 * memory even if we've run out elsewhere!
99 ErrorContext = AllocSetContextCreate(TopMemoryContext,
108 * Release all space allocated within a context and its descendants,
109 * but don't delete the contexts themselves.
111 * The type-specific reset routine handles the context itself, but we
112 * have to do the recursion for the children.
115 MemoryContextReset(MemoryContext context)
117 AssertArg(MemoryContextIsValid(context));
119 MemoryContextResetChildren(context);
120 (*context->methods->reset) (context);
124 * MemoryContextResetChildren
125 * Release all space allocated within a context's descendants,
126 * but don't delete the contexts themselves. The named context
127 * itself is not touched.
130 MemoryContextResetChildren(MemoryContext context)
134 AssertArg(MemoryContextIsValid(context));
136 for (child = context->firstchild; child != NULL; child = child->nextchild)
138 MemoryContextReset(child);
143 * MemoryContextDelete
144 * Delete a context and its descendants, and release all space
147 * The type-specific delete routine removes all subsidiary storage
148 * for the context, but we have to delete the context node itself,
149 * as well as recurse to get the children. We must also delink the
150 * node from its parent, if it has one.
153 MemoryContextDelete(MemoryContext context)
155 AssertArg(MemoryContextIsValid(context));
156 /* We had better not be deleting TopMemoryContext ... */
157 Assert(context != TopMemoryContext);
158 /* And not CurrentMemoryContext, either */
159 Assert(context != CurrentMemoryContext);
161 MemoryContextDeleteChildren(context);
163 * We delink the context from its parent before deleting it,
164 * so that if there's an error we won't have deleted/busted
165 * contexts still attached to the context tree. Better a leak
170 MemoryContext parent = context->parent;
172 if (context == parent->firstchild)
174 parent->firstchild = context->nextchild;
180 for (child = parent->firstchild; child; child = child->nextchild)
182 if (context == child->nextchild)
184 child->nextchild = context->nextchild;
190 (*context->methods->delete) (context);
195 * MemoryContextDeleteChildren
196 * Delete all the descendants of the named context and release all
197 * space allocated therein. The named context itself is not touched.
200 MemoryContextDeleteChildren(MemoryContext context)
202 AssertArg(MemoryContextIsValid(context));
204 * MemoryContextDelete will delink the child from me,
205 * so just iterate as long as there is a child.
207 while (context->firstchild != NULL)
209 MemoryContextDelete(context->firstchild);
214 * MemoryContextResetAndDeleteChildren
215 * Release all space allocated within a context and delete all
218 * This is a common combination case where we want to preserve the
219 * specific context but get rid of absolutely everything under it.
222 MemoryContextResetAndDeleteChildren(MemoryContext context)
224 AssertArg(MemoryContextIsValid(context));
226 MemoryContextDeleteChildren(context);
227 (*context->methods->reset) (context);
232 * Print statistics about the named context and all its descendants.
234 * This is just a debugging utility, so it's not fancy. The statistics
235 * are merely sent to stderr.
238 MemoryContextStats(MemoryContext context)
242 AssertArg(MemoryContextIsValid(context));
244 (*context->methods->stats) (context);
245 for (child = context->firstchild; child != NULL; child = child->nextchild)
247 MemoryContextStats(child);
254 * Check all chunks in the named context.
256 * This is just a debugging utility, so it's not fancy.
258 #ifdef MEMORY_CONTEXT_CHECKING
260 MemoryContextCheck(MemoryContext context)
264 AssertArg(MemoryContextIsValid(context));
266 (*context->methods->check) (context);
267 for (child = context->firstchild; child != NULL; child = child->nextchild)
269 MemoryContextCheck(child);
275 * MemoryContextContains
276 * Detect whether an allocated chunk of memory belongs to a given
279 * Caution: this test is reliable as long as 'pointer' does point to
280 * a chunk of memory allocated from *some* context. If 'pointer' points
281 * at memory obtained in some other way, there is a small chance of a
282 * false-positive result, since the bits right before it might look like
283 * a valid chunk header by chance.
286 MemoryContextContains(MemoryContext context, void *pointer)
288 StandardChunkHeader *header;
291 * Try to detect bogus pointers handed to us, poorly though we can.
292 * Presumably, a pointer that isn't MAXALIGNED isn't pointing at
293 * an allocated chunk.
295 if (pointer == NULL || pointer != (void *) MAXALIGN(pointer))
298 * OK, it's probably safe to look at the chunk header.
300 header = (StandardChunkHeader *)
301 ((char *) pointer - STANDARDCHUNKHEADERSIZE);
303 * If the context link doesn't match then we certainly have a
304 * non-member chunk. Also check for a reasonable-looking size
305 * as extra guard against being fooled by bogus pointers.
307 if (header->context == context && AllocSizeIsValid(header->size))
312 /*--------------------
313 * MemoryContextCreate
314 * Context-type-independent part of context creation.
316 * This is only intended to be called by context-type-specific
317 * context creation routines, not by the unwashed masses.
319 * The context creation procedure is a little bit tricky because
320 * we want to be sure that we don't leave the context tree invalid
321 * in case of failure (such as insufficient memory to allocate the
322 * context node itself). The procedure goes like this:
323 * 1. Context-type-specific routine first calls MemoryContextCreate(),
324 * passing the appropriate tag/size/methods values (the methods
325 * pointer will ordinarily point to statically allocated data).
326 * The parent and name parameters usually come from the caller.
327 * 2. MemoryContextCreate() attempts to allocate the context node,
328 * plus space for the name. If this fails we can elog() with no
330 * 3. We fill in all of the type-independent MemoryContext fields.
331 * 4. We call the type-specific init routine (using the methods pointer).
332 * The init routine is required to make the node minimally valid
333 * with zero chance of failure --- it can't allocate more memory,
335 * 5. Now we have a minimally valid node that can behave correctly
336 * when told to reset or delete itself. We link the node to its
337 * parent (if any), making the node part of the context tree.
338 * 6. We return to the context-type-specific routine, which finishes
339 * up type-specific initialization. This routine can now do things
340 * that might fail (like allocate more memory), so long as it's
341 * sure the node is left in a state that delete will handle.
343 * This protocol doesn't prevent us from leaking memory if step 6 fails
344 * during creation of a top-level context, since there's no parent link
345 * in that case. However, if you run out of memory while you're building
346 * a top-level context, you might as well go home anyway...
348 * Normally, the context node and the name are allocated from
349 * TopMemoryContext (NOT from the parent context, since the node must
350 * survive resets of its parent context!). However, this routine is itself
351 * used to create TopMemoryContext! If we see that TopMemoryContext is NULL,
352 * we assume we are creating TopMemoryContext and use malloc() to allocate
355 * Note that the name field of a MemoryContext does not point to
356 * separately-allocated storage, so it should not be freed at context
358 *--------------------
361 MemoryContextCreate(NodeTag tag, Size size,
362 MemoryContextMethods *methods,
363 MemoryContext parent,
367 Size needed = size + strlen(name) + 1;
369 /* Get space for node and name */
370 if (TopMemoryContext != NULL)
372 /* Normal case: allocate the node in TopMemoryContext */
373 node = (MemoryContext) MemoryContextAlloc(TopMemoryContext,
378 /* Special case for startup: use good ol' malloc */
379 node = (MemoryContext) malloc(needed);
380 Assert(node != NULL);
383 /* Initialize the node as best we can */
384 MemSet(node, 0, size);
386 node->methods = methods;
387 node->parent = NULL; /* for the moment */
388 node->firstchild = NULL;
389 node->nextchild = NULL;
390 node->name = ((char *) node) + size;
391 strcpy(node->name, name);
393 /* Type-specific routine finishes any other essential initialization */
394 (*node->methods->init) (node);
396 /* OK to link node to parent (if any) */
399 node->parent = parent;
400 node->nextchild = parent->firstchild;
401 parent->firstchild = node;
404 /* Return to type-specific creation routine to finish up */
410 * Allocate space within the specified context.
412 * This could be turned into a macro, but we'd have to import
413 * nodes/memnodes.h into postgres.h which seems a bad idea.
416 MemoryContextAlloc(MemoryContext context, Size size)
418 AssertArg(MemoryContextIsValid(context));
420 if (!AllocSizeIsValid(size))
421 elog(ERROR, "MemoryContextAlloc: invalid request size %lu",
422 (unsigned long) size);
424 return (*context->methods->alloc) (context, size);
429 * Release an allocated chunk.
434 StandardChunkHeader *header;
437 * Try to detect bogus pointers handed to us, poorly though we can.
438 * Presumably, a pointer that isn't MAXALIGNED isn't pointing at
439 * an allocated chunk.
441 Assert(pointer != NULL);
442 Assert(pointer == (void *) MAXALIGN(pointer));
444 * OK, it's probably safe to look at the chunk header.
446 header = (StandardChunkHeader *)
447 ((char *) pointer - STANDARDCHUNKHEADERSIZE);
449 AssertArg(MemoryContextIsValid(header->context));
451 (*header->context->methods->free_p) (header->context, pointer);
459 repalloc(void *pointer, Size size)
461 StandardChunkHeader *header;
464 * Try to detect bogus pointers handed to us, poorly though we can.
465 * Presumably, a pointer that isn't MAXALIGNED isn't pointing at
466 * an allocated chunk.
468 Assert(pointer != NULL);
469 Assert(pointer == (void *) MAXALIGN(pointer));
471 * OK, it's probably safe to look at the chunk header.
473 header = (StandardChunkHeader *)
474 ((char *) pointer - STANDARDCHUNKHEADERSIZE);
476 AssertArg(MemoryContextIsValid(header->context));
478 if (!AllocSizeIsValid(size))
479 elog(ERROR, "repalloc: invalid request size %lu",
480 (unsigned long) size);
482 return (*header->context->methods->realloc) (header->context,
487 * MemoryContextSwitchTo
488 * Returns the current context; installs the given context.
491 MemoryContextSwitchTo(MemoryContext context)
495 AssertArg(MemoryContextIsValid(context));
497 old = CurrentMemoryContext;
498 CurrentMemoryContext = context;
503 * MemoryContextStrdup
504 * Like strdup(), but allocate from the specified context
507 MemoryContextStrdup(MemoryContext context, const char *string)
510 Size len = strlen(string) + 1;
512 nstr = (char *) MemoryContextAlloc(context, len);
514 memcpy(nstr, string, len);