diff options
Diffstat (limited to 'src/backend/utils/mmgr/portalmem.c')
-rw-r--r-- | src/backend/utils/mmgr/portalmem.c | 980 |
1 files changed, 980 insertions, 0 deletions
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c new file mode 100644 index 00000000000..b43e85a0793 --- /dev/null +++ b/src/backend/utils/mmgr/portalmem.c @@ -0,0 +1,980 @@ +/*------------------------------------------------------------------------- + * + * portalmem.c-- + * backend portal memory context management stuff + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.1.1.1 1996/07/09 06:22:09 scrappy Exp $ + * + *------------------------------------------------------------------------- + */ +/* + * NOTES + * Do not confuse "Portal" with "PortalEntry" (or "PortalBuffer"). + * When a PQexec() routine is run, the resulting tuples + * find their way into a "PortalEntry". The contents of the resulting + * "PortalEntry" can then be inspected by other PQxxx functions. + * + * A "Portal" is a structure used to keep track of queries of the + * form: + * retrieve portal FOO ( blah... ) where blah... + * + * When the backend sees a "retrieve portal" query, it allocates + * a "PortalD" structure, plans the query and then stores the query + * in the portal without executing it. Later, when the backend + * sees a + * fetch 1 into FOO + * + * the system looks up the portal named "FOO" in the portal table, + * gets the planned query and then calls the executor with a feature of + * '(EXEC_FOR 1). The executor then runs the query and returns a single + * tuple. The problem is that we have to hold onto the state of the + * portal query until we see a "close p". This means we have to be + * careful about memory management. + * + * Having said all that, here is what a PortalD currently looks like: + * + * struct PortalD { + * char* name; + * classObj(PortalVariableMemory) variable; + * classObj(PortalHeapMemory) heap; + * List queryDesc; + * EState state; + * void (*cleanup) ARGS((Portal portal)); + * }; + * + * I hope this makes things clearer to whoever reads this -cim 2/22/91 + * + * Here is an old comment taken from nodes/memnodes.h + * + * MemoryContext -- + * A logical context in which memory allocations occur. + * + * The types of memory contexts can be thought of as members of the + * following inheritance hierarchy with properties summarized below. + * + * Node + * | + * MemoryContext___ + * / \ + * GlobalMemory PortalMemoryContext + * / \ + * PortalVariableMemory PortalHeapMemory + * + * Flushed at Flushed at Checkpoints + * Transaction Portal + * Commit Close + * + * GlobalMemory n n n + * PortalVariableMemory n y n + * PortalHeapMemory y y y * + * + */ +#include <stdio.h> /* for sprintf() */ +#include <string.h> /* for strlen, strncpy */ + +#include "c.h" + +#include "lib/hasht.h" +#include "utils/module.h" +#include "utils/excid.h" /* for Unimplemented */ +#include "utils/elog.h" +#include "utils/mcxt.h" +#include "utils/hsearch.h" + +#include "nodes/memnodes.h" +#include "nodes/nodes.h" +#include "nodes/pg_list.h" +#include "nodes/execnodes.h" /* for EState */ + +#include "utils/portal.h" + +/* ---------------- + * ALLOCFREE_ERROR_ABORT + * define this if you want a core dump when you try to + * free memory already freed -cim 2/9/91 + * ---------------- + */ +#undef ALLOCFREE_ERROR_ABORT + +/* ---------------- + * Global state + * ---------------- + */ + +static int PortalManagerEnableCount = 0; +#define MAX_PORTALNAME_LEN 64 /* XXX LONGALIGNable value */ + +typedef struct portalhashent { + char portalname[MAX_PORTALNAME_LEN]; + Portal portal; +} PortalHashEnt; + +#define PortalManagerEnabled (PortalManagerEnableCount >= 1) + +static HTAB *PortalHashTable = NULL; +#define PortalHashTableLookup(NAME, PORTAL) \ + { PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \ + memset(key, 0, MAX_PORTALNAME_LEN); \ + sprintf(key, "%s", NAME); \ + hentry = (PortalHashEnt*)hash_search(PortalHashTable, \ + key, HASH_FIND, &found); \ + if (hentry == NULL) \ + elog(FATAL, "error in PortalHashTable"); \ + if (found) \ + PORTAL = hentry->portal; \ + else \ + PORTAL = NULL; \ + } +#define PortalHashTableInsert(PORTAL) \ + { PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \ + memset(key, 0, MAX_PORTALNAME_LEN); \ + sprintf(key, "%s", PORTAL->name); \ + hentry = (PortalHashEnt*)hash_search(PortalHashTable, \ + key, HASH_ENTER, &found); \ + if (hentry == NULL) \ + elog(FATAL, "error in PortalHashTable"); \ + if (found) \ + elog(NOTICE, "trying to insert a portal name that exists."); \ + hentry->portal = PORTAL; \ + } +#define PortalHashTableDelete(PORTAL) \ + { PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \ + memset(key, 0, MAX_PORTALNAME_LEN); \ + sprintf(key, "%s", PORTAL->name); \ + hentry = (PortalHashEnt*)hash_search(PortalHashTable, \ + key, HASH_REMOVE, &found); \ + if (hentry == NULL) \ + elog(FATAL, "error in PortalHashTable"); \ + if (!found) \ + elog(NOTICE, "trying to delete portal name that does not exist."); \ + } + +static GlobalMemory PortalMemory = NULL; +static char PortalMemoryName[] = "Portal"; + +static Portal BlankPortal = NULL; + +/* ---------------- + * Internal class definitions + * ---------------- + */ +typedef struct HeapMemoryBlockData { + AllocSetData setData; + FixedItemData itemData; +} HeapMemoryBlockData; + +typedef HeapMemoryBlockData *HeapMemoryBlock; + +#define HEAPMEMBLOCK(context) \ + ((HeapMemoryBlock)(context)->block) + +/* ---------------------------------------------------------------- + * Variable and heap memory methods + * ---------------------------------------------------------------- + */ +/* ---------------- + * PortalVariableMemoryAlloc + * ---------------- + */ +static Pointer +PortalVariableMemoryAlloc(PortalVariableMemory this, + Size size) +{ + return (AllocSetAlloc(&this->setData, size)); +} + +/* ---------------- + * PortalVariableMemoryFree + * ---------------- + */ +static void +PortalVariableMemoryFree(PortalVariableMemory this, + Pointer pointer) +{ + AllocSetFree(&this->setData, pointer); +} + +/* ---------------- + * PortalVariableMemoryRealloc + * ---------------- + */ +static Pointer +PortalVariableMemoryRealloc(PortalVariableMemory this, + Pointer pointer, + Size size) +{ + return (AllocSetRealloc(&this->setData, pointer, size)); +} + +/* ---------------- + * PortalVariableMemoryGetName + * ---------------- + */ +static char* +PortalVariableMemoryGetName(PortalVariableMemory this) +{ + return (form("%s-var", PortalVariableMemoryGetPortal(this)->name)); +} + +/* ---------------- + * PortalVariableMemoryDump + * ---------------- + */ +static void +PortalVariableMemoryDump(PortalVariableMemory this) +{ + printf("--\n%s:\n", PortalVariableMemoryGetName(this)); + + AllocSetDump(&this->setData); /* XXX is this the right interface */ +} + +/* ---------------- + * PortalHeapMemoryAlloc + * ---------------- + */ +static Pointer +PortalHeapMemoryAlloc(PortalHeapMemory this, + Size size) +{ + HeapMemoryBlock block = HEAPMEMBLOCK(this); + + AssertState(PointerIsValid(block)); + + return (AllocSetAlloc(&block->setData, size)); +} + +/* ---------------- + * PortalHeapMemoryFree + * ---------------- + */ +static void +PortalHeapMemoryFree(PortalHeapMemory this, + Pointer pointer) +{ + HeapMemoryBlock block = HEAPMEMBLOCK(this); + + AssertState(PointerIsValid(block)); + + if (AllocSetContains(&block->setData, pointer)) + AllocSetFree(&block->setData, pointer); + else { + elog(NOTICE, + "PortalHeapMemoryFree: 0x%x not in alloc set!", + pointer); +#ifdef ALLOCFREE_ERROR_ABORT + Assert(AllocSetContains(&block->setData, pointer)); +#endif /* ALLOCFREE_ERROR_ABORT*/ + } +} + +/* ---------------- + * PortalHeapMemoryRealloc + * ---------------- + */ +static Pointer +PortalHeapMemoryRealloc(PortalHeapMemory this, + Pointer pointer, + Size size) +{ + HeapMemoryBlock block = HEAPMEMBLOCK(this); + + AssertState(PointerIsValid(block)); + + return (AllocSetRealloc(&block->setData, pointer, size)); +} + +/* ---------------- + * PortalHeapMemoryGetName + * ---------------- + */ +static char* +PortalHeapMemoryGetName(PortalHeapMemory this) +{ + return (form("%s-heap", PortalHeapMemoryGetPortal(this)->name)); +} + +/* ---------------- + * PortalHeapMemoryDump + * ---------------- + */ +static void +PortalHeapMemoryDump(PortalHeapMemory this) +{ + HeapMemoryBlock block; + + printf("--\n%s:\n", PortalHeapMemoryGetName(this)); + + /* XXX is this the right interface */ + if (PointerIsValid(this->block)) + AllocSetDump(&HEAPMEMBLOCK(this)->setData); + + /* dump the stack too */ + for (block = (HeapMemoryBlock)FixedStackGetTop(&this->stackData); + PointerIsValid(block); + block = (HeapMemoryBlock) + FixedStackGetNext(&this->stackData, (Pointer)block)) { + + printf("--\n"); + AllocSetDump(&block->setData); + } +} + +/* ---------------------------------------------------------------- + * variable / heap context method tables + * ---------------------------------------------------------------- + */ +static struct MemoryContextMethodsData PortalVariableContextMethodsData = { + PortalVariableMemoryAlloc, /* Pointer (*)(this, uint32) palloc */ + PortalVariableMemoryFree, /* void (*)(this, Pointer) pfree */ + PortalVariableMemoryRealloc,/* Pointer (*)(this, Pointer) repalloc */ + PortalVariableMemoryGetName,/* char* (*)(this) getName */ + PortalVariableMemoryDump /* void (*)(this) dump */ +}; + +static struct MemoryContextMethodsData PortalHeapContextMethodsData = { + PortalHeapMemoryAlloc, /* Pointer (*)(this, uint32) palloc */ + PortalHeapMemoryFree, /* void (*)(this, Pointer) pfree */ + PortalHeapMemoryRealloc, /* Pointer (*)(this, Pointer) repalloc */ + PortalHeapMemoryGetName, /* char* (*)(this) getName */ + PortalHeapMemoryDump /* void (*)(this) dump */ +}; + + +/* ---------------------------------------------------------------- + * private internal support routines + * ---------------------------------------------------------------- + */ +/* ---------------- + * CreateNewBlankPortal + * ---------------- + */ +static void +CreateNewBlankPortal() +{ + Portal portal; + + AssertState(!PortalIsValid(BlankPortal)); + + /* + * make new portal structure + */ + portal = (Portal) + MemoryContextAlloc((MemoryContext)PortalMemory, sizeof *portal); + + /* + * initialize portal variable context + */ + NodeSetTag((Node*)&portal->variable, T_PortalVariableMemory); + AllocSetInit(&portal->variable.setData, DynamicAllocMode, (Size)0); + portal->variable.method = &PortalVariableContextMethodsData; + + /* + * initialize portal heap context + */ + NodeSetTag((Node*)&portal->heap, T_PortalHeapMemory); + portal->heap.block = NULL; + FixedStackInit(&portal->heap.stackData, + offsetof (HeapMemoryBlockData, itemData)); + portal->heap.method = &PortalHeapContextMethodsData; + + /* + * set bogus portal name + */ + portal->name = "** Blank Portal **"; + + /* initialize portal query */ + portal->queryDesc = NULL; + portal->attinfo = NULL; + portal->state = NULL; + portal->cleanup = NULL; + + /* + * install blank portal + */ + BlankPortal = portal; +} + +bool +PortalNameIsSpecial(char *pname) +{ + if (strcmp(pname, VACPNAME) == 0) + return true; + return false; +} + +/* + * This routine is used to collect all portals created in this xaction + * and then destroy them. There is a little trickiness required as a + * result of the dynamic hashing interface to getting every hash entry + * sequentially. Its use of static variables requires that we get every + * entry *before* we destroy anything (destroying updates the hashtable + * and screws up the sequential walk of the table). -mer 17 Aug 1992 + */ +void +CollectNamedPortals(Portal *portalP, int destroy) +{ + static Portal *portalList = (Portal *)NULL; + static int listIndex = 0; + static int maxIndex = 9; + + if (portalList == (Portal *)NULL) + portalList = (Portal *)malloc(10*sizeof(Portal)); + + if (destroy != 0) + { + int i; + + for (i = 0; i < listIndex; i++) + PortalDestroy(&portalList[i]); + listIndex = 0; + } + else + { + Assert(portalP); + Assert(*portalP); + + /* + * Don't delete special portals, up to portal creator to do this + */ + if (PortalNameIsSpecial((*portalP)->name)) + return; + + portalList[listIndex] = *portalP; + listIndex++; + if (listIndex == maxIndex) + { + portalList = (Portal *) + realloc(portalList, (maxIndex+11)*sizeof(Portal)); + maxIndex += 10; + } + } + return; +} + +void +AtEOXact_portals() +{ + HashTableWalk(PortalHashTable, CollectNamedPortals, 0); + CollectNamedPortals(NULL, 1); +} + +/* ---------------- + * PortalDump + * ---------------- + */ +static void +PortalDump(Portal *thisP) +{ + /* XXX state/argument checking here */ + + PortalVariableMemoryDump(PortalGetVariableMemory(*thisP)); + PortalHeapMemoryDump(PortalGetHeapMemory(*thisP)); +} + +/* ---------------- + * DumpPortals + * ---------------- + */ +static void +DumpPortals() +{ + /* XXX state checking here */ + + HashTableWalk(PortalHashTable, PortalDump, 0); +} + +/* ---------------------------------------------------------------- + * public portal interface functions + * ---------------------------------------------------------------- + */ +/* + * EnablePortalManager -- + * Enables/disables the portal management module. + */ +void +EnablePortalManager(bool on) +{ + static bool processing = false; + HASHCTL ctl; + + AssertState(!processing); + AssertArg(BoolIsValid(on)); + + if (BypassEnable(&PortalManagerEnableCount, on)) + return; + + processing = true; + + if (on) { /* initialize */ + EnableMemoryContext(true); + + PortalMemory = CreateGlobalMemory(PortalMemoryName); + + ctl.keysize = MAX_PORTALNAME_LEN; + ctl.datasize = sizeof(Portal); + + /* use PORTALS_PER_USER, defined in utils/portal.h + * as a guess of how many hash table entries to create, initially + */ + PortalHashTable = hash_create(PORTALS_PER_USER * 3, &ctl, HASH_ELEM); + + CreateNewBlankPortal(); + + } else { /* cleanup */ + if (PortalIsValid(BlankPortal)) { + PortalDestroy(&BlankPortal); + MemoryContextFree((MemoryContext)PortalMemory, + (Pointer)BlankPortal); + BlankPortal = NULL; + } + /* + * Each portal must free its non-memory resources specially. + */ + HashTableWalk(PortalHashTable, PortalDestroy, 0); + hash_destroy(PortalHashTable); + PortalHashTable = NULL; + + GlobalMemoryDestroy(PortalMemory); + PortalMemory = NULL; + + EnableMemoryContext(true); + } + + processing = false; +} + +/* + * GetPortalByName -- + * Returns a portal given a portal name; returns blank portal given + * NULL; returns invalid portal if portal not found. + * + * Exceptions: + * BadState if called when disabled. + */ +Portal +GetPortalByName(char *name) +{ + Portal portal; + + AssertState(PortalManagerEnabled); + + if (PointerIsValid(name)) { + PortalHashTableLookup(name, portal); + } + else { + if (!PortalIsValid(BlankPortal)) + CreateNewBlankPortal(); + portal = BlankPortal; + } + + return (portal); +} + +/* + * BlankPortalAssignName -- + * Returns former blank portal as portal with given name. + * + * Side effect: + * All references to the former blank portal become incorrect. + * + * Exceptions: + * BadState if called when disabled. + * BadState if called without an intervening call to GetPortalByName(NULL). + * BadArg if portal name is invalid. + * "WARN" if portal name is in use. + */ +Portal +BlankPortalAssignName(char *name) /* XXX PortalName */ +{ + Portal portal; + uint16 length; + + AssertState(PortalManagerEnabled); + AssertState(PortalIsValid(BlankPortal)); + AssertArg(PointerIsValid(name)); /* XXX PortalName */ + + portal = GetPortalByName(name); + if (PortalIsValid(portal)) { + elog(NOTICE, "BlankPortalAssignName: portal %s already exists", name); + return (portal); + } + + /* + * remove blank portal + */ + portal = BlankPortal; + BlankPortal = NULL; + + /* + * initialize portal name + */ + length = 1 + strlen(name); + portal->name = (char*) + MemoryContextAlloc((MemoryContext)&portal->variable, length); + + strncpy(portal->name, name, length); + + /* + * put portal in table + */ + PortalHashTableInsert(portal); + + return (portal); +} + +/* + * PortalSetQuery -- + * Attaches a "query" to portal. + * + * Exceptions: + * BadState if called when disabled. + * BadArg if portal is invalid. + * BadArg if queryDesc is "invalid." + * BadArg if state is "invalid." + */ +void +PortalSetQuery(Portal portal, + QueryDesc *queryDesc, + TupleDesc attinfo, + EState *state, + void (*cleanup)(Portal portal)) +{ + AssertState(PortalManagerEnabled); + AssertArg(PortalIsValid(portal)); + AssertArg(IsA((Node*)state,EState)); + + portal->queryDesc = queryDesc; + portal->state = state; + portal->attinfo = attinfo; + portal->cleanup = cleanup; +} + +/* + * PortalGetQueryDesc -- + * Returns query attached to portal. + * + * Exceptions: + * BadState if called when disabled. + * BadArg if portal is invalid. + */ +QueryDesc * +PortalGetQueryDesc(Portal portal) +{ + AssertState(PortalManagerEnabled); + AssertArg(PortalIsValid(portal)); + + return (portal->queryDesc); +} + +/* + * PortalGetState -- + * Returns state attached to portal. + * + * Exceptions: + * BadState if called when disabled. + * BadArg if portal is invalid. + */ +EState * +PortalGetState(Portal portal) +{ + AssertState(PortalManagerEnabled); + AssertArg(PortalIsValid(portal)); + + return (portal->state); +} + +/* + * CreatePortal -- + * Returns a new portal given a name. + * + * Note: + * This is expected to be of very limited usability. See instead, + * BlankPortalAssignName. + * + * Exceptions: + * BadState if called when disabled. + * BadArg if portal name is invalid. + * "WARN" if portal name is in use. + */ +Portal +CreatePortal(char *name) /* XXX PortalName */ +{ + Portal portal; + uint16 length; + + AssertState(PortalManagerEnabled); + AssertArg(PointerIsValid(name)); /* XXX PortalName */ + + portal = GetPortalByName(name); + if (PortalIsValid(portal)) { + elog(NOTICE, "CreatePortal: portal %s already exists", name); + return (portal); + } + + /* make new portal structure */ + portal = (Portal) + MemoryContextAlloc((MemoryContext)PortalMemory, sizeof *portal); + + /* initialize portal variable context */ + NodeSetTag((Node*)&portal->variable, T_PortalVariableMemory); + AllocSetInit(&portal->variable.setData, DynamicAllocMode, (Size)0); + portal->variable.method = &PortalVariableContextMethodsData; + + /* initialize portal heap context */ + NodeSetTag((Node*)&portal->heap, T_PortalHeapMemory); + portal->heap.block = NULL; + FixedStackInit(&portal->heap.stackData, + offsetof (HeapMemoryBlockData, itemData)); + portal->heap.method = &PortalHeapContextMethodsData; + + /* initialize portal name */ + length = 1 + strlen(name); + portal->name = (char*) + MemoryContextAlloc((MemoryContext)&portal->variable, length); + strncpy(portal->name, name, length); + + /* initialize portal query */ + portal->queryDesc = NULL; + portal->attinfo = NULL; + portal->state = NULL; + portal->cleanup = NULL; + + /* put portal in table */ + PortalHashTableInsert(portal); + + /* Trap(PointerIsValid(name), Unimplemented); */ + return (portal); +} + +/* + * PortalDestroy -- + * Destroys portal. + * + * Exceptions: + * BadState if called when disabled. + * BadArg if portal is invalid. + */ +void +PortalDestroy(Portal *portalP) +{ + Portal portal = *portalP; + + AssertState(PortalManagerEnabled); + AssertArg(PortalIsValid(portal)); + + /* remove portal from table if not blank portal */ + if (portal != BlankPortal) + PortalHashTableDelete(portal); + + /* reset portal */ + if (PointerIsValid(portal->cleanup)) + (*portal->cleanup)(portal); + + PortalResetHeapMemory(portal); + MemoryContextFree((MemoryContext)&portal->variable, + (Pointer)portal->name); + AllocSetReset(&portal->variable.setData); /* XXX log */ + + if (portal != BlankPortal) + MemoryContextFree((MemoryContext)PortalMemory, (Pointer)portal); +} + +/* ---------------- + * PortalResetHeapMemory -- + * Resets portal's heap memory context. + * + * Someday, Reset, Start, and End can be optimized by keeping a global + * portal module stack of free HeapMemoryBlock's. This will make Start + * and End be fast. + * + * Exceptions: + * BadState if called when disabled. + * BadState if called when not in PortalHeapMemory context. + * BadArg if mode is invalid. + * ---------------- + */ +void +PortalResetHeapMemory(Portal portal) +{ + PortalHeapMemory context; + MemoryContext currentContext; + + context = PortalGetHeapMemory(portal); + + if (PointerIsValid(context->block)) { + /* save present context */ + currentContext = MemoryContextSwitchTo((MemoryContext)context); + + do { + EndPortalAllocMode(); + } while (PointerIsValid(context->block)); + + /* restore context */ + (void) MemoryContextSwitchTo(currentContext); + } +} + +/* + * StartPortalAllocMode -- + * Starts a new block of portal heap allocation using mode and limit; + * the current block is disabled until EndPortalAllocMode is called. + * + * Note: + * Note blocks may be stacked and restored arbitarily. + * The semantics of mode and limit are described in aset.h. + * + * Exceptions: + * BadState if called when disabled. + * BadState if called when not in PortalHeapMemory context. + * BadArg if mode is invalid. + */ +void +StartPortalAllocMode(AllocMode mode, Size limit) +{ + PortalHeapMemory context; + + AssertState(PortalManagerEnabled); + AssertState(IsA(CurrentMemoryContext,PortalHeapMemory)); + /* AssertArg(AllocModeIsValid); */ + + context = (PortalHeapMemory)CurrentMemoryContext; + + /* stack current mode */ + if (PointerIsValid(context->block)) + FixedStackPush(&context->stackData, context->block); + + /* allocate and initialize new block */ + context->block = + MemoryContextAlloc( + (MemoryContext)PortalHeapMemoryGetVariableMemory(context), + sizeof (HeapMemoryBlockData) ); + + /* XXX careful, context->block has never been stacked => bad state */ + + AllocSetInit(&HEAPMEMBLOCK(context)->setData, mode, limit); +} + +/* + * EndPortalAllocMode -- + * Ends current block of portal heap allocation; previous block is + * reenabled. + * + * Note: + * Note blocks may be stacked and restored arbitarily. + * + * Exceptions: + * BadState if called when disabled. + * BadState if called when not in PortalHeapMemory context. + */ +void +EndPortalAllocMode() +{ + PortalHeapMemory context; + + AssertState(PortalManagerEnabled); + AssertState(IsA(CurrentMemoryContext,PortalHeapMemory)); + + context = (PortalHeapMemory)CurrentMemoryContext; + AssertState(PointerIsValid(context->block)); /* XXX Trap(...) */ + + /* free current mode */ + AllocSetReset(&HEAPMEMBLOCK(context)->setData); + MemoryContextFree((MemoryContext)PortalHeapMemoryGetVariableMemory(context), + context->block); + + /* restore previous mode */ + context->block = FixedStackPop(&context->stackData); +} + +/* + * PortalGetVariableMemory -- + * Returns variable memory context for a given portal. + * + * Exceptions: + * BadState if called when disabled. + * BadArg if portal is invalid. + */ +PortalVariableMemory +PortalGetVariableMemory(Portal portal) +{ + return (&portal->variable); +} + +/* + * PortalGetHeapMemory -- + * Returns heap memory context for a given portal. + * + * Exceptions: + * BadState if called when disabled. + * BadArg if portal is invalid. + */ +PortalHeapMemory +PortalGetHeapMemory(Portal portal) +{ + return (&portal->heap); +} + +/* + * PortalVariableMemoryGetPortal -- + * Returns portal containing given variable memory context. + * + * Exceptions: + * BadState if called when disabled. + * BadArg if context is invalid. + */ +Portal +PortalVariableMemoryGetPortal(PortalVariableMemory context) +{ + return ((Portal)((char *)context - offsetof (PortalD, variable))); +} + +/* + * PortalHeapMemoryGetPortal -- + * Returns portal containing given heap memory context. + * + * Exceptions: + * BadState if called when disabled. + * BadArg if context is invalid. + */ +Portal +PortalHeapMemoryGetPortal(PortalHeapMemory context) +{ + return ((Portal)((char *)context - offsetof (PortalD, heap))); +} + +/* + * PortalVariableMemoryGetHeapMemory -- + * Returns heap memory context associated with given variable memory. + * + * Exceptions: + * BadState if called when disabled. + * BadArg if context is invalid. + */ +PortalHeapMemory +PortalVariableMemoryGetHeapMemory(PortalVariableMemory context) +{ + return ((PortalHeapMemory)((char *)context + - offsetof (PortalD, variable) + + offsetof (PortalD, heap))); +} + +/* + * PortalHeapMemoryGetVariableMemory -- + * Returns variable memory context associated with given heap memory. + * + * Exceptions: + * BadState if called when disabled. + * BadArg if context is invalid. + */ +PortalVariableMemory +PortalHeapMemoryGetVariableMemory(PortalHeapMemory context) +{ + return ((PortalVariableMemory)((char *)context + - offsetof (PortalD, heap) + + offsetof (PortalD, variable))); +} + |