From ccdb219a0e8c6d2e7fdaa5a6ec4968ebfc15357d Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas 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