]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
FIFO lock wait queue, with readers grouped together.
authorBruce Momjian <bruce@momjian.us>
Thu, 19 Feb 1998 15:04:45 +0000 (15:04 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 19 Feb 1998 15:04:45 +0000 (15:04 +0000)
src/backend/storage/lmgr/proc.c

index 1ab096ac527b4b07a31fcffd82839f24f8408d43..d3631a143b3bf3c220c4d6bd09e3b39605035d1f 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.30 1998/01/28 02:29:29 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.31 1998/02/19 15:04:45 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,7 +46,7 @@
  *             This is so that we can support more backends. (system-wide semaphore
  *             sets run out pretty fast.)                                -ay 4/95
  *
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.30 1998/01/28 02:29:29 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.31 1998/02/19 15:04:45 momjian Exp $
  */
 #include <sys/time.h>
 #include <unistd.h>
@@ -451,19 +451,42 @@ ProcSleep(PROC_QUEUE *waitQueue,
                  int prio,
                  LOCK *lock)
 {
-       int                     i;
+       int                     i = 0;
        PROC       *proc;
        struct itimerval timeval,
                                dummy;
 
+       /*
+        *      If the first entries in the waitQueue have a greater priority than
+        *      we have, we must be a reader, and they must be a writers, and we
+        *      must be here because the current holder is a writer or a
+        *      reader but we don't share shared locks if a writer is waiting.
+        *      We put ourselves after the writers.  This way, we have a FIFO, but
+        *      keep the readers together to give them decent priority, and no one
+        *      starves.  Because we group all readers together, a non-empty queue
+        *      only has a few possible configurations:
+        *
+        *      [readers]
+        *      [writers]
+        *      [readers][writers]
+        *      [writers][readers]
+        *      [writers][readers][writers]
+        *
+        *      In a full queue, we would have a reader holding a lock, then a
+        *      writer gets the lock, then a bunch of readers, made up of readers
+        *      who could not share the first readlock because a writer was waiting,
+        *      and new readers arriving while the writer had the lock.
+        *
+        */
        proc = (PROC *) MAKE_PTR(waitQueue->links.prev);
-       for (i = 0; i < waitQueue->size; i++)
-       {
-               if (proc->prio >= prio)
-                       proc = (PROC *) MAKE_PTR(proc->links.prev);
-               else
-                       break;
-       }
+
+       /* If we are a reader, and they are writers, skip past them */
+       while (i++ < waitQueue->size && proc->prio > prio)
+               proc = (PROC *) MAKE_PTR(proc->links.prev);
+
+       /* The rest of the queue is FIFO, with readers first, writers last */
+       while (i++ < waitQueue->size && proc->prio <= prio)
+               proc = (PROC *) MAKE_PTR(proc->links.prev);
 
        MyProc->prio = prio;
        MyProc->token = token;
@@ -596,8 +619,7 @@ ProcLockWakeup(PROC_QUEUE *queue, char *ltable, char *lock)
 
                /*
                 * ProcWakeup removes proc from the lock waiting process queue and
-                * returns the next proc in chain.      If a writer just dropped its
-                * lock and there are several waiting readers, wake them all up.
+                * returns the next proc in chain.
                 */
                proc = ProcWakeup(proc, NO_ERROR);