From 9fdc8cef18e54f939dca0db203d80f1baecc86ae Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Sat, 21 Mar 2026 23:44:15 +0200 Subject: [PATCH v8 15/16] 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 595f1e582d5..d3808432ff1 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -237,7 +237,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,6 +400,7 @@ ShmemGetRequestedSize(void) size = add_size(size, request->options->size); size = add_size(size, request->options->extra_size); + size = add_size(size, request->options->alignment); } return size; @@ -571,7 +572,7 @@ AttachOrInit(ShmemRequest *request, bool init_allowed, bool attach_allowed) size_t allocated_size; void *structPtr; - 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 */ @@ -730,7 +731,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), @@ -749,7 +750,7 @@ ShmemAllocNoError(Size size) { Size allocated_size; - return ShmemAllocRaw(size, &allocated_size); + return ShmemAllocRaw(size, 0, &allocated_size); } /* @@ -759,8 +760,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; @@ -776,14 +778,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) @@ -797,8 +800,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 f59460ae10f..150c86d5884 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -59,6 +59,12 @@ typedef struct ShmemRequestStructOpts ssize_t size; + /* + * Alignment of the starting address. If not set, defaults to cacheline + * boundary. Must be a power of two. + */ + size_t alignment; + /* * Extra space to reserve in the shared memory segment, but it's not part * of the struct itself. This is used for shared memory hash tables that -- 2.47.3