88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmqueue.c,v 1.13 2000 /01/26 05:56:58 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmqueue.c,v 1.14 2001 /01/22 22:30:06 tgl Exp $
1212 *
1313 * NOTES
1414 *
1515 * Package for managing doubly-linked lists in shared memory.
1616 * The only tricky thing is that SHM_QUEUE will usually be a field
17- * in a larger record.SHMQueueGetFirst has to return a pointer
17+ * in a larger record.SHMQueueNext has to return a pointer
1818 * to the record itself instead of a pointer to the SHMQueue field
19- * of the record. It takes an extrapointer and does some extra
19+ * of the record. It takes an extraparameter and does some extra
2020 * pointer arithmetic to do this correctly.
2121 *
2222 * NOTE: These are set up so they can be turned into macros some day.
2323 *
2424 *-------------------------------------------------------------------------
2525 */
26-
2726#include "postgres.h"
27+
2828#include "storage/shmem.h"
2929
3030/*#define SHMQUEUE_DEBUG*/
3131#ifdef SHMQUEUE_DEBUG
32- #define SHMQUEUE_DEBUG_DEL /* deletions */
33- #define SHMQUEUE_DEBUG_HD /* head inserts */
34- #define SHMQUEUE_DEBUG_TL /* tail inserts */
32+
3533#define SHMQUEUE_DEBUG_ELOG NOTICE
36- #endif /* SHMQUEUE_DEBUG */
34+
35+ static void dumpQ (SHM_QUEUE * q ,char * s );
36+
37+ #endif
38+
3739
3840/*
3941 * ShmemQueueInit -- make the head of a new queue point
@@ -84,160 +86,108 @@ SHMQueueDelete(SHM_QUEUE *queue)
8486Assert (SHM_PTR_VALID (nextElem ));
8587Assert (SHM_PTR_VALID (prevElem ));
8688
87- #ifdef SHMQUEUE_DEBUG_DEL
89+ #ifdef SHMQUEUE_DEBUG
8890dumpQ (queue ,"in SHMQueueDelete: begin" );
89- #endif /* SHMQUEUE_DEBUG_DEL */
91+ #endif
9092
9193prevElem -> next = (queue )-> next ;
9294nextElem -> prev = (queue )-> prev ;
9395
94- #ifdef SHMQUEUE_DEBUG_DEL
95- dumpQ ((SHM_QUEUE * )MAKE_PTR (queue -> prev ),"in SHMQueueDelete: end" );
96- #endif /* SHMQUEUE_DEBUG_DEL */
97- }
98-
99- #ifdef SHMQUEUE_DEBUG
100- void
101- dumpQ (SHM_QUEUE * q ,char * s )
102- {
103- char elem [NAMEDATALEN ];
104- char buf [1024 ];
105- SHM_QUEUE * start = q ;
106- int count = 0 ;
107-
108- sprintf (buf ,"q prevs: %x" ,MAKE_OFFSET (q ));
109- q = (SHM_QUEUE * )MAKE_PTR (q -> prev );
110- while (q != start )
111- {
112- sprintf (elem ,"--->%x" ,MAKE_OFFSET (q ));
113- strcat (buf ,elem );
114- q = (SHM_QUEUE * )MAKE_PTR (q -> prev );
115- if (q -> prev == MAKE_OFFSET (q ))
116- break ;
117- if (count ++ > 40 )
118- {
119- strcat (buf ,"BAD PREV QUEUE!!" );
120- break ;
121- }
122- }
123- sprintf (elem ,"--->%x" ,MAKE_OFFSET (q ));
124- strcat (buf ,elem );
125- elog (SHMQUEUE_DEBUG_ELOG ,"%s: %s" ,s ,buf );
126-
127- sprintf (buf ,"q nexts: %x" ,MAKE_OFFSET (q ));
128- count = 0 ;
129- q = (SHM_QUEUE * )MAKE_PTR (q -> next );
130- while (q != start )
131- {
132- sprintf (elem ,"--->%x" ,MAKE_OFFSET (q ));
133- strcat (buf ,elem );
134- q = (SHM_QUEUE * )MAKE_PTR (q -> next );
135- if (q -> next == MAKE_OFFSET (q ))
136- break ;
137- if (count ++ > 10 )
138- {
139- strcat (buf ,"BAD NEXT QUEUE!!" );
140- break ;
141- }
142- }
143- sprintf (elem ,"--->%x" ,MAKE_OFFSET (q ));
144- strcat (buf ,elem );
145- elog (SHMQUEUE_DEBUG_ELOG ,"%s: %s" ,s ,buf );
96+ (queue )-> prev = (queue )-> next = INVALID_OFFSET ;
14697}
14798
148- #endif /* SHMQUEUE_DEBUG */
149-
15099/*
151- * SHMQueueInsertHD -- put elem in queue between the queue head
152- *and its "prev" element.
100+ * SHMQueueInsertBefore -- put elem in queue before the given queue
101+ *element. Inserting "before" the queue head puts the elem
102+ *at the tail of the queue.
153103 */
154- #ifdef NOT_USED
155104void
156- SHMQueueInsertHD (SHM_QUEUE * queue ,SHM_QUEUE * elem )
105+ SHMQueueInsertBefore (SHM_QUEUE * queue ,SHM_QUEUE * elem )
157106{
158107SHM_QUEUE * prevPtr = (SHM_QUEUE * )MAKE_PTR ((queue )-> prev );
159108SHMEM_OFFSET elemOffset = MAKE_OFFSET (elem );
160109
161110Assert (SHM_PTR_VALID (queue ));
162111Assert (SHM_PTR_VALID (elem ));
163112
164- #ifdef SHMQUEUE_DEBUG_HD
165- dumpQ (queue ,"inSHMQueueInsertHD : begin" );
166- #endif /* SHMQUEUE_DEBUG_HD */
113+ #ifdef SHMQUEUE_DEBUG
114+ dumpQ (queue ,"inSHMQueueInsertBefore : begin" );
115+ #endif
167116
168117(elem )-> next = prevPtr -> next ;
169118(elem )-> prev = queue -> prev ;
170119(queue )-> prev = elemOffset ;
171120prevPtr -> next = elemOffset ;
172121
173- #ifdef SHMQUEUE_DEBUG_HD
174- dumpQ (queue ,"in SHMQueueInsertHD: end" );
175- #endif /* SHMQUEUE_DEBUG_HD */
176- }
177-
122+ #ifdef SHMQUEUE_DEBUG
123+ dumpQ (queue ,"in SHMQueueInsertBefore: end" );
178124#endif
125+ }
179126
127+ /*
128+ * SHMQueueInsertAfter -- put elem in queue after the given queue
129+ *element. Inserting "after" the queue head puts the elem
130+ *at the head of the queue.
131+ */
132+ #ifdef NOT_USED
180133void
181- SHMQueueInsertTL (SHM_QUEUE * queue ,SHM_QUEUE * elem )
134+ SHMQueueInsertAfter (SHM_QUEUE * queue ,SHM_QUEUE * elem )
182135{
183136SHM_QUEUE * nextPtr = (SHM_QUEUE * )MAKE_PTR ((queue )-> next );
184137SHMEM_OFFSET elemOffset = MAKE_OFFSET (elem );
185138
186139Assert (SHM_PTR_VALID (queue ));
187140Assert (SHM_PTR_VALID (elem ));
188141
189- #ifdef SHMQUEUE_DEBUG_TL
190- dumpQ (queue ,"inSHMQueueInsertTL : begin" );
191- #endif /* SHMQUEUE_DEBUG_TL */
142+ #ifdef SHMQUEUE_DEBUG
143+ dumpQ (queue ,"inSHMQueueInsertAfter : begin" );
144+ #endif
192145
193146(elem )-> prev = nextPtr -> prev ;
194147(elem )-> next = queue -> next ;
195148(queue )-> next = elemOffset ;
196149nextPtr -> prev = elemOffset ;
197150
198- #ifdef SHMQUEUE_DEBUG_TL
199- dumpQ (queue ,"inSHMQueueInsertTL : end" );
200- #endif /* SHMQUEUE_DEBUG_TL */
151+ #ifdef SHMQUEUE_DEBUG
152+ dumpQ (queue ,"inSHMQueueInsertAfter : end" );
153+ #endif
201154}
155+ #endif /* NOT_USED */
202156
203- /*
204- *SHMQueueFirst -- Get thefirst element from a queue
157+ /*--------------------
158+ *SHMQueueNext -- Get thenext element from a queue
205159 *
206- * First element is queue->next. If SHMQueue is part of
160+ * To start the iteration, pass the queue head as both queue and curElem.
161+ * Returns NULL if no more elements.
162+ *
163+ * Next element is at curElem->next. If SHMQueue is part of
207164 * a larger structure, we want to return a pointer to the
208165 * whole structure rather than a pointer to its SHMQueue field.
209166 * I.E. struct {
210167 *intstuff;
211168 *SHMQueueelem;
212169 * } ELEMType;
213- * when this element is in a queue (queue->next) is struct.elem.
214- * nextQueue allows us to calculate the offset of the SHMQueue
215- * field in the structure.
216- *
217- * call to SHMQueueFirst should take these parameters:
170+ * When this element is in a queue, (prevElem->next) is struct.elem.
171+ * We subtract linkOffset to get the correct start address of the structure.
218172 *
219- * &(queueHead),&firstElem,&(firstElem->next)
173+ * calls to SHMQueueNext should take these parameters:
220174 *
221- * Note that firstElem may well be uninitialized. if firstElem
222- * is initially K, &(firstElem->next) will be K+ the offset to
223- * next.
175+ * &(queueHead), &(queueHead), offsetof(ELEMType, elem)
176+ * or
177+ * &(queueHead), &(curElem->elem), offsetof(ELEMType, elem)
178+ *--------------------
224179 */
225- void
226- SHMQueueFirst (SHM_QUEUE * queue ,Pointer * nextPtrPtr , SHM_QUEUE * nextQueue )
180+ Pointer
181+ SHMQueueNext (SHM_QUEUE * queue ,SHM_QUEUE * curElem , Size linkOffset )
227182{
228- SHM_QUEUE * elemPtr = (SHM_QUEUE * )MAKE_PTR ((queue )-> next );
183+ SHM_QUEUE * elemPtr = (SHM_QUEUE * )MAKE_PTR ((curElem )-> next );
229184
230- Assert (SHM_PTR_VALID (queue ));
231- * nextPtrPtr = (Pointer ) (((unsigned long )* nextPtrPtr )+
232- ((unsigned long )elemPtr )- ((unsigned long )nextQueue ));
233-
234- /*
235- * nextPtrPtr a ptr to a structure linked in the queue nextQueue is
236- * the SHMQueue field of the structure nextPtrPtr - nextQueue is 0
237- * minus the offset of the queue field n the record elemPtr +
238- * (*nextPtrPtr - nexQueue) is the start of the structure containing
239- * elemPtr.
240- */
185+ Assert (SHM_PTR_VALID (curElem ));
186+
187+ if (elemPtr == queue )/* back to the queue head? */
188+ return NULL ;
189+
190+ return (Pointer ) (((char * )elemPtr )- linkOffset );
241191}
242192
243193/*
@@ -255,3 +205,55 @@ SHMQueueEmpty(SHM_QUEUE *queue)
255205}
256206return FALSE;
257207}
208+
209+ #ifdef SHMQUEUE_DEBUG
210+
211+ static void
212+ dumpQ (SHM_QUEUE * q ,char * s )
213+ {
214+ char elem [NAMEDATALEN ];
215+ char buf [1024 ];
216+ SHM_QUEUE * start = q ;
217+ int count = 0 ;
218+
219+ sprintf (buf ,"q prevs: %lx" ,MAKE_OFFSET (q ));
220+ q = (SHM_QUEUE * )MAKE_PTR (q -> prev );
221+ while (q != start )
222+ {
223+ sprintf (elem ,"--->%lx" ,MAKE_OFFSET (q ));
224+ strcat (buf ,elem );
225+ q = (SHM_QUEUE * )MAKE_PTR (q -> prev );
226+ if (q -> prev == MAKE_OFFSET (q ))
227+ break ;
228+ if (count ++ > 40 )
229+ {
230+ strcat (buf ,"BAD PREV QUEUE!!" );
231+ break ;
232+ }
233+ }
234+ sprintf (elem ,"--->%lx" ,MAKE_OFFSET (q ));
235+ strcat (buf ,elem );
236+ elog (SHMQUEUE_DEBUG_ELOG ,"%s: %s" ,s ,buf );
237+
238+ sprintf (buf ,"q nexts: %lx" ,MAKE_OFFSET (q ));
239+ count = 0 ;
240+ q = (SHM_QUEUE * )MAKE_PTR (q -> next );
241+ while (q != start )
242+ {
243+ sprintf (elem ,"--->%lx" ,MAKE_OFFSET (q ));
244+ strcat (buf ,elem );
245+ q = (SHM_QUEUE * )MAKE_PTR (q -> next );
246+ if (q -> next == MAKE_OFFSET (q ))
247+ break ;
248+ if (count ++ > 10 )
249+ {
250+ strcat (buf ,"BAD NEXT QUEUE!!" );
251+ break ;
252+ }
253+ }
254+ sprintf (elem ,"--->%lx" ,MAKE_OFFSET (q ));
255+ strcat (buf ,elem );
256+ elog (SHMQUEUE_DEBUG_ELOG ,"%s: %s" ,s ,buf );
257+ }
258+
259+ #endif /* SHMQUEUE_DEBUG */