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 */
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
8796static 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 */
137159ShmemVariableCache = (VariableCache )
138- ShmemAlloc (sizeof (* ShmemVariableCache ));
160+ ShmemAlloc (sizeof (* ShmemVariableCache ));
139161memset (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 */
151265void *
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 */
159274volatile 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)
176305newFree = newStart + size ;
177306if (newFree <=shmemseghdr -> totalsize )
178307{
179- newSpace = (void * )MAKE_PTR ( newStart );
308+ newSpace = (void * )MAKE_PTRFROM (( SHMEM_OFFSET ) shmemseghdr , newStart );
180309shmemseghdr -> freeoffset = newFree ;
181310}
182311else
@@ -192,6 +321,22 @@ ShmemAlloc(Size size)
192321return 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 *