FIFO lock wait queue, with readers grouped together.
authorBruce Momjian
Thu, 19 Feb 1998 15:04:45 +0000 (15:04 +0000)
committerBruce Momjian
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 
 #include 
@@ -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);