diff options
author | Bruce Momjian <bruce@momjian.us> | 2006-08-01 19:03:11 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2006-08-01 19:03:11 +0000 |
commit | 2c6d96cef6c9d9a1a8bf80c5f6a761d29f7a2a47 (patch) | |
tree | f26a1a8ee27eaf0008673ccc6d2ca9180d88c9cd /src/backend/storage/ipc | |
parent | c61607bd52d84bc543f451ea27c22e8212a48b24 (diff) |
Add support for loadable modules to allocated shared memory and
lightweight locks.
Marc Munro
Diffstat (limited to 'src/backend/storage/ipc')
-rw-r--r-- | src/backend/storage/ipc/ipci.c | 22 | ||||
-rw-r--r-- | src/backend/storage/ipc/shmem.c | 161 |
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. |