postgresql/src/backend/utils/mmgr/portalmem.c

1012 lines
24 KiB
C
Raw Normal View History

/*-------------------------------------------------------------------------
*
* portalmem.c--
* backend portal memory context management stuff
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
1997-09-18 22:22:58 +02:00
* $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.9 1997/09/18 20:22:36 momjian 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 */
1996-11-03 07:54:38 +01:00
#include "postgres.h"
#include "lib/hasht.h"
#include "utils/module.h"
#include "utils/excid.h" /* for Unimplemented */
#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"
static void CollectNamedPortals(Portal *portalP, int destroy);
static Portal PortalHeapMemoryGetPortal(PortalHeapMemory context);
static PortalVariableMemory PortalHeapMemoryGetVariableMemory(PortalHeapMemory context);
static void PortalResetHeapMemory(Portal portal);
static Portal PortalVariableMemoryGetPortal(PortalVariableMemory context);
/* ----------------
* 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]; \
1997-09-18 22:22:58 +02:00
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]; \
1997-09-18 22:22:58 +02:00
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]; \
1997-09-18 22:22:58 +02:00
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
*/
static 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
* ----------------
*/
1996-11-08 07:02:30 +01:00
#ifdef NOT_USED
static void
PortalDump(Portal *thisP)
{
/* XXX state/argument checking here */
PortalVariableMemoryDump(PortalGetVariableMemory(*thisP));
PortalHeapMemoryDump(PortalGetHeapMemory(*thisP));
}
1996-11-08 07:02:30 +01:00
#endif
/* ----------------
* DumpPortals
* ----------------
*/
1996-11-08 07:02:30 +01:00
#ifdef NOT_USED
static void
DumpPortals()
{
/* XXX state checking here */
HashTableWalk(PortalHashTable, PortalDump, 0);
}
1996-11-08 07:02:30 +01:00
#endif
/* ----------------------------------------------------------------
* 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.
* ----------------
*/
static 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 */
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.
*/
static 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.
*/
static 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.
*/
#ifdef NOT_USED
PortalHeapMemory
PortalVariableMemoryGetHeapMemory(PortalVariableMemory context)
{
return ((PortalHeapMemory) ((char *) context
- offsetof(PortalD, variable)
+offsetof(PortalD, heap)));
}
#endif
/*
* PortalHeapMemoryGetVariableMemory --
* Returns variable memory context associated with given heap memory.
*
* Exceptions:
* BadState if called when disabled.
* BadArg if context is invalid.
*/
static PortalVariableMemory
PortalHeapMemoryGetVariableMemory(PortalHeapMemory context)
{
return ((PortalVariableMemory) ((char *) context
- offsetof(PortalD, heap)
+offsetof(PortalD, variable)));
}