summaryrefslogtreecommitdiff
path: root/src/backend/storage/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/ipc')
-rw-r--r--src/backend/storage/ipc/ipci.c22
-rw-r--r--src/backend/storage/ipc/shmem.c161
2 files changed, 174 insertions, 9 deletions
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index 0b0bf77eee6..a4d36d157be 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.86 2006/07/15 15:47:17 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.87 2006/08/01 19:03:11 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -57,6 +57,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
{
PGShmemHeader *seghdr;
Size size;
+ Size size_b4addins;
int numSemas;
/*
@@ -93,6 +94,15 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
/* might as well round it off to a multiple of a typical page size */
size = add_size(size, 8192 - (size % 8192));
+ /*
+ * The shared memory for add-ins is treated as a separate
+ * segment, but in reality it is not.
+ */
+ size_b4addins = size;
+ size = add_size(size, AddinShmemSize());
+ /* round it off again */
+ size = add_size(size, 8192 - (size % 8192));
+
elog(DEBUG3, "invoking IpcMemoryCreate(size=%lu)",
(unsigned long) size);
@@ -101,6 +111,16 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
*/
seghdr = PGSharedMemoryCreate(size, makePrivate, port);
+ /*
+ * Modify hdr to show segment size before add-ins
+ */
+ seghdr->totalsize = size_b4addins;
+
+ /*
+ * Set up segment header sections in each Addin context
+ */
+ InitAddinContexts((void *) ((char *) seghdr + size_b4addins));
+
InitShmemAccess(seghdr);
/*
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 6a65429f0fc..3c48173f2f6 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.94 2006/07/22 23:04:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.95 2006/08/01 19:03:11 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -61,6 +61,15 @@
* cannot be redistributed to other tables. We could build a simple
* hash bucket garbage collector if need be. Right now, it seems
* unnecessary.
+ *
+ * (e) Add-ins can request their own logical shared memory segments
+ * by calling RegisterAddinContext() from the preload-libraries hook.
+ * Each call establishes a uniquely named add-in shared memopry
+ * context which will be set up as part of postgres intialisation.
+ * Memory can be allocated from these contexts using
+ * ShmemAllocFromContext(), and can be reset to its initial condition
+ * using ShmemResetContext(). Also, RegisterAddinLWLock(LWLockid *lock_ptr)
+ * can be used to request that a LWLock be allocated, placed into *lock_ptr.
*/
#include "postgres.h"
@@ -86,6 +95,19 @@ slock_t *ShmemLock; /* spinlock for shared memory and LWLock
static HTAB *ShmemIndex = NULL; /* primary index hashtable for shmem */
+/* Structures and globals for managing add-in shared memory contexts */
+typedef struct context
+{
+ char *name;
+ Size size;
+ PGShmemHeader *seg_hdr;
+ struct context *next;
+} ContextNode;
+
+static ContextNode *addin_contexts = NULL;
+static Size addin_contexts_size = 0;
+
+
/*
* InitShmemAccess() --- set up basic pointers to shared memory.
@@ -135,12 +157,104 @@ InitShmemAllocation(void)
* (This doesn't really belong here, but not worth moving.)
*/
ShmemVariableCache = (VariableCache)
- ShmemAlloc(sizeof(*ShmemVariableCache));
+ ShmemAlloc(sizeof(*ShmemVariableCache));
memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache));
}
/*
- * ShmemAlloc -- allocate max-aligned chunk from shared memory
+ * RegisterAddinContext -- Register the requirement for a named shared
+ * memory context.
+ */
+void
+RegisterAddinContext(const char *name, Size size)
+{
+ char *newstr = malloc(strlen(name) + 1);
+ ContextNode *node = malloc(sizeof(ContextNode));
+
+ strcpy(newstr, name);
+ node->name = newstr;
+
+ /* Round up to typical page size */
+ node->size = add_size(size, 8192 - (size % 8192));
+ node->next = addin_contexts;
+
+ addin_contexts = node;
+ addin_contexts_size = add_size(addin_contexts_size, node->size);
+}
+
+
+/*
+ * ContextFromName -- Return the ContextNode for the given named
+ * context, or NULL if not found.
+ */
+static ContextNode *
+ContextFromName(const char *name)
+{
+ ContextNode *context = addin_contexts;
+
+ while (context)
+ {
+ if (strcmp(name, context->name) == 0)
+ return context;
+ context = context->next;
+ }
+ return NULL;
+}
+
+/*
+ * InitAddinContexts -- Initialise the registered addin shared memory
+ * contexts.
+ */
+void
+InitAddinContexts(void *start)
+{
+ PGShmemHeader *next_segment = (PGShmemHeader *) start;
+ ContextNode *context = addin_contexts;
+
+ while (context)
+ {
+ context->seg_hdr = next_segment;
+
+ next_segment->totalsize = context->size;
+ next_segment->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
+
+ next_segment = (PGShmemHeader *)
+ ((char *) next_segment + context->size);
+ context = context->next;
+ }
+}
+
+/*
+ * ShmemResetContext -- Re-initialise the named addin shared memory context.
+ */
+void
+ShmemResetContext(const char *name)
+{
+ PGShmemHeader *segment;
+ ContextNode *context = ContextFromName(name);
+
+ if (!context)
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("cannot reset unknown shared memory context %s",
+ name)));
+
+ segment = context->seg_hdr;
+ segment->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
+}
+
+/*
+ * AddinShmemSize -- Report how much shared memory has been registered
+ * for add-ins.
+ */
+Size
+AddinShmemSize(void)
+{
+ return addin_contexts_size;
+}
+
+/*
+ * ShmemAllocFromContext -- allocate max-aligned chunk from shared memory
*
* Assumes ShmemLock and ShmemSegHdr are initialized.
*
@@ -149,15 +263,30 @@ InitShmemAllocation(void)
* to be compatible with malloc().
*/
void *
-ShmemAlloc(Size size)
+ShmemAllocFromContext(Size size, const char *context_name)
{
- Size newStart;
- Size newFree;
- void *newSpace;
+ Size newStart;
+ Size newFree;
+ void *newSpace;
+ ContextNode *context;
/* use volatile pointer to prevent code rearrangement */
volatile PGShmemHeader *shmemseghdr = ShmemSegHdr;
+ /*
+ * if context_name is provided, allocate from the named context
+ */
+ if (context_name)
+ {
+ context = ContextFromName(context_name);
+ if (!context)
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("cannot reset unknown shared memory context %s",
+ context_name)));
+ shmemseghdr = context->seg_hdr;
+ }
+
/*
* ensure all space is adequately aligned.
*/
@@ -176,7 +305,7 @@ ShmemAlloc(Size size)
newFree = newStart + size;
if (newFree <= shmemseghdr->totalsize)
{
- newSpace = (void *) MAKE_PTR(newStart);
+ newSpace = (void *) MAKE_PTRFROM((SHMEM_OFFSET) shmemseghdr, newStart);
shmemseghdr->freeoffset = newFree;
}
else
@@ -193,6 +322,22 @@ ShmemAlloc(Size size)
}
/*
+ * ShmemAlloc -- allocate max-aligned chunk from shared memory
+ *
+ * Assumes ShmemLock and ShmemSegHdr are initialized.
+ *
+ * Returns: real pointer to memory or NULL if we are out
+ * of space. Has to return a real pointer in order
+ * to be compatible with malloc().
+ */
+
+void *
+ShmemAlloc(Size size)
+{
+ return ShmemAllocFromContext(size, NULL);
+}
+
+/*
* ShmemIsValid -- test if an offset refers to valid shared memory
*
* Returns TRUE if the pointer is valid.