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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy