v7-0017-Add-option-for-aligning-shmem-allocations.patch

text/x-patch

Filename: v7-0017-Add-option-for-aligning-shmem-allocations.patch
Type: text/x-patch
Part: 16
Message: Re: Better shared data structure management and resizable shared data structures

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v7-0017
Subject: Add option for aligning shmem allocations
File+
src/backend/storage/ipc/shmem.c 13 9
src/include/storage/shmem.h 6 0
From ccdb219a0e8c6d2e7fdaa5a6ec4968ebfc15357d Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Sat, 21 Mar 2026 23:44:15 +0200
Subject: [PATCH v7 17/18] Add option for aligning shmem allocations

The buffer blocks (in the next commit) are IO-aligned. This might come
handy in other places too, so make it an explicit feature of
ShmemRequestStruct.
---
 src/backend/storage/ipc/shmem.c | 22 +++++++++++++---------
 src/include/storage/shmem.h     |  6 ++++++
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index d2b72606876..ae43ac8c326 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -225,7 +225,7 @@ typedef struct ShmemAllocatorData
 	slock_t		shmem_lock;
 } ShmemAllocatorData;
 
-static void *ShmemAllocRaw(Size size, Size *allocated_size);
+static void *ShmemAllocRaw(Size size, Size alignment, Size *allocated_size);
 
 /* shared memory global variables */
 
@@ -334,6 +334,7 @@ ShmemGetRequestedSize(void)
 
 		size = add_size(size, desc->size);
 		size = add_size(size, desc->extra_size);
+		size = add_size(size, desc->alignment);
 	}
 
 	return size;
@@ -500,7 +501,7 @@ AttachOrInit(ShmemStructDesc *desc, bool init_allowed, bool attach_allowed)
 		size_t		allocated_size;
 		void	   *structPtr;
 
-		structPtr = ShmemAllocRaw(desc->size, &allocated_size);
+		structPtr = ShmemAllocRaw(desc->size, desc->alignment, &allocated_size);
 		if (structPtr == NULL)
 		{
 			/* out of memory; remove the failed ShmemIndex entry */
@@ -651,7 +652,7 @@ ShmemAlloc(Size size)
 	void	   *newSpace;
 	Size		allocated_size;
 
-	newSpace = ShmemAllocRaw(size, &allocated_size);
+	newSpace = ShmemAllocRaw(size, 0, &allocated_size);
 	if (!newSpace)
 		ereport(ERROR,
 				(errcode(ERRCODE_OUT_OF_MEMORY),
@@ -670,7 +671,7 @@ ShmemAllocNoError(Size size)
 {
 	Size		allocated_size;
 
-	return ShmemAllocRaw(size, &allocated_size);
+	return ShmemAllocRaw(size, 0, &allocated_size);
 }
 
 /*
@@ -680,8 +681,9 @@ ShmemAllocNoError(Size size)
  * be equal to the number requested plus any padding we choose to add.
  */
 static void *
-ShmemAllocRaw(Size size, Size *allocated_size)
+ShmemAllocRaw(Size size, Size alignment, Size *allocated_size)
 {
+	Size		rawStart;
 	Size		newStart;
 	Size		newFree;
 	void	   *newSpace;
@@ -697,14 +699,15 @@ ShmemAllocRaw(Size size, Size *allocated_size)
 	 * structures out to a power-of-two size - but without this, even that
 	 * won't be sufficient.
 	 */
-	size = CACHELINEALIGN(size);
-	*allocated_size = size;
+	if (alignment < PG_CACHE_LINE_SIZE)
+		alignment = PG_CACHE_LINE_SIZE;
 
 	Assert(ShmemSegHdr != NULL);
 
 	SpinLockAcquire(ShmemLock);
 
-	newStart = ShmemAllocator->free_offset;
+	rawStart = ShmemAllocator->free_offset;
+	newStart = TYPEALIGN(alignment, rawStart);
 
 	newFree = newStart + size;
 	if (newFree <= ShmemSegHdr->totalsize)
@@ -718,8 +721,9 @@ ShmemAllocRaw(Size size, Size *allocated_size)
 	SpinLockRelease(ShmemLock);
 
 	/* note this assert is okay with newSpace == NULL */
-	Assert(newSpace == (void *) CACHELINEALIGN(newSpace));
+	Assert(newSpace == (void *) TYPEALIGN(alignment, newSpace));
 
+	*allocated_size = newFree - rawStart;
 	return newSpace;
 }
 
diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h
index cd6f5165139..2f01f413167 100644
--- a/src/include/storage/shmem.h
+++ b/src/include/storage/shmem.h
@@ -48,6 +48,12 @@ typedef struct ShmemStructDesc
 	const char *name;
 	size_t		size;
 
+	/*
+	 * Alignment of the starting address. If not set, defaults to cacheline
+	 * boundary. Must be a power of two.
+	 */
+	size_t		alignment;
+
 	/*
 	 * Direct callers of ShmemRequestStruct() should leave this unset (i.e.
 	 * SHMEM_KIND_STRUCT).  The other values are reserved for higher-level
-- 
2.47.3