diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 98eead9558a1369adf4fe11b1e8bb5b62c081bee..a3a61a3a36e64ac27f8ff4ed32e8b9f0304b01b8 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lwlock.c,v 1.5 2001/12/28 23:26:04 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lwlock.c,v 1.6 2001/12/29 21:28:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -195,7 +195,8 @@ void
 LWLockAcquire(LWLockId lockid, LWLockMode mode)
 {
 	volatile LWLock *lock = LWLockArray + lockid;
-	bool		mustwait;
+	PROC	   *proc = MyProc;
+	int			extraWaits = 0;
 
 	PRINT_LWDEBUG("LWLockAcquire", lockid, lock);
 
@@ -206,43 +207,57 @@ LWLockAcquire(LWLockId lockid, LWLockMode mode)
 	 */
 	HOLD_INTERRUPTS();
 
-	/* Acquire mutex.  Time spent holding mutex should be short! */
-	SpinLockAcquire_NoHoldoff(&lock->mutex);
-
-	/* If I can get the lock, do so quickly. */
-	if (mode == LW_EXCLUSIVE)
+	/*
+	 * Loop here to try to acquire lock after each time we are signaled
+	 * by LWLockRelease.
+	 *
+	 * NOTE: it might seem better to have LWLockRelease actually grant us
+	 * the lock, rather than retrying and possibly having to go back to
+	 * sleep.  But in practice that is no good because it means a process
+	 * swap for every lock acquisition when two or more processes are
+	 * contending for the same lock.  Since LWLocks are normally used to
+	 * protect not-very-long sections of computation, a process needs to
+	 * be able to acquire and release the same lock many times during a
+	 * single process dispatch cycle, even in the presence of contention.
+	 * The efficiency of being able to do that outweighs the inefficiency of
+	 * sometimes wasting a dispatch cycle because the lock is not free when a
+	 * released waiter gets to run.  See pgsql-hackers archives for 29-Dec-01.
+	 */
+	for (;;)
 	{
-		if (lock->exclusive == 0 && lock->shared == 0)
+		bool		mustwait;
+
+		/* Acquire mutex.  Time spent holding mutex should be short! */
+		SpinLockAcquire_NoHoldoff(&lock->mutex);
+
+		/* If I can get the lock, do so quickly. */
+		if (mode == LW_EXCLUSIVE)
 		{
-			lock->exclusive++;
-			mustwait = false;
+			if (lock->exclusive == 0 && lock->shared == 0)
+			{
+				lock->exclusive++;
+				mustwait = false;
+			}
+			else
+				mustwait = true;
 		}
 		else
-			mustwait = true;
-	}
-	else
-	{
-		/*
-		 * If there is someone waiting (presumably for exclusive access),
-		 * queue up behind him even though I could get the lock.  This
-		 * prevents a stream of read locks from starving a writer.
-		 */
-		if (lock->exclusive == 0 && lock->head == NULL)
 		{
-			lock->shared++;
-			mustwait = false;
+			if (lock->exclusive == 0)
+			{
+				lock->shared++;
+				mustwait = false;
+			}
+			else
+				mustwait = true;
 		}
-		else
-			mustwait = true;
-	}
 
-	if (mustwait)
-	{
-		/* Add myself to wait queue */
-		PROC	   *proc = MyProc;
-		int			extraWaits = 0;
+		if (!mustwait)
+			break;				/* got the lock */
 
 		/*
+		 * Add myself to wait queue.
+		 *
 		 * If we don't have a PROC structure, there's no way to wait. This
 		 * should never occur, since MyProc should only be null during
 		 * shared memory initialization.
@@ -267,9 +282,9 @@ LWLockAcquire(LWLockId lockid, LWLockMode mode)
 		 *
 		 * Since we share the process wait semaphore with the regular lock
 		 * manager and ProcWaitForSignal, and we may need to acquire an
-		 * LWLock while one of those is pending, it is possible that we
-		 * get awakened for a reason other than being granted the LWLock.
-		 * If so, loop back and wait again.  Once we've gotten the lock,
+		 * LWLock while one of those is pending, it is possible that we get
+		 * awakened for a reason other than being signaled by LWLockRelease.
+		 * If so, loop back and wait again.  Once we've gotten the LWLock,
 		 * re-increment the sema by the number of additional signals
 		 * received, so that the lock manager or signal manager will see
 		 * the received signal when it next waits.
@@ -287,23 +302,21 @@ LWLockAcquire(LWLockId lockid, LWLockMode mode)
 
 		LOG_LWDEBUG("LWLockAcquire", lockid, "awakened");
 
-		/*
-		 * The awakener already updated the lock struct's state, so we
-		 * don't need to do anything more to it.  Just need to fix the
-		 * semaphore count.
-		 */
-		while (extraWaits-- > 0)
-			IpcSemaphoreUnlock(proc->sem.semId, proc->sem.semNum);
-	}
-	else
-	{
-		/* Got the lock without waiting */
-		SpinLockRelease_NoHoldoff(&lock->mutex);
+		/* Now loop back and try to acquire lock again. */
 	}
 
+	/* We are done updating shared state of the lock itself. */
+	SpinLockRelease_NoHoldoff(&lock->mutex);
+
 	/* Add lock to list of locks held by this backend */
 	Assert(num_held_lwlocks < MAX_SIMUL_LWLOCKS);
 	held_lwlocks[num_held_lwlocks++] = lockid;
+
+	/*
+	 * Fix the process wait semaphore's count for any absorbed wakeups.
+	 */
+	while (extraWaits-- > 0)
+		IpcSemaphoreUnlock(proc->sem.semId, proc->sem.semNum);
 }
 
 /*
@@ -344,12 +357,7 @@ LWLockConditionalAcquire(LWLockId lockid, LWLockMode mode)
 	}
 	else
 	{
-		/*
-		 * If there is someone waiting (presumably for exclusive access),
-		 * queue up behind him even though I could get the lock.  This
-		 * prevents a stream of read locks from starving a writer.
-		 */
-		if (lock->exclusive == 0 && lock->head == NULL)
+		if (lock->exclusive == 0)
 		{
 			lock->shared++;
 			mustwait = false;
@@ -427,20 +435,17 @@ LWLockRelease(LWLockId lockid)
 		if (lock->exclusive == 0 && lock->shared == 0)
 		{
 			/*
-			 * Remove the to-be-awakened PROCs from the queue, and update
-			 * the lock state to show them as holding the lock.
+			 * Remove the to-be-awakened PROCs from the queue.  If the
+			 * front waiter wants exclusive lock, awaken him only.
+			 * Otherwise awaken as many waiters as want shared access.
 			 */
 			proc = head;
-			if (proc->lwExclusive)
-				lock->exclusive++;
-			else
+			if (!proc->lwExclusive)
 			{
-				lock->shared++;
 				while (proc->lwWaitLink != NULL &&
 					   !proc->lwWaitLink->lwExclusive)
 				{
 					proc = proc->lwWaitLink;
-					lock->shared++;
 				}
 			}
 			/* proc is now the last PROC to be released */
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index fa6bb88289a71aee497765ec39f0d668f4d9ac24..674eaeb91a17fa1f35204826005764146e6f66a0 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.84 2001/12/29 18:40:58 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.85 2001/12/29 21:28:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -959,7 +959,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
 					if (tzp == NULL)
 						return -1;
 
-					if ((isdigit(*field[i]) || (ptype != 0))
+					if (isdigit(*field[i]) || ptype != 0)
 					{
 						char *cp;