1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-16 15:02:33 +03:00

Add support for loadable modules to allocated shared memory and

lightweight locks.

Marc Munro
This commit is contained in:
Bruce Momjian
2006-08-01 19:03:11 +00:00
parent c61607bd52
commit 2c6d96cef6
6 changed files with 261 additions and 13 deletions

View File

@@ -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);
/*

View File

@@ -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
@@ -192,6 +321,22 @@ ShmemAlloc(Size size)
return newSpace;
}
/*
* 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
*