📄 mcxt.c
字号:
/*------------------------------------------------------------------------- * * 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-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/utils/mmgr/mcxt.c,v 1.56 2005/10/15 02:49:36 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "nodes/memnodes.h"#include "utils/memutils.h"/***************************************************************************** * GLOBAL MEMORY * *****************************************************************************//* * CurrentMemoryContext * Default memory context for allocations. */MemoryContext CurrentMemoryContext = NULL;/* * Standard top-level contexts. For a description of the purpose of each * of these contexts, refer to src/backend/utils/mmgr/README */MemoryContext TopMemoryContext = NULL;MemoryContext ErrorContext = NULL;MemoryContext PostmasterContext = NULL;MemoryContext CacheMemoryContext = NULL;MemoryContext MessageContext = NULL;MemoryContext TopTransactionContext = NULL;MemoryContext CurTransactionContext = NULL;/* These two are transient links to contexts owned by other objects: */MemoryContext QueryContext = NULL;MemoryContext PortalContext = 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. */voidMemoryContextInit(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", 0, 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. */voidMemoryContextReset(MemoryContext context){ AssertArg(MemoryContextIsValid(context)); /* save a function call in common case where there are no children */ if (context->firstchild != NULL) 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. */voidMemoryContextResetChildren(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. */voidMemoryContextDelete(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. */voidMemoryContextDeleteChildren(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. */voidMemoryContextResetAndDeleteChildren(MemoryContext context){ AssertArg(MemoryContextIsValid(context)); MemoryContextDeleteChildren(context); (*context->methods->reset) (context);}/* * GetMemoryChunkSpace * Given a currently-allocated chunk, determine the total space * it occupies (including all memory-allocation overhead). * * This is useful for measuring the total space occupied by a set of * allocated chunks. */SizeGetMemoryChunkSpace(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)); return (*header->context->methods->get_chunk_space) (header->context, pointer);}/* * GetMemoryChunkContext * Given a currently-allocated chunk, determine the context * it belongs to. */MemoryContextGetMemoryChunkContext(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)); return header->context;}/* * MemoryContextIsEmpty * Is a memory context empty of any allocated space? */boolMemoryContextIsEmpty(MemoryContext context){ AssertArg(MemoryContextIsValid(context)); /* * For now, we consider a memory context nonempty if it has any children; * perhaps this should be changed later. */ if (context->firstchild != NULL) return false; /* Otherwise use the type-specific inquiry */ return (*context->methods->is_empty) (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. */voidMemoryContextStats(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_CHECKINGvoidMemoryContextCheck(MemoryContext context){ MemoryContext child; AssertArg(MemoryContextIsValid(context));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -