Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2c6d96c

Browse files
committed
Add support for loadable modules to allocated shared memory and
lightweight locks. Marc Munro
1 parent c61607b commit 2c6d96c

File tree

6 files changed

+261
-13
lines changed

6 files changed

+261
-13
lines changed

src/backend/storage/ipc/ipci.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.86 2006/07/15 15:47:17 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.87 2006/08/01 19:03:11 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -57,6 +57,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
5757
{
5858
PGShmemHeader *seghdr;
5959
Size size;
60+
Size size_b4addins;
6061
int numSemas;
6162

6263
/*
@@ -93,6 +94,15 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
9394
/* might as well round it off to a multiple of a typical page size */
9495
size = add_size(size, 8192 - (size % 8192));
9596

97+
/*
98+
* The shared memory for add-ins is treated as a separate
99+
* segment, but in reality it is not.
100+
*/
101+
size_b4addins = size;
102+
size = add_size(size, AddinShmemSize());
103+
/* round it off again */
104+
size = add_size(size, 8192 - (size % 8192));
105+
96106
elog(DEBUG3, "invoking IpcMemoryCreate(size=%lu)",
97107
(unsigned long) size);
98108

@@ -101,6 +111,16 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
101111
*/
102112
seghdr = PGSharedMemoryCreate(size, makePrivate, port);
103113

114+
/*
115+
* Modify hdr to show segment size before add-ins
116+
*/
117+
seghdr->totalsize = size_b4addins;
118+
119+
/*
120+
* Set up segment header sections in each Addin context
121+
*/
122+
InitAddinContexts((void *) ((char *) seghdr + size_b4addins));
123+
104124
InitShmemAccess(seghdr);
105125

106126
/*

src/backend/storage/ipc/shmem.c

Lines changed: 153 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.94 2006/07/22 23:04:39 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.95 2006/08/01 19:03:11 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -61,6 +61,15 @@
6161
* cannot be redistributed to other tables. We could build a simple
6262
* hash bucket garbage collector if need be. Right now, it seems
6363
* unnecessary.
64+
*
65+
* (e) Add-ins can request their own logical shared memory segments
66+
* by calling RegisterAddinContext() from the preload-libraries hook.
67+
* Each call establishes a uniquely named add-in shared memopry
68+
* context which will be set up as part of postgres intialisation.
69+
* Memory can be allocated from these contexts using
70+
* ShmemAllocFromContext(), and can be reset to its initial condition
71+
* using ShmemResetContext(). Also, RegisterAddinLWLock(LWLockid *lock_ptr)
72+
* can be used to request that a LWLock be allocated, placed into *lock_ptr.
6473
*/
6574

6675
#include "postgres.h"
@@ -86,6 +95,19 @@ slock_t *ShmemLock; /* spinlock for shared memory and LWLock
8695

8796
static HTAB *ShmemIndex = NULL; /* primary index hashtable for shmem */
8897

98+
/* Structures and globals for managing add-in shared memory contexts */
99+
typedef struct context
100+
{
101+
char *name;
102+
Size size;
103+
PGShmemHeader *seg_hdr;
104+
struct context *next;
105+
} ContextNode;
106+
107+
static ContextNode *addin_contexts = NULL;
108+
static Size addin_contexts_size = 0;
109+
110+
89111

90112
/*
91113
* InitShmemAccess() --- set up basic pointers to shared memory.
@@ -135,12 +157,104 @@ InitShmemAllocation(void)
135157
* (This doesn't really belong here, but not worth moving.)
136158
*/
137159
ShmemVariableCache = (VariableCache)
138-
ShmemAlloc(sizeof(*ShmemVariableCache));
160+
ShmemAlloc(sizeof(*ShmemVariableCache));
139161
memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache));
140162
}
141163

142164
/*
143-
* ShmemAlloc -- allocate max-aligned chunk from shared memory
165+
* RegisterAddinContext -- Register the requirement for a named shared
166+
* memory context.
167+
*/
168+
void
169+
RegisterAddinContext(const char *name, Size size)
170+
{
171+
char *newstr = malloc(strlen(name) + 1);
172+
ContextNode *node = malloc(sizeof(ContextNode));
173+
174+
strcpy(newstr, name);
175+
node->name = newstr;
176+
177+
/* Round up to typical page size */
178+
node->size = add_size(size, 8192 - (size % 8192));
179+
node->next = addin_contexts;
180+
181+
addin_contexts = node;
182+
addin_contexts_size = add_size(addin_contexts_size, node->size);
183+
}
184+
185+
186+
/*
187+
* ContextFromName -- Return the ContextNode for the given named
188+
* context, or NULL if not found.
189+
*/
190+
static ContextNode *
191+
ContextFromName(const char *name)
192+
{
193+
ContextNode *context = addin_contexts;
194+
195+
while (context)
196+
{
197+
if (strcmp(name, context->name) == 0)
198+
return context;
199+
context = context->next;
200+
}
201+
return NULL;
202+
}
203+
204+
/*
205+
* InitAddinContexts -- Initialise the registered addin shared memory
206+
* contexts.
207+
*/
208+
void
209+
InitAddinContexts(void *start)
210+
{
211+
PGShmemHeader *next_segment = (PGShmemHeader *) start;
212+
ContextNode *context = addin_contexts;
213+
214+
while (context)
215+
{
216+
context->seg_hdr = next_segment;
217+
218+
next_segment->totalsize = context->size;
219+
next_segment->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
220+
221+
next_segment = (PGShmemHeader *)
222+
((char *) next_segment + context->size);
223+
context = context->next;
224+
}
225+
}
226+
227+
/*
228+
* ShmemResetContext -- Re-initialise the named addin shared memory context.
229+
*/
230+
void
231+
ShmemResetContext(const char *name)
232+
{
233+
PGShmemHeader *segment;
234+
ContextNode *context = ContextFromName(name);
235+
236+
if (!context)
237+
ereport(ERROR,
238+
(errcode(ERRCODE_INTERNAL_ERROR),
239+
errmsg("cannot reset unknown shared memory context %s",
240+
name)));
241+
242+
segment = context->seg_hdr;
243+
segment->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
244+
}
245+
246+
/*
247+
* AddinShmemSize -- Report how much shared memory has been registered
248+
* for add-ins.
249+
*/
250+
Size
251+
AddinShmemSize(void)
252+
{
253+
return addin_contexts_size;
254+
}
255+
256+
/*
257+
* ShmemAllocFromContext -- allocate max-aligned chunk from shared memory
144258
*
145259
* Assumes ShmemLock and ShmemSegHdr are initialized.
146260
*
@@ -149,15 +263,30 @@ InitShmemAllocation(void)
149263
* to be compatible with malloc().
150264
*/
151265
void *
152-
ShmemAlloc(Size size)
266+
ShmemAllocFromContext(Size size, const char *context_name)
153267
{
154-
Size newStart;
155-
Size newFree;
156-
void *newSpace;
268+
Size newStart;
269+
Size newFree;
270+
void *newSpace;
271+
ContextNode *context;
157272

158273
/* use volatile pointer to prevent code rearrangement */
159274
volatile PGShmemHeader *shmemseghdr = ShmemSegHdr;
160275

276+
/*
277+
* if context_name is provided, allocate from the named context
278+
*/
279+
if (context_name)
280+
{
281+
context = ContextFromName(context_name);
282+
if (!context)
283+
ereport(ERROR,
284+
(errcode(ERRCODE_INTERNAL_ERROR),
285+
errmsg("cannot reset unknown shared memory context %s",
286+
context_name)));
287+
shmemseghdr = context->seg_hdr;
288+
}
289+
161290
/*
162291
* ensure all space is adequately aligned.
163292
*/
@@ -176,7 +305,7 @@ ShmemAlloc(Size size)
176305
newFree = newStart + size;
177306
if (newFree <= shmemseghdr->totalsize)
178307
{
179-
newSpace = (void *) MAKE_PTR(newStart);
308+
newSpace = (void *) MAKE_PTRFROM((SHMEM_OFFSET) shmemseghdr, newStart);
180309
shmemseghdr->freeoffset = newFree;
181310
}
182311
else
@@ -192,6 +321,22 @@ ShmemAlloc(Size size)
192321
return newSpace;
193322
}
194323

324+
/*
325+
* ShmemAlloc -- allocate max-aligned chunk from shared memory
326+
*
327+
* Assumes ShmemLock and ShmemSegHdr are initialized.
328+
*
329+
* Returns: real pointer to memory or NULL if we are out
330+
* of space. Has to return a real pointer in order
331+
* to be compatible with malloc().
332+
*/
333+
334+
void *
335+
ShmemAlloc(Size size)
336+
{
337+
return ShmemAllocFromContext(size, NULL);
338+
}
339+
195340
/*
196341
* ShmemIsValid -- test if an offset refers to valid shared memory
197342
*

src/backend/storage/lmgr/lwlock.c

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.42 2006/07/24 16:32:45 petere Exp $
18+
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.43 2006/08/01 19:03:11 momjian Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -29,6 +29,10 @@
2929
#include "storage/spin.h"
3030

3131

32+
static int NumAddinLWLocks(void);
33+
static void AssignAddinLWLocks(void);
34+
35+
3236
/* We use the ShmemLock spinlock to protect LWLockAssign */
3337
extern slock_t *ShmemLock;
3438

@@ -90,6 +94,62 @@ static int *ex_acquire_counts;
9094
static int *block_counts;
9195
#endif
9296

97+
/*
98+
* Structures and globals to allow add-ins to register for their own
99+
* lwlocks from the preload-libraries hook.
100+
*/
101+
typedef struct LWLockNode
102+
{
103+
LWLockId *lock;
104+
struct LWLockNode *next;
105+
} LWLockNode;
106+
107+
static LWLockNode *addin_locks = NULL;
108+
static int num_addin_locks = 0;
109+
110+
111+
/*
112+
* RegisterAddinLWLock() --- Allow an andd-in to request a LWLock
113+
* from the preload-libraries hook.
114+
*/
115+
void
116+
RegisterAddinLWLock(LWLockId *lock)
117+
{
118+
LWLockNode *locknode = malloc(sizeof(LWLockNode));
119+
120+
locknode->next = addin_locks;
121+
locknode->lock = lock;
122+
123+
addin_locks = locknode;
124+
num_addin_locks++;
125+
}
126+
127+
/*
128+
* NumAddinLWLocks() --- Return the number of LWLocks requested by add-ins.
129+
*/
130+
int
131+
NumAddinLWLocks()
132+
{
133+
return num_addin_locks;
134+
}
135+
136+
/*
137+
* AssignAddinLWLocks() --- Assign LWLocks previously requested by add-ins.
138+
*/
139+
void
140+
AssignAddinLWLocks()
141+
{
142+
LWLockNode *node = addin_locks;
143+
144+
while (node)
145+
{
146+
*(node->lock) = LWLockAssign();
147+
node = node->next;
148+
}
149+
}
150+
151+
152+
93153

94154
#ifdef LOCK_DEBUG
95155
bool Trace_lwlocks = false;
@@ -174,6 +234,9 @@ NumLWLocks(void)
174234
/* Leave a few extra for use by user-defined modules. */
175235
numLocks += NUM_USER_DEFINED_LWLOCKS;
176236

237+
/* Add the number that have been explicitly requested by add-ins. */
238+
numLocks += NumAddinLWLocks();
239+
177240
return numLocks;
178241
}
179242

@@ -241,6 +304,12 @@ CreateLWLocks(void)
241304
LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int));
242305
LWLockCounter[0] = (int) NumFixedLWLocks;
243306
LWLockCounter[1] = numLocks;
307+
308+
/*
309+
* Allocate LWLocks for those add-ins that have explicitly requested
310+
* them.
311+
*/
312+
AssignAddinLWLocks();
244313
}
245314

246315

src/include/storage/lwlock.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/storage/lwlock.h,v 1.30 2006/07/23 23:08:46 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/storage/lwlock.h,v 1.31 2006/08/01 19:03:11 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -92,4 +92,6 @@ extern int NumLWLocks(void);
9292
extern Size LWLockShmemSize(void);
9393
extern void CreateLWLocks(void);
9494

95+
extern void RegisterAddinLWLock(LWLockId *lock);
96+
9597
#endif /* LWLOCK_H */

0 commit comments

Comments
 (0)