From 8c9488e9b467e0f405c59dd04143e19cbc1bd34d Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 2 Dec 2025 18:44:54 -0500
Subject: [PATCH v7 04/15] bufmgr: Optimize LockBufHdr() by delaying spin-delay
 setup

Previously we always initialized the SpinDelayStatus. That is sufficiently
expensive / buffer header lock acquisitions are sufficiently frequent to make
it worthwhile to instead have a fastpath that does not initialize the
SpinDelayStatus.

While this is a small gain on its own, it mainly is aimed at preventing a
regression after a future commit, which requires additional locking to set
hint bits.

Discussion: https://postgr.es/m/fvfmkr5kk4nyex56ejgxj3uzi63isfxovp2biecb4bspbjrze7@az2pljabhnff
---
 src/backend/storage/buffer/bufmgr.c | 32 ++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 62f420dd344..0ffad2cd735 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -6263,23 +6263,35 @@ rlocator_comparator(const void *p1, const void *p2)
 uint32
 LockBufHdr(BufferDesc *desc)
 {
-	SpinDelayStatus delayStatus;
 	uint32		old_buf_state;
 
 	Assert(!BufferIsLocal(BufferDescriptorGetBuffer(desc)));
 
-	init_local_spin_delay(&delayStatus);
+	/*
+	 * Try to acquire the lock once, without setting up the spin-delay
+	 * infrastructure. The work necessary for that shows up in profiles and is
+	 * rarely necessary.
+	 */
+	old_buf_state = pg_atomic_fetch_or_u32(&desc->state, BM_LOCKED);
 
-	while (true)
+	if (unlikely(old_buf_state & BM_LOCKED))
 	{
-		/* set BM_LOCKED flag */
-		old_buf_state = pg_atomic_fetch_or_u32(&desc->state, BM_LOCKED);
-		/* if it wasn't set before we're OK */
-		if (!(old_buf_state & BM_LOCKED))
-			break;
-		perform_spin_delay(&delayStatus);
+		SpinDelayStatus delayStatus;
+
+		init_local_spin_delay(&delayStatus);
+
+		while (true)
+		{
+			/* set BM_LOCKED flag */
+			old_buf_state = pg_atomic_fetch_or_u32(&desc->state, BM_LOCKED);
+			/* if it wasn't set before we're OK */
+			if (!(old_buf_state & BM_LOCKED))
+				break;
+			perform_spin_delay(&delayStatus);
+		}
+		finish_spin_delay(&delayStatus);
 	}
-	finish_spin_delay(&delayStatus);
+
 	return old_buf_state | BM_LOCKED;
 }
 
-- 
2.48.1.76.g4e746b1a31.dirty

