aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/mmgr/mcxt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/mmgr/mcxt.c')
-rw-r--r--src/backend/utils/mmgr/mcxt.c510
1 files changed, 510 insertions, 0 deletions
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
new file mode 100644
index 00000000000..d9095af11f4
--- /dev/null
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -0,0 +1,510 @@
+/*-------------------------------------------------------------------------
+ *
+ * mcxt.c--
+ * POSTGRES memory context code.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.1.1.1 1996/07/09 06:22:09 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdio.h> /* XXX for printf debugging */
+
+#include "postgres.h"
+
+#include "utils/memutils.h"
+#include "utils/module.h"
+#include "utils/excid.h"
+
+#include "nodes/memnodes.h"
+#include "nodes/nodes.h"
+
+#include "utils/mcxt.h"
+#include "utils/elog.h"
+
+#include "utils/palloc.h"
+
+#undef MemoryContextAlloc
+#undef MemoryContextFree
+#undef malloc
+#undef free
+
+/*
+ * Global State
+ */
+static int MemoryContextEnableCount = 0;
+#define MemoryContextEnabled (MemoryContextEnableCount > 0)
+
+static OrderedSetData ActiveGlobalMemorySetData; /* uninitialized */
+#define ActiveGlobalMemorySet (&ActiveGlobalMemorySetData)
+
+/*
+ * description of allocated memory representation goes here
+ */
+
+#define PSIZE(PTR) (*((int32 *)(PTR) - 1))
+#define PSIZEALL(PTR) (*((int32 *)(PTR) - 1) + sizeof (int32))
+#define PSIZESKIP(PTR) ((char *)((int32 *)(PTR) + 1))
+#define PSIZEFIND(PTR) ((char *)((int32 *)(PTR) - 1))
+#define PSIZESPACE(LEN) ((LEN) + sizeof (int32))
+
+/*
+ * AllocSizeIsValid --
+ * True iff 0 < size and size <= MaxAllocSize.
+ */
+#define AllocSizeIsValid(size) (0 < (size) && (size) <= MaxAllocSize)
+
+/*****************************************************************************
+ * GLOBAL MEMORY *
+ *****************************************************************************/
+
+/*
+ * CurrentMemoryContext --
+ * Memory context for general global allocations.
+ */
+MemoryContext CurrentMemoryContext = NULL;
+
+/*****************************************************************************
+ * PRIVATE DEFINITIONS *
+ *****************************************************************************/
+
+static Pointer GlobalMemoryAlloc(GlobalMemory this, Size size);
+static void GlobalMemoryFree(GlobalMemory this, Pointer pointer);
+static Pointer GlobalMemoryRealloc(GlobalMemory this, Pointer pointer,
+ Size size);
+static char *GlobalMemoryGetName(GlobalMemory this);
+static void GlobalMemoryDump(GlobalMemory this);
+static void DumpGlobalMemories(void);
+
+
+/*
+ * Global Memory Methods
+ */
+
+static struct MemoryContextMethodsData GlobalContextMethodsData = {
+ GlobalMemoryAlloc, /* Pointer (*)(this, uint32) palloc */
+ GlobalMemoryFree, /* void (*)(this, Pointer) pfree */
+ GlobalMemoryRealloc, /* Pointer (*)(this, Pointer) repalloc */
+ GlobalMemoryGetName, /* char* (*)(this) getName */
+ GlobalMemoryDump /* void (*)(this) dump */
+};
+
+/*
+ * Note:
+ * TopGlobalMemory is handled specially because of bootstrapping.
+ */
+/* extern bool EqualGlobalMemory(); */
+
+static struct GlobalMemory TopGlobalMemoryData = {
+ T_GlobalMemory, /* NodeTag tag */
+ &GlobalContextMethodsData, /* ContextMethods method */
+ { { 0 } }, /* uninitialized
+ * OrderedSetData allocSetD
+ */
+ "TopGlobal", /* char* name */
+ { 0 } /* uninitialized OrderedElemData elemD */
+};
+
+/*
+ * TopMemoryContext --
+ * Memory context for general global allocations.
+ *
+ * Note:
+ * Don't use this memory context for random allocations. If you
+ * allocate something here, you are expected to clean it up when
+ * appropriate.
+ */
+MemoryContext TopMemoryContext = (MemoryContext)&TopGlobalMemoryData;
+
+
+
+
+/*
+ * Module State
+ */
+
+/*
+ * EnableMemoryContext --
+ * Enables/disables memory management and global contexts.
+ *
+ * Note:
+ * This must be called before creating contexts or allocating memory.
+ * This must be called before other contexts are created.
+ *
+ * Exceptions:
+ * BadArg if on is invalid.
+ * BadState if on is false when disabled.
+ */
+void
+EnableMemoryContext(bool on)
+{
+ static bool processing = false;
+
+ AssertState(!processing);
+ AssertArg(BoolIsValid(on));
+
+ if (BypassEnable(&MemoryContextEnableCount, on)) {
+ return;
+ }
+
+ processing = true;
+
+ if (on) { /* initialize */
+ /* initialize TopGlobalMemoryData.setData */
+ AllocSetInit(&TopGlobalMemoryData.setData, DynamicAllocMode,
+ (Size)0);
+
+ /* make TopGlobalMemoryData member of ActiveGlobalMemorySet */
+ OrderedSetInit(ActiveGlobalMemorySet,
+ offsetof(struct GlobalMemory, elemData));
+ OrderedElemPushInto(&TopGlobalMemoryData.elemData,
+ ActiveGlobalMemorySet);
+
+ /* initialize CurrentMemoryContext */
+ CurrentMemoryContext = TopMemoryContext;
+
+ } else { /* cleanup */
+ GlobalMemory context;
+
+ /* walk the list of allocations */
+ while (PointerIsValid(context = (GlobalMemory)
+ OrderedSetGetHead(ActiveGlobalMemorySet))) {
+
+ if (context == &TopGlobalMemoryData) {
+ /* don't free it and clean it last */
+ OrderedElemPop(&TopGlobalMemoryData.elemData);
+ } else {
+ GlobalMemoryDestroy(context);
+ }
+ /* what is needed for the top? */
+ }
+
+ /*
+ * Freeing memory here should be safe as this is called
+ * only after all modules which allocate in TopMemoryContext
+ * have been disabled.
+ */
+
+ /* step through remaining allocations and log */
+ /* AllocSetStep(...); */
+
+ /* deallocate whatever is left */
+ AllocSetReset(&TopGlobalMemoryData.setData);
+ }
+
+ processing = false;
+}
+
+/*
+ * MemoryContextAlloc --
+ * Returns pointer to aligned allocated memory in the given context.
+ *
+ * Note:
+ * none
+ *
+ * Exceptions:
+ * BadState if called before InitMemoryManager.
+ * BadArg if context is invalid or if size is 0.
+ * BadAllocSize if size is larger than MaxAllocSize.
+ */
+Pointer
+MemoryContextAlloc(MemoryContext context, Size size)
+{
+ AssertState(MemoryContextEnabled);
+ AssertArg(MemoryContextIsValid(context));
+
+ LogTrap(!AllocSizeIsValid(size), BadAllocSize,
+ ("size=%d [0x%x]", size, size));
+
+ return (context->method->alloc(context, size));
+}
+
+/*
+ * MemoryContextFree --
+ * Frees allocated memory referenced by pointer in the given context.
+ *
+ * Note:
+ * none
+ *
+ * Exceptions:
+ * ???
+ * BadArgumentsErr if firstTime is true for subsequent calls.
+ */
+void
+MemoryContextFree(MemoryContext context, Pointer pointer)
+{
+ AssertState(MemoryContextEnabled);
+ AssertArg(MemoryContextIsValid(context));
+ AssertArg(PointerIsValid(pointer));
+
+ context->method->free_p(context, pointer);
+}
+
+/*
+ * MemoryContextRelloc --
+ * Returns pointer to aligned allocated memory in the given context.
+ *
+ * Note:
+ * none
+ *
+ * Exceptions:
+ * ???
+ * BadArgumentsErr if firstTime is true for subsequent calls.
+ */
+Pointer
+MemoryContextRealloc(MemoryContext context,
+ Pointer pointer,
+ Size size)
+{
+ AssertState(MemoryContextEnabled);
+ AssertArg(MemoryContextIsValid(context));
+ AssertArg(PointerIsValid(pointer));
+
+ LogTrap(!AllocSizeIsValid(size), BadAllocSize,
+ ("size=%d [0x%x]", size, size));
+
+ return (context->method->realloc(context, pointer, size));
+}
+
+/*
+ * MemoryContextGetName --
+ * Returns pointer to aligned allocated memory in the given context.
+ *
+ * Note:
+ * none
+ *
+ * Exceptions:
+ * ???
+ * BadArgumentsErr if firstTime is true for subsequent calls.
+ */
+char*
+MemoryContextGetName(MemoryContext context)
+{
+ AssertState(MemoryContextEnabled);
+ AssertArg(MemoryContextIsValid(context));
+
+ return (context->method->getName(context));
+}
+
+/*
+ * PointerGetAllocSize --
+ * Returns size of aligned allocated memory given pointer to it.
+ *
+ * Note:
+ * none
+ *
+ * Exceptions:
+ * ???
+ * BadArgumentsErr if firstTime is true for subsequent calls.
+ */
+Size
+PointerGetAllocSize(Pointer pointer)
+{
+ AssertState(MemoryContextEnabled);
+ AssertArg(PointerIsValid(pointer));
+
+ return (PSIZE(pointer));
+}
+
+/*
+ * MemoryContextSwitchTo --
+ * Returns the current context; installs the given context.
+ *
+ * Note:
+ * none
+ *
+ * Exceptions:
+ * BadState if called when disabled.
+ * BadArg if context is invalid.
+ */
+MemoryContext
+MemoryContextSwitchTo(MemoryContext context)
+{
+ MemoryContext old;
+
+ AssertState(MemoryContextEnabled);
+ AssertArg(MemoryContextIsValid(context));
+
+ old = CurrentMemoryContext;
+ CurrentMemoryContext = context;
+ return (old);
+}
+
+/*
+ * External Functions
+ */
+/*
+ * CreateGlobalMemory --
+ * Returns new global memory context.
+ *
+ * Note:
+ * Assumes name is static.
+ *
+ * Exceptions:
+ * BadState if called when disabled.
+ * BadState if called outside TopMemoryContext (TopGlobalMemory).
+ * BadArg if name is invalid.
+ */
+GlobalMemory
+CreateGlobalMemory(char *name) /* XXX MemoryContextName */
+{
+ GlobalMemory context;
+ MemoryContext savecxt;
+
+ AssertState(MemoryContextEnabled);
+
+ savecxt = MemoryContextSwitchTo(TopMemoryContext);
+
+ context = (GlobalMemory)newNode(sizeof(struct GlobalMemory), T_GlobalMemory);
+ context->method = &GlobalContextMethodsData;
+ context->name = name; /* assumes name is static */
+ AllocSetInit(&context->setData, DynamicAllocMode, (Size)0);
+
+ /* link the context */
+ OrderedElemPushInto(&context->elemData, ActiveGlobalMemorySet);
+
+ MemoryContextSwitchTo(savecxt);
+ return (context);
+}
+
+/*
+ * GlobalMemoryDestroy --
+ * Destroys given global memory context.
+ *
+ * Exceptions:
+ * BadState if called when disabled.
+ * BadState if called outside TopMemoryContext (TopGlobalMemory).
+ * BadArg if context is invalid GlobalMemory.
+ * BadArg if context is TopMemoryContext (TopGlobalMemory).
+ */
+void
+GlobalMemoryDestroy(GlobalMemory context)
+{
+ AssertState(MemoryContextEnabled);
+ AssertArg(IsA(context,GlobalMemory));
+ AssertArg(context != &TopGlobalMemoryData);
+
+ AllocSetReset(&context->setData);
+
+ /* unlink and delete the context */
+ OrderedElemPop(&context->elemData);
+ MemoryContextFree(TopMemoryContext, (Pointer)context);
+}
+
+/*****************************************************************************
+ * PRIVATE *
+ *****************************************************************************/
+
+/*
+ * GlobalMemoryAlloc --
+ * Returns pointer to aligned space in the global context.
+ *
+ * Exceptions:
+ * ExhaustedMemory if allocation fails.
+ */
+static Pointer
+GlobalMemoryAlloc(GlobalMemory this, Size size)
+{
+ return (AllocSetAlloc(&this->setData, size));
+}
+
+/*
+ * GlobalMemoryFree --
+ * Frees allocated memory in the global context.
+ *
+ * Exceptions:
+ * BadContextErr if current context is not the global context.
+ * BadArgumentsErr if pointer is invalid.
+ */
+static void
+GlobalMemoryFree(GlobalMemory this,
+ Pointer pointer)
+{
+ AllocSetFree(&this->setData, pointer);
+}
+
+/*
+ * GlobalMemoryRealloc --
+ * Returns pointer to aligned space in the global context.
+ *
+ * Note:
+ * Memory associated with the pointer is freed before return.
+ *
+ * Exceptions:
+ * BadContextErr if current context is not the global context.
+ * BadArgumentsErr if pointer is invalid.
+ * NoMoreMemoryErr if allocation fails.
+ */
+static Pointer
+GlobalMemoryRealloc(GlobalMemory this,
+ Pointer pointer,
+ Size size)
+{
+ return (AllocSetRealloc(&this->setData, pointer, size));
+}
+
+/*
+ * GlobalMemoryGetName --
+ * Returns name string for context.
+ *
+ * Exceptions:
+ * ???
+ */
+static char*
+GlobalMemoryGetName(GlobalMemory this)
+{
+ return (this->name);
+}
+
+/*
+ * GlobalMemoryDump --
+ * Dumps global memory context for debugging.
+ *
+ * Exceptions:
+ * ???
+ */
+static void
+GlobalMemoryDump(GlobalMemory this)
+{
+ GlobalMemory context;
+
+ printf("--\n%s:\n", GlobalMemoryGetName(this));
+
+ context = (GlobalMemory)OrderedElemGetPredecessor(&this->elemData);
+ if (PointerIsValid(context)) {
+ printf("\tpredecessor=%s\n", GlobalMemoryGetName(context));
+ }
+
+ context = (GlobalMemory)OrderedElemGetSuccessor(&this->elemData);
+ if (PointerIsValid(context)) {
+ printf("\tsucessor=%s\n", GlobalMemoryGetName(context));
+ }
+
+ AllocSetDump(&this->setData); /* XXX is this right interface */
+}
+
+/*
+ * DumpGlobalMemories --
+ * Dumps all global memory contexts for debugging.
+ *
+ * Exceptions:
+ * ???
+ */
+static void
+DumpGlobalMemories()
+{
+ GlobalMemory context;
+
+ context = (GlobalMemory)OrderedSetGetHead(&ActiveGlobalMemorySetData);
+
+ while (PointerIsValid(context)) {
+ GlobalMemoryDump(context);
+
+ context = (GlobalMemory)OrderedElemGetSuccessor(
+ &context->elemData);
+ }
+}
+