Add support for loadable modules to allocated shared memory and
lightweight locks. Marc Munro
This commit is contained in:
parent
c61607bd52
commit
2c6d96cef6
@ -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.
|
||||
@ -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
|
||||
*
|
||||
|
@ -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)))
|
||||
|
Loading…
Reference in New Issue
Block a user