diff options
Diffstat (limited to 'src/backend/utils/mmgr/mcxt.c')
-rw-r--r-- | src/backend/utils/mmgr/mcxt.c | 515 |
1 files changed, 0 insertions, 515 deletions
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c deleted file mode 100644 index 01669b62e2f..00000000000 --- a/src/backend/utils/mmgr/mcxt.c +++ /dev/null @@ -1,515 +0,0 @@ -/*------------------------------------------------------------------------- - * - * mcxt.c - * POSTGRES memory context management code. - * - * This module handles context management operations that are independent - * of the particular kind of context being operated on. It calls - * context-type-specific operations via the function pointers in a - * context's MemoryContextMethods struct. - * - * - * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.30 2002/06/20 20:29:40 momjian Exp $ - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" - -#include "nodes/memnodes.h" -#include "utils/excid.h" -#include "utils/memutils.h" - - -/***************************************************************************** - * GLOBAL MEMORY * - *****************************************************************************/ - -/* - * CurrentMemoryContext - * Default memory context for allocations. - */ -MemoryContext CurrentMemoryContext = NULL; - -/* - * Standard top-level contexts - */ -MemoryContext TopMemoryContext = NULL; -MemoryContext ErrorContext = NULL; -MemoryContext PostmasterContext = NULL; -MemoryContext CacheMemoryContext = NULL; -MemoryContext QueryContext = NULL; -MemoryContext TopTransactionContext = NULL; -MemoryContext TransactionCommandContext = NULL; - - -/***************************************************************************** - * EXPORTED ROUTINES * - *****************************************************************************/ - - -/* - * MemoryContextInit - * Start up the memory-context subsystem. - * - * This must be called before creating contexts or allocating memory in - * contexts. TopMemoryContext and ErrorContext are initialized here; - * other contexts must be created afterwards. - * - * In normal multi-backend operation, this is called once during - * postmaster startup, and not at all by individual backend startup - * (since the backends inherit an already-initialized context subsystem - * by virtue of being forked off the postmaster). - * - * In a standalone backend this must be called during backend startup. - */ -void -MemoryContextInit(void) -{ - AssertState(TopMemoryContext == NULL); - - /* - * Initialize TopMemoryContext as an AllocSetContext with slow growth - * rate --- we don't really expect much to be allocated in it. - * - * (There is special-case code in MemoryContextCreate() for this call.) - */ - TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL, - "TopMemoryContext", - 8 * 1024, - 8 * 1024, - 8 * 1024); - - /* - * Not having any other place to point CurrentMemoryContext, make it - * point to TopMemoryContext. Caller should change this soon! - */ - CurrentMemoryContext = TopMemoryContext; - - /* - * Initialize ErrorContext as an AllocSetContext with slow growth rate - * --- we don't really expect much to be allocated in it. More to the - * point, require it to contain at least 8K at all times. This is the - * only case where retained memory in a context is *essential* --- we - * want to be sure ErrorContext still has some memory even if we've - * run out elsewhere! - */ - ErrorContext = AllocSetContextCreate(TopMemoryContext, - "ErrorContext", - 8 * 1024, - 8 * 1024, - 8 * 1024); -} - -/* - * MemoryContextReset - * Release all space allocated within a context and its descendants, - * but don't delete the contexts themselves. - * - * The type-specific reset routine handles the context itself, but we - * have to do the recursion for the children. - */ -void -MemoryContextReset(MemoryContext context) -{ - AssertArg(MemoryContextIsValid(context)); - - MemoryContextResetChildren(context); - (*context->methods->reset) (context); -} - -/* - * MemoryContextResetChildren - * Release all space allocated within a context's descendants, - * but don't delete the contexts themselves. The named context - * itself is not touched. - */ -void -MemoryContextResetChildren(MemoryContext context) -{ - MemoryContext child; - - AssertArg(MemoryContextIsValid(context)); - - for (child = context->firstchild; child != NULL; child = child->nextchild) - MemoryContextReset(child); -} - -/* - * MemoryContextDelete - * Delete a context and its descendants, and release all space - * allocated therein. - * - * The type-specific delete routine removes all subsidiary storage - * for the context, but we have to delete the context node itself, - * as well as recurse to get the children. We must also delink the - * node from its parent, if it has one. - */ -void -MemoryContextDelete(MemoryContext context) -{ - AssertArg(MemoryContextIsValid(context)); - /* We had better not be deleting TopMemoryContext ... */ - Assert(context != TopMemoryContext); - /* And not CurrentMemoryContext, either */ - Assert(context != CurrentMemoryContext); - - MemoryContextDeleteChildren(context); - - /* - * We delink the context from its parent before deleting it, so that - * if there's an error we won't have deleted/busted contexts still - * attached to the context tree. Better a leak than a crash. - */ - if (context->parent) - { - MemoryContext parent = context->parent; - - if (context == parent->firstchild) - parent->firstchild = context->nextchild; - else - { - MemoryContext child; - - for (child = parent->firstchild; child; child = child->nextchild) - { - if (context == child->nextchild) - { - child->nextchild = context->nextchild; - break; - } - } - } - } - (*context->methods->delete) (context); - pfree(context); -} - -/* - * MemoryContextDeleteChildren - * Delete all the descendants of the named context and release all - * space allocated therein. The named context itself is not touched. - */ -void -MemoryContextDeleteChildren(MemoryContext context) -{ - AssertArg(MemoryContextIsValid(context)); - - /* - * MemoryContextDelete will delink the child from me, so just iterate - * as long as there is a child. - */ - while (context->firstchild != NULL) - MemoryContextDelete(context->firstchild); -} - -/* - * MemoryContextResetAndDeleteChildren - * Release all space allocated within a context and delete all - * its descendants. - * - * This is a common combination case where we want to preserve the - * specific context but get rid of absolutely everything under it. - */ -void -MemoryContextResetAndDeleteChildren(MemoryContext context) -{ - AssertArg(MemoryContextIsValid(context)); - - MemoryContextDeleteChildren(context); - (*context->methods->reset) (context); -} - -/* - * MemoryContextStats - * Print statistics about the named context and all its descendants. - * - * This is just a debugging utility, so it's not fancy. The statistics - * are merely sent to stderr. - */ -void -MemoryContextStats(MemoryContext context) -{ - MemoryContext child; - - AssertArg(MemoryContextIsValid(context)); - - (*context->methods->stats) (context); - for (child = context->firstchild; child != NULL; child = child->nextchild) - MemoryContextStats(child); -} - - -/* - * MemoryContextCheck - * Check all chunks in the named context. - * - * This is just a debugging utility, so it's not fancy. - */ -#ifdef MEMORY_CONTEXT_CHECKING -void -MemoryContextCheck(MemoryContext context) -{ - MemoryContext child; - - AssertArg(MemoryContextIsValid(context)); - - (*context->methods->check) (context); - for (child = context->firstchild; child != NULL; child = child->nextchild) - MemoryContextCheck(child); -} -#endif - -/* - * MemoryContextContains - * Detect whether an allocated chunk of memory belongs to a given - * context or not. - * - * Caution: this test is reliable as long as 'pointer' does point to - * a chunk of memory allocated from *some* context. If 'pointer' points - * at memory obtained in some other way, there is a small chance of a - * false-positive result, since the bits right before it might look like - * a valid chunk header by chance. - */ -bool -MemoryContextContains(MemoryContext context, void *pointer) -{ - StandardChunkHeader *header; - - /* - * Try to detect bogus pointers handed to us, poorly though we can. - * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an - * allocated chunk. - */ - if (pointer == NULL || pointer != (void *) MAXALIGN(pointer)) - return false; - - /* - * OK, it's probably safe to look at the chunk header. - */ - header = (StandardChunkHeader *) - ((char *) pointer - STANDARDCHUNKHEADERSIZE); - - /* - * If the context link doesn't match then we certainly have a - * non-member chunk. Also check for a reasonable-looking size as - * extra guard against being fooled by bogus pointers. - */ - if (header->context == context && AllocSizeIsValid(header->size)) - return true; - return false; -} - -/*-------------------- - * MemoryContextCreate - * Context-type-independent part of context creation. - * - * This is only intended to be called by context-type-specific - * context creation routines, not by the unwashed masses. - * - * The context creation procedure is a little bit tricky because - * we want to be sure that we don't leave the context tree invalid - * in case of failure (such as insufficient memory to allocate the - * context node itself). The procedure goes like this: - * 1. Context-type-specific routine first calls MemoryContextCreate(), - * passing the appropriate tag/size/methods values (the methods - * pointer will ordinarily point to statically allocated data). - * The parent and name parameters usually come from the caller. - * 2. MemoryContextCreate() attempts to allocate the context node, - * plus space for the name. If this fails we can elog() with no - * damage done. - * 3. We fill in all of the type-independent MemoryContext fields. - * 4. We call the type-specific init routine (using the methods pointer). - * The init routine is required to make the node minimally valid - * with zero chance of failure --- it can't allocate more memory, - * for example. - * 5. Now we have a minimally valid node that can behave correctly - * when told to reset or delete itself. We link the node to its - * parent (if any), making the node part of the context tree. - * 6. We return to the context-type-specific routine, which finishes - * up type-specific initialization. This routine can now do things - * that might fail (like allocate more memory), so long as it's - * sure the node is left in a state that delete will handle. - * - * This protocol doesn't prevent us from leaking memory if step 6 fails - * during creation of a top-level context, since there's no parent link - * in that case. However, if you run out of memory while you're building - * a top-level context, you might as well go home anyway... - * - * Normally, the context node and the name are allocated from - * TopMemoryContext (NOT from the parent context, since the node must - * survive resets of its parent context!). However, this routine is itself - * used to create TopMemoryContext! If we see that TopMemoryContext is NULL, - * we assume we are creating TopMemoryContext and use malloc() to allocate - * the node. - * - * Note that the name field of a MemoryContext does not point to - * separately-allocated storage, so it should not be freed at context - * deletion. - *-------------------- - */ -MemoryContext -MemoryContextCreate(NodeTag tag, Size size, - MemoryContextMethods *methods, - MemoryContext parent, - const char *name) -{ - MemoryContext node; - Size needed = size + strlen(name) + 1; - - /* Get space for node and name */ - if (TopMemoryContext != NULL) - { - /* Normal case: allocate the node in TopMemoryContext */ - node = (MemoryContext) MemoryContextAlloc(TopMemoryContext, - needed); - } - else - { - /* Special case for startup: use good ol' malloc */ - node = (MemoryContext) malloc(needed); - Assert(node != NULL); - } - - /* Initialize the node as best we can */ - MemSet(node, 0, size); - node->type = tag; - node->methods = methods; - node->parent = NULL; /* for the moment */ - node->firstchild = NULL; - node->nextchild = NULL; - node->name = ((char *) node) + size; - strcpy(node->name, name); - - /* Type-specific routine finishes any other essential initialization */ - (*node->methods->init) (node); - - /* OK to link node to parent (if any) */ - if (parent) - { - node->parent = parent; - node->nextchild = parent->firstchild; - parent->firstchild = node; - } - - /* Return to type-specific creation routine to finish up */ - return node; -} - -/* - * MemoryContextAlloc - * Allocate space within the specified context. - * - * This could be turned into a macro, but we'd have to import - * nodes/memnodes.h into postgres.h which seems a bad idea. - */ -void * -MemoryContextAlloc(MemoryContext context, Size size) -{ - AssertArg(MemoryContextIsValid(context)); - - if (!AllocSizeIsValid(size)) - elog(ERROR, "MemoryContextAlloc: invalid request size %lu", - (unsigned long) size); - - return (*context->methods->alloc) (context, size); -} - -/* - * pfree - * Release an allocated chunk. - */ -void -pfree(void *pointer) -{ - StandardChunkHeader *header; - - /* - * Try to detect bogus pointers handed to us, poorly though we can. - * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an - * allocated chunk. - */ - Assert(pointer != NULL); - Assert(pointer == (void *) MAXALIGN(pointer)); - - /* - * OK, it's probably safe to look at the chunk header. - */ - header = (StandardChunkHeader *) - ((char *) pointer - STANDARDCHUNKHEADERSIZE); - - AssertArg(MemoryContextIsValid(header->context)); - - (*header->context->methods->free_p) (header->context, pointer); -} - -/* - * repalloc - * - */ -void * -repalloc(void *pointer, Size size) -{ - StandardChunkHeader *header; - - /* - * Try to detect bogus pointers handed to us, poorly though we can. - * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an - * allocated chunk. - */ - Assert(pointer != NULL); - Assert(pointer == (void *) MAXALIGN(pointer)); - - /* - * OK, it's probably safe to look at the chunk header. - */ - header = (StandardChunkHeader *) - ((char *) pointer - STANDARDCHUNKHEADERSIZE); - - AssertArg(MemoryContextIsValid(header->context)); - - if (!AllocSizeIsValid(size)) - elog(ERROR, "repalloc: invalid request size %lu", - (unsigned long) size); - - return (*header->context->methods->realloc) (header->context, - pointer, size); -} - -/* - * MemoryContextSwitchTo - * Returns the current context; installs the given context. - */ -MemoryContext -MemoryContextSwitchTo(MemoryContext context) -{ - MemoryContext old; - - AssertArg(MemoryContextIsValid(context)); - - old = CurrentMemoryContext; - CurrentMemoryContext = context; - return old; -} - -/* - * MemoryContextStrdup - * Like strdup(), but allocate from the specified context - */ -char * -MemoryContextStrdup(MemoryContext context, const char *string) -{ - char *nstr; - Size len = strlen(string) + 1; - - nstr = (char *) MemoryContextAlloc(context, len); - - memcpy(nstr, string, len); - - return nstr; -} |