aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/ipc/ipci.c22
-rw-r--r--src/backend/storage/ipc/shmem.c161
-rw-r--r--src/backend/storage/lmgr/lwlock.c71
-rw-r--r--src/include/storage/lwlock.h4
-rw-r--r--src/include/storage/pg_shmem.h9
-rw-r--r--src/include/storage/shmem.h7
6 files changed, 261 insertions, 13 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.
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index f10de0dca0e..16791bf620d 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.42 2006/07/24 16:32:45 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.43 2006/08/01 19:03:11 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -29,6 +29,10 @@
#include "storage/spin.h"
+static int NumAddinLWLocks(void);
+static void AssignAddinLWLocks(void);
+
+
/* We use the ShmemLock spinlock to protect LWLockAssign */
extern slock_t *ShmemLock;
@@ -90,6 +94,62 @@ static int *ex_acquire_counts;
static int *block_counts;
#endif
+/*
+ * Structures and globals to allow add-ins to register for their own
+ * lwlocks from the preload-libraries hook.
+ */
+typedef struct LWLockNode
+{
+ LWLockId *lock;
+ struct LWLockNode *next;
+} LWLockNode;
+
+static LWLockNode *addin_locks = NULL;
+static int num_addin_locks = 0;
+
+
+/*
+ * RegisterAddinLWLock() --- Allow an andd-in to request a LWLock
+ * from the preload-libraries hook.
+ */
+void
+RegisterAddinLWLock(LWLockId *lock)
+{
+ LWLockNode *locknode = malloc(sizeof(LWLockNode));
+
+ locknode->next = addin_locks;
+ locknode->lock = lock;
+
+ addin_locks = locknode;
+ num_addin_locks++;
+}
+
+/*
+ * NumAddinLWLocks() --- Return the number of LWLocks requested by add-ins.
+ */
+int
+NumAddinLWLocks()
+{
+ return num_addin_locks;
+}
+
+/*
+ * AssignAddinLWLocks() --- Assign LWLocks previously requested by add-ins.
+ */
+void
+AssignAddinLWLocks()
+{
+ LWLockNode *node = addin_locks;
+
+ while (node)
+ {
+ *(node->lock) = LWLockAssign();
+ node = node->next;
+ }
+}
+
+
+
#ifdef LOCK_DEBUG
bool Trace_lwlocks = false;
@@ -174,6 +234,9 @@ NumLWLocks(void)
/* Leave a few extra for use by user-defined modules. */
numLocks += NUM_USER_DEFINED_LWLOCKS;
+ /* Add the number that have been explicitly requested by add-ins. */
+ numLocks += NumAddinLWLocks();
+
return numLocks;
}
@@ -241,6 +304,12 @@ CreateLWLocks(void)
LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int));
LWLockCounter[0] = (int) NumFixedLWLocks;
LWLockCounter[1] = numLocks;
+
+ /*
+ * Allocate LWLocks for those add-ins that have explicitly requested
+ * them.
+ */
+ AssignAddinLWLocks();
}
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index ce779932430..5c4db528920 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/lwlock.h,v 1.30 2006/07/23 23:08:46 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/lwlock.h,v 1.31 2006/08/01 19:03:11 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -92,4 +92,6 @@ extern int NumLWLocks(void);
extern Size LWLockShmemSize(void);
extern void CreateLWLocks(void);
+extern void RegisterAddinLWLock(LWLockId *lock);
+
#endif /* LWLOCK_H */
diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h
index 7a89f318206..47f6709a674 100644
--- a/src/include/storage/pg_shmem.h
+++ b/src/include/storage/pg_shmem.h
@@ -17,7 +17,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/pg_shmem.h,v 1.18 2006/03/05 15:58:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/pg_shmem.h,v 1.19 2006/08/01 19:03:11 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -51,4 +51,11 @@ extern PGShmemHeader *PGSharedMemoryCreate(Size size, bool makePrivate,
extern bool PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2);
extern void PGSharedMemoryDetach(void);
+
+extern void RegisterAddinContext(const char *name, Size size);
+extern Size AddinShmemSize(void);
+extern void InitAddinContexts(void * start);
+extern void *ShmemAllocFromContext(Size size, const char *name);
+extern void ShmemResetContext(const char *name);
+
#endif /* PG_SHMEM_H */
diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h
index 96a67b069a9..bd55fbdb5c8 100644
--- a/src/include/storage/shmem.h
+++ b/src/include/storage/shmem.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.47 2006/03/05 15:59:00 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.48 2006/08/01 19:03:11 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -38,6 +38,11 @@ typedef unsigned long SHMEM_OFFSET;
extern DLLIMPORT SHMEM_OFFSET ShmemBase;
+/* coerce an offset into a pointer in a specified address space. This
+ * macro (only) is not confined to the primary shared memory region */
+#define MAKE_PTRFROM(base,xx_offs)\
+ (base+((unsigned long)(xx_offs)))
+
/* coerce an offset into a pointer in this process's address space */
#define MAKE_PTR(xx_offs)\
(ShmemBase+((unsigned long)(xx_offs)))