>From a7a2548c17c3881068053fc9bf040c9cc0c2b533 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 13 Jan 2015 11:58:04 +0100
Subject: [PATCH 09/10] WIP: lwlock.c: use latches

---
 src/backend/storage/lmgr/lwlock.c | 89 ++++++++++++++++++++++++++++++++-------
 1 file changed, 73 insertions(+), 16 deletions(-)

diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 7ca8dc0..c159cce 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -107,6 +107,8 @@ extern slock_t *ShmemLock;
 /* Must be greater than MAX_BACKENDS - which is 2^23-1, so we're fine. */
 #define LW_SHARED_MASK				((uint32)(1 << 23))
 
+#define LW_USE_LATCHES
+
 /*
  * This is indexed by tranche ID and stores metadata for all tranches known
  * to the current backend.
@@ -731,7 +733,11 @@ LWLockWakeup(LWLock *lock)
 		 */
 		pg_write_barrier();
 		waiter->lwWaiting = false;
+#ifdef LW_USE_LATCHES
+		SetLatch(&waiter->procLatch);
+#else
 		PGSemaphoreUnlock(&waiter->sem);
+#endif
 	}
 }
 
@@ -843,7 +849,9 @@ LWLockDequeueSelf(LWLock *lock)
 		MyProc->lwWaiting = false;
 	else
 	{
+#ifndef LW_USE_LATCHES
 		int		extraWaits = 0;
+#endif
 
 		/*
 		 * Somebody else dequeued us and has or will wake us up. Deal with the
@@ -863,17 +871,26 @@ LWLockDequeueSelf(LWLock *lock)
 		 */
 		for (;;)
 		{
+#ifdef LW_USE_LATCHES
+			if (!MyProc->lwWaiting)
+				break;
+			WaitLatch(&MyProc->procLatch, WL_LATCH_SET, 0);
+			ResetLatch(&MyProc->procLatch);
+#else
 			PGSemaphoreLock(&MyProc->sem);
 			if (!MyProc->lwWaiting)
 				break;
 			extraWaits++;
+#endif
 		}
 
+#ifndef LW_USE_LATCHES
 		/*
 		 * Fix the process wait semaphore's count for any absorbed wakeups.
 		 */
 		while (extraWaits-- > 0)
 			PGSemaphoreUnlock(&MyProc->sem);
+#endif
 	}
 
 #ifdef LOCK_DEBUG
@@ -914,9 +931,10 @@ LWLockAcquireWithVar(LWLock *l, uint64 *valptr, uint64 val)
 static inline bool
 LWLockAcquireCommon(LWLock *lock, LWLockMode mode, uint64 *valptr, uint64 val)
 {
-	PGPROC	   *proc = MyProc;
 	bool		result = true;
-	int			extraWaits = 0;
+#ifndef LW_USE_LATCHES
+	int         extraWaits = 0;
+#endif
 #ifdef LWLOCK_STATS
 	lwlock_stats *lwstats;
 
@@ -940,7 +958,7 @@ LWLockAcquireCommon(LWLock *lock, LWLockMode mode, uint64 *valptr, uint64 val)
 	 * during bootstrap or shared memory initialization.  Put an Assert here
 	 * to catch unsafe coding practices.
 	 */
-	Assert(!(proc == NULL && IsUnderPostmaster));
+	Assert(!(MyProc == NULL && IsUnderPostmaster));
 
 	/* Ensure we will have room to remember the lock */
 	if (num_held_lwlocks >= MAX_SIMUL_LWLOCKS)
@@ -1033,10 +1051,19 @@ LWLockAcquireCommon(LWLock *lock, LWLockMode mode, uint64 *valptr, uint64 val)
 
 		for (;;)
 		{
-			PGSemaphoreLock(&proc->sem);
-			if (!proc->lwWaiting)
+#ifdef LW_USE_LATCHES
+			pg_read_barrier();
+			if (!MyProc->lwWaiting)
+				break;
+
+			WaitLatch(&MyProc->procLatch, WL_LATCH_SET, 0);
+			ResetLatch(&MyProc->procLatch);
+#else
+			PGSemaphoreLock(&MyProc->sem);
+			if (!MyProc->lwWaiting)
 				break;
 			extraWaits++;
+#endif
 		}
 
 		/* Retrying, allow LWLockRelease to release waiters again. */
@@ -1068,11 +1095,13 @@ LWLockAcquireCommon(LWLock *lock, LWLockMode mode, uint64 *valptr, uint64 val)
 	held_lwlocks[num_held_lwlocks].lock = lock;
 	held_lwlocks[num_held_lwlocks++].mode = mode;
 
+#ifndef LW_USE_LATCHES
 	/*
 	 * Fix the process wait semaphore's count for any absorbed wakeups.
 	 */
 	while (extraWaits-- > 0)
-		PGSemaphoreUnlock(&proc->sem);
+		PGSemaphoreUnlock(&MyProc->sem);
+#endif
 
 	return result;
 }
@@ -1142,9 +1171,10 @@ LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
 bool
 LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
 {
-	PGPROC	   *proc = MyProc;
 	bool		mustwait;
-	int			extraWaits = 0;
+#ifndef LW_USE_LATCHES
+	int         extraWaits = 0;
+#endif
 #ifdef LWLOCK_STATS
 	lwlock_stats *lwstats;
 
@@ -1193,10 +1223,19 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
 
 			for (;;)
 			{
-				PGSemaphoreLock(&proc->sem);
-				if (!proc->lwWaiting)
+#ifdef LW_USE_LATCHES
+				pg_read_barrier();
+				if (!MyProc->lwWaiting)
+					break;
+
+				WaitLatch(&MyProc->procLatch, WL_LATCH_SET, 0);
+				ResetLatch(&MyProc->procLatch);
+#else
+				PGSemaphoreLock(&MyProc->sem);
+				if (!MyProc->lwWaiting)
 					break;
 				extraWaits++;
+#endif
 			}
 
 #ifdef LOCK_DEBUG
@@ -1224,11 +1263,13 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
 		}
 	}
 
+#ifndef LW_USE_LATCHES
 	/*
 	 * Fix the process wait semaphore's count for any absorbed wakeups.
 	 */
 	while (extraWaits-- > 0)
-		PGSemaphoreUnlock(&proc->sem);
+		PGSemaphoreUnlock(&MyProc->sem);
+#endif
 
 	if (mustwait)
 	{
@@ -1271,9 +1312,10 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
 bool
 LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
 {
-	PGPROC	   *proc = MyProc;
-	int			extraWaits = 0;
 	bool		result = false;
+#ifndef LW_USE_LATCHES
+	int         extraWaits = 0;
+#endif
 #ifdef LWLOCK_STATS
 	lwlock_stats *lwstats;
 
@@ -1394,10 +1436,19 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
 
 		for (;;)
 		{
-			PGSemaphoreLock(&proc->sem);
-			if (!proc->lwWaiting)
+#ifdef LW_USE_LATCHES
+			pg_read_barrier();
+			if (!MyProc->lwWaiting)
+				break;
+
+			WaitLatch(&MyProc->procLatch, WL_LATCH_SET, 0);
+			ResetLatch(&MyProc->procLatch);
+#else
+			PGSemaphoreLock(&MyProc->sem);
+			if (!MyProc->lwWaiting)
 				break;
 			extraWaits++;
+#endif
 		}
 
 #ifdef LOCK_DEBUG
@@ -1418,11 +1469,13 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
 
 	TRACE_POSTGRESQL_LWLOCK_ACQUIRE(T_NAME(lock), T_ID(lock), LW_EXCLUSIVE);
 
+#ifndef LW_USE_LATCHES
 	/*
 	 * Fix the process wait semaphore's count for any absorbed wakeups.
 	 */
 	while (extraWaits-- > 0)
-		PGSemaphoreUnlock(&proc->sem);
+		PGSemaphoreUnlock(&MyProc->sem);
+#endif
 
 	/*
 	 * Now okay to allow cancel/die interrupts.
@@ -1498,7 +1551,11 @@ LWLockUpdateVar(LWLock *lock, uint64 *valptr, uint64 val)
 		/* check comment in LWLockWakeup() about this barrier */
 		pg_write_barrier();
 		waiter->lwWaiting = false;
+#ifdef LW_USE_LATCHES
+		SetLatch(&waiter->procLatch);
+#else
 		PGSemaphoreUnlock(&waiter->sem);
+#endif
 	}
 }
 
-- 
2.0.0.rc2.4.g1dc51c6.dirty

