]> granicus.if.org Git - postgresql/blob - src/backend/storage/lmgr/proc.c
Oops, only wanted python change in the last commit. Backing out.
[postgresql] / src / backend / storage / lmgr / proc.c
1 /*-------------------------------------------------------------------------
2  *
3  * proc.c
4  *        routines to manage per-process shared memory data structure
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.102 2001/05/25 15:45:33 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 /*
16  *      Each postgres backend gets one of these.  We'll use it to
17  *      clean up after the process should the process suddenly die.
18  *
19  *
20  * Interface (a):
21  *              ProcSleep(), ProcWakeup(),
22  *              ProcQueueAlloc() -- create a shm queue for sleeping processes
23  *              ProcQueueInit() -- create a queue without allocing memory
24  *
25  * Locking and waiting for buffers can cause the backend to be
26  * put to sleep.  Whoever releases the lock, etc. wakes the
27  * process up again (and gives it an error code so it knows
28  * whether it was awoken on an error condition).
29  *
30  * Interface (b):
31  *
32  * ProcReleaseLocks -- frees the locks associated with current transaction
33  *
34  * ProcKill -- destroys the shared memory state (and locks)
35  *              associated with the process.
36  *
37  * 5/15/91 -- removed the buffer pool based lock chain in favor
38  *              of a shared memory lock chain.  The write-protection is
39  *              more expensive if the lock chain is in the buffer pool.
40  *              The only reason I kept the lock chain in the buffer pool
41  *              in the first place was to allow the lock table to grow larger
42  *              than available shared memory and that isn't going to work
43  *              without a lot of unimplemented support anyway.
44  *
45  * 4/7/95 -- instead of allocating a set of 1 semaphore per process, we
46  *              allocate a semaphore from a set of PROC_NSEMS_PER_SET semaphores
47  *              shared among backends (we keep a few sets of semaphores around).
48  *              This is so that we can support more backends. (system-wide semaphore
49  *              sets run out pretty fast.)                                -ay 4/95
50  */
51 #include "postgres.h"
52
53 #include <errno.h>
54 #include <sys/time.h>
55 #include <unistd.h>
56 #include <signal.h>
57 #include <sys/types.h>
58
59 #if defined(solaris_sparc) || defined(__CYGWIN__)
60 #include <sys/ipc.h>
61 #include <sys/sem.h>
62 #endif
63
64 #include "miscadmin.h"
65
66 #if defined(__darwin__)
67 #include "port/darwin/sem.h"
68 #endif
69
70 /* In Ultrix and QNX, sem.h must be included after ipc.h */
71 #ifdef HAVE_SYS_SEM_H
72 #include <sys/sem.h>
73 #endif
74
75 #include "access/xact.h"
76 #include "storage/proc.h"
77
78
79 int                     DeadlockTimeout = 1000;
80
81 /* --------------------
82  * Spin lock for manipulating the shared process data structure:
83  * ProcGlobal.... Adding an extra spin lock seemed like the smallest
84  * hack to get around reading and updating this structure in shared
85  * memory. -mer 17 July 1991
86  * --------------------
87  */
88 SPINLOCK        ProcStructLock;
89
90 static PROC_HDR *ProcGlobal = NULL;
91
92 PROC       *MyProc = NULL;
93
94 static bool waitingForLock = false;
95
96 static void ProcKill(void);
97 static void ProcGetNewSemIdAndNum(IpcSemaphoreId *semId, int *semNum);
98 static void ProcFreeSem(IpcSemaphoreId semId, int semNum);
99 static void ZeroProcSemaphore(PROC *proc);
100 static void ProcFreeAllSemaphores(void);
101
102
103 /*
104  * InitProcGlobal -
105  *        initializes the global process table. We put it here so that
106  *        the postmaster can do this initialization. (ProcFreeAllSemaphores needs
107  *        to read this table on exiting the postmaster. If we have the first
108  *        backend do this, starting up and killing the postmaster without
109  *        starting any backends will be a problem.)
110  *
111  *        We also allocate all the per-process semaphores we will need to support
112  *        the requested number of backends.  We used to allocate semaphores
113  *        only when backends were actually started up, but that is bad because
114  *        it lets Postgres fail under load --- a lot of Unix systems are
115  *        (mis)configured with small limits on the number of semaphores, and
116  *        running out when trying to start another backend is a common failure.
117  *        So, now we grab enough semaphores to support the desired max number
118  *        of backends immediately at initialization --- if the sysadmin has set
119  *        MaxBackends higher than his kernel will support, he'll find out sooner
120  *        rather than later.
121  */
122 void
123 InitProcGlobal(int maxBackends)
124 {
125         bool            found = false;
126
127         /* attach to the free list */
128         ProcGlobal = (PROC_HDR *)
129                 ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
130
131         /* --------------------
132          * We're the first - initialize.
133          * XXX if found should ever be true, it is a sign of impending doom ...
134          * ought to complain if so?
135          * --------------------
136          */
137         if (!found)
138         {
139                 int                     i;
140
141                 ProcGlobal->freeProcs = INVALID_OFFSET;
142                 for (i = 0; i < PROC_SEM_MAP_ENTRIES; i++)
143                 {
144                         ProcGlobal->procSemIds[i] = -1;
145                         ProcGlobal->freeSemMap[i] = 0;
146                 }
147
148                 /*
149                  * Arrange to delete semas on exit --- set this up now so that we
150                  * will clean up if pre-allocation fails.  We use our own
151                  * freeproc, rather than IpcSemaphoreCreate's removeOnExit option,
152                  * because we don't want to fill up the on_shmem_exit list with a
153                  * separate entry for each semaphore set.
154                  */
155                 on_shmem_exit(ProcFreeAllSemaphores, 0);
156
157                 /*
158                  * Pre-create the semaphores for the first maxBackends processes.
159                  */
160                 Assert(maxBackends > 0 && maxBackends <= MAXBACKENDS);
161
162                 for (i = 0; i < ((maxBackends - 1) / PROC_NSEMS_PER_SET + 1); i++)
163                 {
164                         IpcSemaphoreId semId;
165
166                         semId = IpcSemaphoreCreate(PROC_NSEMS_PER_SET,
167                                                                            IPCProtection,
168                                                                            1,
169                                                                            false);
170                         ProcGlobal->procSemIds[i] = semId;
171                 }
172         }
173 }
174
175 /* ------------------------
176  * InitProc -- create a per-process data structure for this process
177  * used by the lock manager on semaphore queues.
178  * ------------------------
179  */
180 void
181 InitProcess(void)
182 {
183         bool            found = false;
184         unsigned long location,
185                                 myOffset;
186
187         SpinAcquire(ProcStructLock);
188
189         /* attach to the ProcGlobal structure */
190         ProcGlobal = (PROC_HDR *)
191                 ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
192         if (!found)
193         {
194                 /* this should not happen. InitProcGlobal() is called before this. */
195                 elog(STOP, "InitProcess: Proc Header uninitialized");
196         }
197
198         if (MyProc != NULL)
199         {
200                 SpinRelease(ProcStructLock);
201                 elog(ERROR, "ProcInit: you already exist");
202         }
203
204         /* try to get a proc struct from the free list first */
205
206         myOffset = ProcGlobal->freeProcs;
207
208         if (myOffset != INVALID_OFFSET)
209         {
210                 MyProc = (PROC *) MAKE_PTR(myOffset);
211                 ProcGlobal->freeProcs = MyProc->links.next;
212         }
213         else
214         {
215
216                 /*
217                  * have to allocate one.  We can't use the normal shmem index
218                  * table mechanism because the proc structure is stored by PID
219                  * instead of by a global name (need to look it up by PID when we
220                  * cleanup dead processes).
221                  */
222
223                 MyProc = (PROC *) ShmemAlloc(sizeof(PROC));
224                 if (!MyProc)
225                 {
226                         SpinRelease(ProcStructLock);
227                         elog(FATAL, "cannot create new proc: out of memory");
228                 }
229         }
230
231         /*
232          * zero out the spin lock counts and set the sLocks field for
233          * ProcStructLock to 1 as we have acquired this spinlock above but
234          * didn't record it since we didn't have MyProc until now.
235          */
236         MemSet(MyProc->sLocks, 0, sizeof(MyProc->sLocks));
237         MyProc->sLocks[ProcStructLock] = 1;
238
239         /*
240          * Set up a wait-semaphore for the proc.
241          */
242         if (IsUnderPostmaster)
243         {
244                 ProcGetNewSemIdAndNum(&MyProc->sem.semId, &MyProc->sem.semNum);
245
246                 /*
247                  * we might be reusing a semaphore that belongs to a dead backend.
248                  * So be careful and reinitialize its value here.
249                  */
250                 ZeroProcSemaphore(MyProc);
251         }
252         else
253         {
254                 MyProc->sem.semId = -1;
255                 MyProc->sem.semNum = -1;
256         }
257
258         SHMQueueElemInit(&(MyProc->links));
259         MyProc->errType = STATUS_OK;
260         MyProc->pid = MyProcPid;
261         MyProc->databaseId = MyDatabaseId;
262         MyProc->xid = InvalidTransactionId;
263         MyProc->xmin = InvalidTransactionId;
264         MyProc->waitLock = NULL;
265         MyProc->waitHolder = NULL;
266         SHMQueueInit(&(MyProc->procHolders));
267
268         /*
269          * Release the lock.
270          */
271         SpinRelease(ProcStructLock);
272
273         /*
274          * Install ourselves in the shmem index table.  The name to use is
275          * determined by the OS-assigned process id.  That allows the cleanup
276          * process to find us after any untimely exit.
277          */
278         location = MAKE_OFFSET(MyProc);
279         if ((!ShmemPIDLookup(MyProcPid, &location)) ||
280                 (location != MAKE_OFFSET(MyProc)))
281                 elog(STOP, "InitProcess: ShmemPID table broken");
282
283         /*
284          * Arrange to clean up at backend exit.
285          */
286         on_shmem_exit(ProcKill, 0);
287
288         /*
289          * Now that we have a PROC, we could try to acquire locks, so
290          * initialize the deadlock checker.
291          */
292         InitDeadLockChecking();
293 }
294
295 /*
296  * Initialize the proc's wait-semaphore to count zero.
297  */
298 static void
299 ZeroProcSemaphore(PROC *proc)
300 {
301         union semun semun;
302
303         semun.val = 0;
304         if (semctl(proc->sem.semId, proc->sem.semNum, SETVAL, semun) < 0)
305         {
306                 fprintf(stderr, "ZeroProcSemaphore: semctl(id=%d,SETVAL) failed: %s\n",
307                                 proc->sem.semId, strerror(errno));
308                 proc_exit(255);
309         }
310 }
311
312 /*
313  * Cancel any pending wait for lock, when aborting a transaction.
314  *
315  * Returns true if we had been waiting for a lock, else false.
316  *
317  * (Normally, this would only happen if we accept a cancel/die
318  * interrupt while waiting; but an elog(ERROR) while waiting is
319  * within the realm of possibility, too.)
320  */
321 bool
322 LockWaitCancel(void)
323 {
324         /* Nothing to do if we weren't waiting for a lock */
325         if (!waitingForLock)
326                 return false;
327
328         waitingForLock = false;
329
330         /* Turn off the deadlock timer, if it's still running (see ProcSleep) */
331 #ifndef __BEOS__
332         {
333                 struct itimerval timeval,
334                                         dummy;
335
336                 MemSet(&timeval, 0, sizeof(struct itimerval));
337                 setitimer(ITIMER_REAL, &timeval, &dummy);
338         }
339 #else
340         /* BeOS doesn't have setitimer, but has set_alarm */
341         set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM);
342 #endif   /* __BEOS__ */
343
344         /* Unlink myself from the wait queue, if on it (might not be anymore!) */
345         LockLockTable();
346         if (MyProc->links.next != INVALID_OFFSET)
347                 RemoveFromWaitQueue(MyProc);
348         UnlockLockTable();
349
350         /*
351          * Reset the proc wait semaphore to zero.  This is necessary in the
352          * scenario where someone else granted us the lock we wanted before we
353          * were able to remove ourselves from the wait-list.  The semaphore
354          * will have been bumped to 1 by the would-be grantor, and since we
355          * are no longer going to wait on the sema, we have to force it back
356          * to zero. Otherwise, our next attempt to wait for a lock will fall
357          * through prematurely.
358          */
359         ZeroProcSemaphore(MyProc);
360
361         /*
362          * Return true even if we were kicked off the lock before we were able
363          * to remove ourselves.
364          */
365         return true;
366 }
367
368
369 /*
370  * ProcReleaseLocks() -- release locks associated with current transaction
371  *                      at transaction commit or abort
372  *
373  * At commit, we release only locks tagged with the current transaction's XID,
374  * leaving those marked with XID 0 (ie, session locks) undisturbed.  At abort,
375  * we release all locks including XID 0, because we need to clean up after
376  * a failure.  This logic will need extension if we ever support nested
377  * transactions.
378  *
379  * Note that user locks are not released in either case.
380  */
381 void
382 ProcReleaseLocks(bool isCommit)
383 {
384         if (!MyProc)
385                 return;
386         /* If waiting, get off wait queue (should only be needed after error) */
387         LockWaitCancel();
388         /* Release locks */
389         LockReleaseAll(DEFAULT_LOCKMETHOD, MyProc,
390                                    !isCommit, GetCurrentTransactionId());
391 }
392
393 /*
394  * ProcRemove -
395  *        called by the postmaster to clean up the global tables after a
396  *        backend exits.  This also frees up the proc's wait semaphore.
397  */
398 bool
399 ProcRemove(int pid)
400 {
401         SHMEM_OFFSET location;
402         PROC       *proc;
403
404         location = ShmemPIDDestroy(pid);
405         if (location == INVALID_OFFSET)
406                 return FALSE;
407         proc = (PROC *) MAKE_PTR(location);
408
409         SpinAcquire(ProcStructLock);
410
411         ProcFreeSem(proc->sem.semId, proc->sem.semNum);
412
413         /* Add PROC struct to freelist so space can be recycled in future */
414         proc->links.next = ProcGlobal->freeProcs;
415         ProcGlobal->freeProcs = MAKE_OFFSET(proc);
416
417         SpinRelease(ProcStructLock);
418
419         return TRUE;
420 }
421
422 /*
423  * ProcKill() -- Destroy the per-proc data structure for
424  *              this process. Release any of its held spin locks.
425  *
426  * This is done inside the backend process before it exits.
427  * ProcRemove, above, will be done by the postmaster afterwards.
428  */
429 static void
430 ProcKill(void)
431 {
432         Assert(MyProc);
433
434         /* Release any spinlocks I am holding */
435         ProcReleaseSpins(MyProc);
436
437         /* Get off any wait queue I might be on */
438         LockWaitCancel();
439
440         /* Remove from the standard lock table */
441         LockReleaseAll(DEFAULT_LOCKMETHOD, MyProc, true, InvalidTransactionId);
442
443 #ifdef USER_LOCKS
444         /* Remove from the user lock table */
445         LockReleaseAll(USER_LOCKMETHOD, MyProc, true, InvalidTransactionId);
446 #endif
447
448         MyProc = NULL;
449 }
450
451 /*
452  * ProcQueue package: routines for putting processes to sleep
453  *              and  waking them up
454  */
455
456 /*
457  * ProcQueueAlloc -- alloc/attach to a shared memory process queue
458  *
459  * Returns: a pointer to the queue or NULL
460  * Side Effects: Initializes the queue if we allocated one
461  */
462 #ifdef NOT_USED
463 PROC_QUEUE *
464 ProcQueueAlloc(char *name)
465 {
466         bool            found;
467         PROC_QUEUE *queue = (PROC_QUEUE *)
468         ShmemInitStruct(name, sizeof(PROC_QUEUE), &found);
469
470         if (!queue)
471                 return NULL;
472         if (!found)
473                 ProcQueueInit(queue);
474         return queue;
475 }
476
477 #endif
478
479 /*
480  * ProcQueueInit -- initialize a shared memory process queue
481  */
482 void
483 ProcQueueInit(PROC_QUEUE *queue)
484 {
485         SHMQueueInit(&(queue->links));
486         queue->size = 0;
487 }
488
489
490 /*
491  * ProcSleep -- put a process to sleep
492  *
493  * Caller must have set MyProc->heldLocks to reflect locks already held
494  * on the lockable object by this process (under all XIDs).
495  *
496  * Locktable's spinlock must be held at entry, and will be held
497  * at exit.
498  *
499  * Result: STATUS_OK if we acquired the lock, STATUS_ERROR if not (deadlock).
500  *
501  * ASSUME: that no one will fiddle with the queue until after
502  *              we release the spin lock.
503  *
504  * NOTES: The process queue is now a priority queue for locking.
505  *
506  * P() on the semaphore should put us to sleep.  The process
507  * semaphore is normally zero, so when we try to acquire it, we sleep.
508  */
509 int
510 ProcSleep(LOCKMETHODTABLE *lockMethodTable,
511                   LOCKMODE lockmode,
512                   LOCK *lock,
513                   HOLDER *holder)
514 {
515         LOCKMETHODCTL *lockctl = lockMethodTable->ctl;
516         SPINLOCK        spinlock = lockctl->masterLock;
517         PROC_QUEUE *waitQueue = &(lock->waitProcs);
518         int                     myHeldLocks = MyProc->heldLocks;
519         PROC       *proc;
520         int                     i;
521
522 #ifndef __BEOS__
523         struct itimerval timeval,
524                                 dummy;
525
526 #else
527         bigtime_t       time_interval;
528
529 #endif
530
531         /*
532          * Determine where to add myself in the wait queue.
533          *
534          * Normally I should go at the end of the queue.  However, if I already
535          * hold locks that conflict with the request of any previous waiter,
536          * put myself in the queue just in front of the first such waiter.
537          * This is not a necessary step, since deadlock detection would move
538          * me to before that waiter anyway; but it's relatively cheap to
539          * detect such a conflict immediately, and avoid delaying till
540          * deadlock timeout.
541          *
542          * Special case: if I find I should go in front of some waiter, check to
543          * see if I conflict with already-held locks or the requests before
544          * that waiter.  If not, then just grant myself the requested lock
545          * immediately.  This is the same as the test for immediate grant in
546          * LockAcquire, except we are only considering the part of the wait
547          * queue before my insertion point.
548          *
549          */
550         if (myHeldLocks != 0)
551         {
552                 int                     aheadRequests = 0;
553
554                 proc = (PROC *) MAKE_PTR(waitQueue->links.next);
555                 for (i = 0; i < waitQueue->size; i++)
556                 {
557                         /* Must he wait for me? */
558                         if (lockctl->conflictTab[proc->waitLockMode] & myHeldLocks)
559                         {
560                                 /* Must I wait for him ? */
561                                 if (lockctl->conflictTab[lockmode] & proc->heldLocks)
562                                 {
563                                         /* Yes, can report deadlock failure immediately */
564                                         MyProc->errType = STATUS_ERROR;
565                                         return STATUS_ERROR;
566                                 }
567                                 /* I must go before this waiter.  Check special case. */
568                                 if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 &&
569                                         LockCheckConflicts(lockMethodTable,
570                                                                            lockmode,
571                                                                            lock,
572                                                                            holder,
573                                                                            MyProc,
574                                                                            NULL) == STATUS_OK)
575                                 {
576                                         /* Skip the wait and just grant myself the lock. */
577                                         GrantLock(lock, holder, lockmode);
578                                         return STATUS_OK;
579                                 }
580                                 /* Break out of loop to put myself before him */
581                                 break;
582                         }
583                         /* Nope, so advance to next waiter */
584                         aheadRequests |= (1 << proc->waitLockMode);
585                         proc = (PROC *) MAKE_PTR(proc->links.next);
586                 }
587
588                 /*
589                  * If we fall out of loop normally, proc points to waitQueue head,
590                  * so we will insert at tail of queue as desired.
591                  */
592         }
593         else
594         {
595                 /* I hold no locks, so I can't push in front of anyone. */
596                 proc = (PROC *) &(waitQueue->links);
597         }
598
599         /*
600          * Insert self into queue, ahead of the given proc (or at tail of
601          * queue).
602          */
603         SHMQueueInsertBefore(&(proc->links), &(MyProc->links));
604         waitQueue->size++;
605
606         lock->waitMask |= (1 << lockmode);
607
608         /* Set up wait information in PROC object, too */
609         MyProc->waitLock = lock;
610         MyProc->waitHolder = holder;
611         MyProc->waitLockMode = lockmode;
612
613         MyProc->errType = STATUS_OK;/* initialize result for success */
614
615         /* mark that we are waiting for a lock */
616         waitingForLock = true;
617
618         /*
619          * Release the locktable's spin lock.
620          *
621          * NOTE: this may also cause us to exit critical-section state, possibly
622          * allowing a cancel/die interrupt to be accepted. This is OK because
623          * we have recorded the fact that we are waiting for a lock, and so
624          * LockWaitCancel will clean up if cancel/die happens.
625          */
626         SpinRelease(spinlock);
627
628         /*
629          * Set timer so we can wake up after awhile and check for a deadlock.
630          * If a deadlock is detected, the handler releases the process's
631          * semaphore and sets MyProc->errType = STATUS_ERROR, allowing us to
632          * know that we must report failure rather than success.
633          *
634          * By delaying the check until we've waited for a bit, we can avoid
635          * running the rather expensive deadlock-check code in most cases.
636          *
637          * Need to zero out struct to set the interval and the microseconds
638          * fields to 0.
639          */
640 #ifndef __BEOS__
641         MemSet(&timeval, 0, sizeof(struct itimerval));
642         timeval.it_value.tv_sec = DeadlockTimeout / 1000;
643         timeval.it_value.tv_usec = (DeadlockTimeout % 1000) * 1000;
644         if (setitimer(ITIMER_REAL, &timeval, &dummy))
645                 elog(FATAL, "ProcSleep: Unable to set timer for process wakeup");
646 #else
647         time_interval = DeadlockTimeout * 1000000;      /* usecs */
648         if (set_alarm(time_interval, B_ONE_SHOT_RELATIVE_ALARM) < 0)
649                 elog(FATAL, "ProcSleep: Unable to set timer for process wakeup");
650 #endif
651
652         /*
653          * If someone wakes us between SpinRelease and IpcSemaphoreLock,
654          * IpcSemaphoreLock will not block.  The wakeup is "saved" by the
655          * semaphore implementation.  Note also that if HandleDeadLock is
656          * invoked but does not detect a deadlock, IpcSemaphoreLock() will
657          * continue to wait.  There used to be a loop here, but it was useless
658          * code...
659          *
660          * We pass interruptOK = true, which eliminates a window in which
661          * cancel/die interrupts would be held off undesirably.  This is a
662          * promise that we don't mind losing control to a cancel/die interrupt
663          * here.  We don't, because we have no state-change work to do after
664          * being granted the lock (the grantor did it all).
665          */
666         IpcSemaphoreLock(MyProc->sem.semId, MyProc->sem.semNum, true);
667
668         /*
669          * Disable the timer, if it's still running
670          */
671 #ifndef __BEOS__
672         MemSet(&timeval, 0, sizeof(struct itimerval));
673         if (setitimer(ITIMER_REAL, &timeval, &dummy))
674                 elog(FATAL, "ProcSleep: Unable to disable timer for process wakeup");
675 #else
676         if (set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM) < 0)
677                 elog(FATAL, "ProcSleep: Unable to disable timer for process wakeup");
678 #endif
679
680         /*
681          * Now there is nothing for LockWaitCancel to do.
682          */
683         waitingForLock = false;
684
685         /*
686          * Re-acquire the locktable's spin lock.
687          *
688          * We could accept a cancel/die interrupt here.  That's OK because the
689          * lock is now registered as being held by this process.
690          */
691         SpinAcquire(spinlock);
692
693         /*
694          * We don't have to do anything else, because the awaker did all the
695          * necessary update of the lock table and MyProc.
696          */
697         return MyProc->errType;
698 }
699
700
701 /*
702  * ProcWakeup -- wake up a process by releasing its private semaphore.
703  *
704  *       Also remove the process from the wait queue and set its links invalid.
705  *       RETURN: the next process in the wait queue.
706  */
707 PROC *
708 ProcWakeup(PROC *proc, int errType)
709 {
710         PROC       *retProc;
711
712         /* assume that spinlock has been acquired */
713
714         /* Proc should be sleeping ... */
715         if (proc->links.prev == INVALID_OFFSET ||
716                 proc->links.next == INVALID_OFFSET)
717                 return (PROC *) NULL;
718
719         /* Save next process before we zap the list link */
720         retProc = (PROC *) MAKE_PTR(proc->links.next);
721
722         /* Remove process from wait queue */
723         SHMQueueDelete(&(proc->links));
724         (proc->waitLock->waitProcs.size)--;
725
726         /* Clean up process' state and pass it the ok/fail signal */
727         proc->waitLock = NULL;
728         proc->waitHolder = NULL;
729         proc->errType = errType;
730
731         /* And awaken it */
732         IpcSemaphoreUnlock(proc->sem.semId, proc->sem.semNum);
733
734         return retProc;
735 }
736
737 /*
738  * ProcLockWakeup -- routine for waking up processes when a lock is
739  *              released (or a prior waiter is aborted).  Scan all waiters
740  *              for lock, waken any that are no longer blocked.
741  */
742 void
743 ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock)
744 {
745         LOCKMETHODCTL *lockctl = lockMethodTable->ctl;
746         PROC_QUEUE *waitQueue = &(lock->waitProcs);
747         int                     queue_size = waitQueue->size;
748         PROC       *proc;
749         int                     aheadRequests = 0;
750
751         Assert(queue_size >= 0);
752
753         if (queue_size == 0)
754                 return;
755
756         proc = (PROC *) MAKE_PTR(waitQueue->links.next);
757
758         while (queue_size-- > 0)
759         {
760                 LOCKMODE        lockmode = proc->waitLockMode;
761
762                 /*
763                  * Waken if (a) doesn't conflict with requests of earlier waiters,
764                  * and (b) doesn't conflict with already-held locks.
765                  */
766                 if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 &&
767                         LockCheckConflicts(lockMethodTable,
768                                                            lockmode,
769                                                            lock,
770                                                            proc->waitHolder,
771                                                            proc,
772                                                            NULL) == STATUS_OK)
773                 {
774                         /* OK to waken */
775                         GrantLock(lock, proc->waitHolder, lockmode);
776                         proc = ProcWakeup(proc, STATUS_OK);
777
778                         /*
779                          * ProcWakeup removes proc from the lock's waiting process
780                          * queue and returns the next proc in chain; don't use proc's
781                          * next-link, because it's been cleared.
782                          */
783                 }
784                 else
785                 {
786
787                         /*
788                          * Cannot wake this guy. Remember his request for later
789                          * checks.
790                          */
791                         aheadRequests |= (1 << lockmode);
792                         proc = (PROC *) MAKE_PTR(proc->links.next);
793                 }
794         }
795
796         Assert(waitQueue->size >= 0);
797 }
798
799 /* --------------------
800  * We only get to this routine if we got SIGALRM after DeadlockTimeout
801  * while waiting for a lock to be released by some other process.  Look
802  * to see if there's a deadlock; if not, just return and continue waiting.
803  * If we have a real deadlock, remove ourselves from the lock's wait queue
804  * and signal an error to ProcSleep.
805  * --------------------
806  */
807 void
808 HandleDeadLock(SIGNAL_ARGS)
809 {
810         int                     save_errno = errno;
811
812         /*
813          * Acquire locktable lock.      Note that the SIGALRM interrupt had better
814          * not be enabled anywhere that this process itself holds the
815          * locktable lock, else this will wait forever.  Also note that this
816          * calls SpinAcquire which creates a critical section, so that this
817          * routine cannot be interrupted by cancel/die interrupts.
818          */
819         LockLockTable();
820
821         /*
822          * Check to see if we've been awoken by anyone in the interim.
823          *
824          * If we have we can return and resume our transaction -- happy day.
825          * Before we are awoken the process releasing the lock grants it to us
826          * so we know that we don't have to wait anymore.
827          *
828          * We check by looking to see if we've been unlinked from the wait queue.
829          * This is quicker than checking our semaphore's state, since no
830          * kernel call is needed, and it is safe because we hold the locktable
831          * lock.
832          *
833          */
834         if (MyProc->links.prev == INVALID_OFFSET ||
835                 MyProc->links.next == INVALID_OFFSET)
836         {
837                 UnlockLockTable();
838                 errno = save_errno;
839                 return;
840         }
841
842 #ifdef LOCK_DEBUG
843         if (Debug_deadlocks)
844                 DumpAllLocks();
845 #endif
846
847         if (!DeadLockCheck(MyProc))
848         {
849                 /* No deadlock, so keep waiting */
850                 UnlockLockTable();
851                 errno = save_errno;
852                 return;
853         }
854
855         /*
856          * Oops.  We have a deadlock.
857          *
858          * Get this process out of wait state.
859          */
860         RemoveFromWaitQueue(MyProc);
861
862         /*
863          * Set MyProc->errType to STATUS_ERROR so that ProcSleep will report
864          * an error after we return from this signal handler.
865          */
866         MyProc->errType = STATUS_ERROR;
867
868         /*
869          * Unlock my semaphore so that the interrupted ProcSleep() call can
870          * finish.
871          */
872         IpcSemaphoreUnlock(MyProc->sem.semId, MyProc->sem.semNum);
873
874         /*
875          * We're done here.  Transaction abort caused by the error that
876          * ProcSleep will raise will cause any other locks we hold to be
877          * released, thus allowing other processes to wake up; we don't need
878          * to do that here. NOTE: an exception is that releasing locks we hold
879          * doesn't consider the possibility of waiters that were blocked
880          * behind us on the lock we just failed to get, and might now be
881          * wakable because we're not in front of them anymore.  However,
882          * RemoveFromWaitQueue took care of waking up any such processes.
883          */
884         UnlockLockTable();
885         errno = save_errno;
886 }
887
888 void
889 ProcReleaseSpins(PROC *proc)
890 {
891         int                     i;
892
893         if (!proc)
894                 proc = MyProc;
895
896         if (!proc)
897                 return;
898         for (i = 0; i < (int) MAX_SPINS; i++)
899         {
900                 if (proc->sLocks[i])
901                 {
902                         Assert(proc->sLocks[i] == 1);
903                         SpinRelease(i);
904                 }
905         }
906         AbortBufferIO();
907 }
908
909 /*****************************************************************************
910  *
911  *****************************************************************************/
912
913 /*
914  * ProcGetNewSemIdAndNum -
915  *        scan the free semaphore bitmap and allocate a single semaphore from
916  *        a semaphore set.
917  */
918 static void
919 ProcGetNewSemIdAndNum(IpcSemaphoreId *semId, int *semNum)
920 {
921         int                     i;
922         IpcSemaphoreId *procSemIds = ProcGlobal->procSemIds;
923         int32      *freeSemMap = ProcGlobal->freeSemMap;
924         int32           fullmask = (1 << PROC_NSEMS_PER_SET) - 1;
925
926         /*
927          * we hold ProcStructLock when entering this routine. We scan through
928          * the bitmap to look for a free semaphore.
929          */
930
931         for (i = 0; i < PROC_SEM_MAP_ENTRIES; i++)
932         {
933                 int                     mask = 1;
934                 int                     j;
935
936                 if (freeSemMap[i] == fullmask)
937                         continue;                       /* this set is fully allocated */
938                 if (procSemIds[i] < 0)
939                         continue;                       /* this set hasn't been initialized */
940
941                 for (j = 0; j < PROC_NSEMS_PER_SET; j++)
942                 {
943                         if ((freeSemMap[i] & mask) == 0)
944                         {
945
946                                 /*
947                                  * a free semaphore found. Mark it as allocated.
948                                  */
949                                 freeSemMap[i] |= mask;
950
951                                 *semId = procSemIds[i];
952                                 *semNum = j;
953                                 return;
954                         }
955                         mask <<= 1;
956                 }
957         }
958
959         /* if we reach here, all the semaphores are in use. */
960         elog(ERROR, "ProcGetNewSemIdAndNum: cannot allocate a free semaphore");
961 }
962
963 /*
964  * ProcFreeSem -
965  *        free up our semaphore in the semaphore set.
966  */
967 static void
968 ProcFreeSem(IpcSemaphoreId semId, int semNum)
969 {
970         int32           mask;
971         int                     i;
972
973         mask = ~(1 << semNum);
974
975         for (i = 0; i < PROC_SEM_MAP_ENTRIES; i++)
976         {
977                 if (ProcGlobal->procSemIds[i] == semId)
978                 {
979                         ProcGlobal->freeSemMap[i] &= mask;
980                         return;
981                 }
982         }
983         fprintf(stderr, "ProcFreeSem: no ProcGlobal entry for semId %d\n", semId);
984 }
985
986 /*
987  * ProcFreeAllSemaphores -
988  *        called at shmem_exit time, ie when exiting the postmaster or
989  *        destroying shared state for a failed set of backends.
990  *        Free up all the semaphores allocated to the lmgrs of the backends.
991  */
992 static void
993 ProcFreeAllSemaphores(void)
994 {
995         int                     i;
996
997         for (i = 0; i < PROC_SEM_MAP_ENTRIES; i++)
998         {
999                 if (ProcGlobal->procSemIds[i] >= 0)
1000                         IpcSemaphoreKill(ProcGlobal->procSemIds[i]);
1001         }
1002 }