From 49da32783fece28aec798a9475e2d7097c340c0b Mon Sep 17 00:00:00 2001
From: Alexandre Felipe <o.alexandre.felipe@gmail.com>
Date: Wed, 9 Sep 2026 10:19:22 +0100
Subject: [PATCH 2/2] rooms applied to BufferMapping

This commit updates the BufMappingPartitionLock
to compute both the partition (selecting a LWLock*)
and room, that gives additional granularity for LW_EXCLUSIVE
locks.

The line
LW_LOCK_ROOM_ALPHA(hashcode >> LOG2_NUM_BUFFER_PARTITIONS)
doing a `- % + <<` another approach would be `& * >>` sequence.
e.g. (hashcode & (0x1f << (32 - 5))) * 26 >> (32 - 5)
or with a single 64-bit multiplications as 
(hashcode * 26ll) >> 32
But we might be about to sleep, that is a bigger concern.

---
 src/backend/storage/buffer/bufmgr.c | 23 +++++++----------------
 src/include/storage/buf_internals.h | 23 ++++++++---------------
 2 files changed, 15 insertions(+), 31 deletions(-)

diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 17f142e4c5b..b6a0a9130c4 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -712,10 +712,9 @@ PrefetchSharedBuffer(SMgrRelation smgr_reln,
 
 	/* determine its hash code and partition lock ID */
 	newHash = BufTableHashCode(&newTag);
-	newPartitionLock = BufMappingPartitionLock(newHash);
+	newPartitionLock = BufMappingPartitionLock(newHash, LW_SHARED);
 
 	/* see if the block is in the buffer pool already */
-	LWLockAcquire(newPartitionLock, LW_SHARED);
 	buf_id = BufTableLookup(&newTag, newHash);
 	LWLockRelease(newPartitionLock);
 
@@ -2217,10 +2216,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 
 	/* determine its hash code and partition lock ID */
 	newHash = BufTableHashCode(&newTag);
-	newPartitionLock = BufMappingPartitionLock(newHash);
+	newPartitionLock = BufMappingPartitionLock(newHash, LW_SHARED);
 
 	/* see if the block is in the buffer pool already */
-	LWLockAcquire(newPartitionLock, LW_SHARED);
 	existing_buf_id = BufTableLookup(&newTag, newHash);
 	if (existing_buf_id >= 0)
 	{
@@ -2273,7 +2271,7 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 	 * somebody else inserted another buffer for the tag, we'll release the
 	 * victim buffer we acquired and use the already inserted one.
 	 */
-	LWLockAcquire(newPartitionLock, LW_EXCLUSIVE);
+	newPartitionLock = BufMappingPartitionLock(newHash, LW_EXCLUSIVE);
 	existing_buf_id = BufTableInsert(&newTag, newHash, victim_buf_hdr->buf_id);
 	if (existing_buf_id >= 0)
 	{
@@ -2386,15 +2384,13 @@ InvalidateBuffer(BufferDesc *buf)
 	 * here?  Probably not.
 	 */
 	oldHash = BufTableHashCode(&oldTag);
-	oldPartitionLock = BufMappingPartitionLock(oldHash);
-
 retry:
 
 	/*
 	 * Acquire exclusive mapping lock in preparation for changing the buffer's
 	 * association.
 	 */
-	LWLockAcquire(oldPartitionLock, LW_EXCLUSIVE);
+	oldPartitionLock = BufMappingPartitionLock(oldHash, LW_EXCLUSIVE);
 
 	/* Re-lock the buffer header */
 	buf_state = LockBufHdr(buf);
@@ -2481,9 +2477,7 @@ InvalidateVictimBuffer(BufferDesc *buf_hdr)
 	tag = buf_hdr->tag;
 
 	hash = BufTableHashCode(&tag);
-	partition_lock = BufMappingPartitionLock(hash);
-
-	LWLockAcquire(partition_lock, LW_EXCLUSIVE);
+	partition_lock = BufMappingPartitionLock(hash, LW_EXCLUSIVE);
 
 	/* lock the buffer header */
 	buf_state = LockBufHdr(buf_hdr);
@@ -2925,9 +2919,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
 		InitBufferTag(&tag, &BMR_GET_SMGR(bmr)->smgr_rlocator.locator, fork,
 					  first_block + i);
 		hash = BufTableHashCode(&tag);
-		partition_lock = BufMappingPartitionLock(hash);
-
-		LWLockAcquire(partition_lock, LW_EXCLUSIVE);
+		partition_lock = BufMappingPartitionLock(hash, LW_EXCLUSIVE);
 
 		existing_id = BufTableInsert(&tag, hash, victim_buf_hdr->buf_id);
 
@@ -5094,10 +5086,9 @@ FindAndDropRelationBuffers(RelFileLocator rlocator, ForkNumber forkNum,
 
 		/* determine its hash code and partition lock ID */
 		bufHash = BufTableHashCode(&bufTag);
-		bufPartitionLock = BufMappingPartitionLock(bufHash);
+		bufPartitionLock = BufMappingPartitionLock(bufHash, LW_SHARED);
 
 		/* Check that it is in the buffer pool. If not, do nothing. */
-		LWLockAcquire(bufPartitionLock, LW_SHARED);
 		buf_id = BufTableLookup(&bufTag, bufHash);
 		LWLockRelease(bufPartitionLock);
 
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index e4ff5619b79..e8b0cc72f48 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -242,25 +242,18 @@ BufTagMatchesRelFileLocator(const BufferTag *tag,
  * The shared buffer mapping table is partitioned to reduce contention.
  * To determine which partition lock a given tag requires, compute the tag's
  * hash code with BufTableHashCode(), then apply BufMappingPartitionLock().
- * NB: NUM_BUFFER_PARTITIONS must be a power of 2!
+ * 
  */
-static inline uint32
-BufTableHashPartition(uint32 hashcode)
-{
-	return hashcode % NUM_BUFFER_PARTITIONS;
-}
-
-static inline LWLock *
-BufMappingPartitionLock(uint32 hashcode)
-{
-	return &MainLWLockArray[BUFFER_MAPPING_LWLOCK_OFFSET +
-							BufTableHashPartition(hashcode)].lock;
-}
 
 static inline LWLock *
-BufMappingPartitionLockByIndex(uint32 index)
+BufMappingPartitionLock(uint32 hashcode, LWLockMode mode)
 {
-	return &MainLWLockArray[BUFFER_MAPPING_LWLOCK_OFFSET + index].lock;
+	int p = BUFFER_MAPPING_LWLOCK_OFFSET + (hashcode % NUM_BUFFER_PARTITIONS);
+	LWLock *lock = &MainLWLockArray[p].lock;
+	if(mode == LW_EXCLUSIVE)
+		mode += LW_LOCK_ROOM_ALPHA(hashcode >> LOG2_NUM_BUFFER_PARTITIONS);
+	LWLockAcquire(lock, mode);
+	return lock;
 }
 
 /*
-- 
2.53.0

