Skip to content
Snippets Groups Projects
Commit 2c6d96ce authored by Bruce Momjian's avatar Bruce Momjian
Browse files

Add support for loadable modules to allocated shared memory and

lightweight locks.

Marc Munro
parent c61607bd
No related branches found
No related tags found
No related merge requests found
......@@ -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);
/*
......
......@@ -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.
......@@ -140,7 +162,99 @@ InitShmemAllocation(void)
}
/*
* 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;
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
*
......
......@@ -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();
}
......
......@@ -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 */
......@@ -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 */
......@@ -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)))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment