From 0ef99d0958c12bffa69f5529cce82faf7215d2f3 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Sat, 21 Mar 2026 23:44:15 +0200 Subject: [PATCH v11 12/14] 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 | 26 ++++++++++++++++---------- src/include/storage/shmem.h | 6 ++++++ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index bc186d6ea17..973811e545e 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -239,7 +239,7 @@ typedef struct ShmemAllocatorData #define ShmemIndexLock (&ShmemAllocator->index_lock) -static void *ShmemAllocRaw(Size size, Size *allocated_size); +static void *ShmemAllocRaw(Size size, Size alignment, Size *allocated_size); /* shared memory global variables */ @@ -400,7 +400,8 @@ ShmemGetRequestedSize(void) { size = add_size(size, request->options->size); /* calculate alignment padding like ShmemAllocRaw() does */ - size = CACHELINEALIGN(size); + size = TYPEALIGN(Max(request->options->alignment, PG_CACHE_LINE_SIZE), + size); } return size; @@ -525,7 +526,9 @@ InitShmemIndexEntry(ShmemRequest *request) * We inserted the entry to the shared memory index. Allocate requested * amount of shared memory for it, and initialize the index entry. */ - structPtr = ShmemAllocRaw(request->options->size, &allocated_size); + structPtr = ShmemAllocRaw(request->options->size, + request->options->alignment, + &allocated_size); if (structPtr == NULL) { /* out of memory; remove the failed ShmemIndex entry */ @@ -754,7 +757,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), @@ -773,7 +776,7 @@ ShmemAllocNoError(Size size) { Size allocated_size; - return ShmemAllocRaw(size, &allocated_size); + return ShmemAllocRaw(size, 0, &allocated_size); } /* @@ -783,8 +786,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; @@ -800,14 +804,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(&ShmemAllocator->shmem_lock); - newStart = ShmemAllocator->free_offset; + rawStart = ShmemAllocator->free_offset; + newStart = TYPEALIGN(alignment, rawStart); newFree = newStart + size; if (newFree <= ShmemSegHdr->totalsize) @@ -821,8 +826,9 @@ ShmemAllocRaw(Size size, Size *allocated_size) SpinLockRelease(&ShmemAllocator->shmem_lock); /* 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 147a6915f7e..91218db6d6e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -51,6 +51,12 @@ typedef struct ShmemStructOpts */ ssize_t size; + /* + * Alignment of the starting address. If not set, defaults to cacheline + * boundary. Must be a power of two. + */ + size_t alignment; + /* * When the shmem area is initialized or attached to, pointer to it is * stored in *ptr. It usually points to a global variable, used to access -- 2.47.3