Skip to content

Commit e84c429

Browse files
committed
Clean up lockmanager data structures some more, in preparation for planned
rewrite of deadlock checking. Lock holder objects are now reachable from the associated LOCK as well as from the owning PROC. This makes it practical to find all the processes holding a lock, as well as all those waiting on the lock. Also, clean up some of the grottier aspects of the SHMQueue API, and cause the waitProcs list to be stored in the intuitive direction instead of the nonintuitive one. (Bet you didn't know that the code followed the 'prev' link to get to the next waiting process, instead of the 'next' link. It doesn't do that anymore.)
1 parent 56f5f2b commit e84c429

File tree

7 files changed

+504
-318
lines changed

7 files changed

+504
-318
lines changed

src/backend/storage/ipc/shmqueue.c

Lines changed: 111 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,34 @@
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 extra pointer and does some extra
19+
* of the record. It takes an extra parameter 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)
8486
Assert(SHM_PTR_VALID(nextElem));
8587
Assert(SHM_PTR_VALID(prevElem));
8688

87-
#ifdef SHMQUEUE_DEBUG_DEL
89+
#ifdef SHMQUEUE_DEBUG
8890
dumpQ(queue, "in SHMQueueDelete: begin");
89-
#endif /* SHMQUEUE_DEBUG_DEL */
91+
#endif
9092

9193
prevElem->next = (queue)->next;
9294
nextElem->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
155104
void
156-
SHMQueueInsertHD(SHM_QUEUE *queue, SHM_QUEUE *elem)
105+
SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
157106
{
158107
SHM_QUEUE *prevPtr = (SHM_QUEUE *) MAKE_PTR((queue)->prev);
159108
SHMEM_OFFSET elemOffset = MAKE_OFFSET(elem);
160109

161110
Assert(SHM_PTR_VALID(queue));
162111
Assert(SHM_PTR_VALID(elem));
163112

164-
#ifdef SHMQUEUE_DEBUG_HD
165-
dumpQ(queue, "in SHMQueueInsertHD: begin");
166-
#endif /* SHMQUEUE_DEBUG_HD */
113+
#ifdef SHMQUEUE_DEBUG
114+
dumpQ(queue, "in SHMQueueInsertBefore: begin");
115+
#endif
167116

168117
(elem)->next = prevPtr->next;
169118
(elem)->prev = queue->prev;
170119
(queue)->prev = elemOffset;
171120
prevPtr->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
180133
void
181-
SHMQueueInsertTL(SHM_QUEUE *queue, SHM_QUEUE *elem)
134+
SHMQueueInsertAfter(SHM_QUEUE *queue, SHM_QUEUE *elem)
182135
{
183136
SHM_QUEUE *nextPtr = (SHM_QUEUE *) MAKE_PTR((queue)->next);
184137
SHMEM_OFFSET elemOffset = MAKE_OFFSET(elem);
185138

186139
Assert(SHM_PTR_VALID(queue));
187140
Assert(SHM_PTR_VALID(elem));
188141

189-
#ifdef SHMQUEUE_DEBUG_TL
190-
dumpQ(queue, "in SHMQueueInsertTL: begin");
191-
#endif /* SHMQUEUE_DEBUG_TL */
142+
#ifdef SHMQUEUE_DEBUG
143+
dumpQ(queue, "in SHMQueueInsertAfter: begin");
144+
#endif
192145

193146
(elem)->prev = nextPtr->prev;
194147
(elem)->next = queue->next;
195148
(queue)->next = elemOffset;
196149
nextPtr->prev = elemOffset;
197150

198-
#ifdef SHMQUEUE_DEBUG_TL
199-
dumpQ(queue, "in SHMQueueInsertTL: end");
200-
#endif /* SHMQUEUE_DEBUG_TL */
151+
#ifdef SHMQUEUE_DEBUG
152+
dumpQ(queue, "in SHMQueueInsertAfter: end");
153+
#endif
201154
}
155+
#endif /* NOT_USED */
202156

203-
/*
204-
* SHMQueueFirst -- Get the first element from a queue
157+
/*--------------------
158+
* SHMQueueNext -- Get the next 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
* int stuff;
211168
* SHMQueue elem;
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
}
256206
return 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 */

0 commit comments

Comments
 (0)