From 26e809af49a2002fff4a3bc561dfd112fd08b2c6 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Sat, 21 Mar 2026 23:44:15 +0200 Subject: [PATCH v9 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 73297e82265..1cbac7946e1 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -238,7 +238,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 */ @@ -399,6 +399,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; @@ -588,7 +589,7 @@ AttachOrInitShmemIndexEntry(ShmemRequest *request, 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 */ @@ -754,7 +755,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 +774,7 @@ ShmemAllocNoError(Size size) { Size allocated_size; - return ShmemAllocRaw(size, &allocated_size); + return ShmemAllocRaw(size, 0, &allocated_size); } /* @@ -783,8 +784,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 +802,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 +824,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 64c1fb044c6..4939130aab1 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -63,6 +63,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; + /* * 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