postgres.git / summary / log / commit / refs

commit    ac883ac453e9c479f397780918f235c440b7a02f
Author:   Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date:     Wed Aug 16 18:52:38 2017 +0000

    Fix shm_toc.c to always return buffer-aligned memory.
    
    Previously, if you passed a non-aligned size to shm_toc_create(), the
    memory returned by shm_toc_allocate() would be similarly non-aligned.
    This was exposed by commit 3cda10f41b, which allocated structs containing
    a pg_atomic_uint64 field with shm_toc_allocate(). On systems with
    MAXIMUM_ALIGNOF = 4, such structs still need to be 8-bytes aligned, but
    the memory returned by shm_toc_allocate() was only 4-bytes aligned.
    
    It's quite bogus that we abuse BUFFERALIGN to align the structs for
    pg_atomic_uint64. It doesn't really have anything to do with buffers. But
    that's a separate issue.
    
    This ought to fix the buildfarm failures on 32-bit x86 systems.
    
    Discussion: https://www.postgresql.org/message-id/7e0a73a5-0df9-1859-b8ae-9acf122dc38d@iki.fi


src/backend/storage/ipc/shm_toc.c | 24 +++++++++++++++++++----- src/include/c.h | 1 + 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 9f259441f01..958397884de 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -44,7 +44,12 @@ shm_toc_create(uint64 magic, void *address, Size nbytes) Assert(nbytes > offsetof(shm_toc, toc_entry)); toc->toc_magic = magic; SpinLockInit(&toc->toc_mutex); - toc->toc_total_bytes = nbytes; + + /* + * The alignment code in shm_toc_allocate() assumes that the starting + * value is buffer-aligned. + */ + toc->toc_total_bytes = BUFFERALIGN_DOWN(nbytes); toc->toc_allocated_bytes = 0; toc->toc_nentry = 0; @@ -88,7 +93,12 @@ shm_toc_allocate(shm_toc *toc, Size nbytes) Size nentry; Size toc_bytes; - /* Make sure request is well-aligned. */ + /* + * Make sure request is well-aligned. XXX: MAXALIGN is not enough, + * because atomic ops might need a wider alignment. We don't have a + * proper definition for the minimum to make atomic ops safe, but + * BUFFERALIGN ought to be enough. + */ nbytes = BUFFERALIGN(nbytes); SpinLockAcquire(&toc->toc_mutex); @@ -252,7 +262,11 @@ shm_toc_lookup(shm_toc *toc, uint64 key, bool noError) Size shm_toc_estimate(shm_toc_estimator *e) { - return add_size(offsetof(shm_toc, toc_entry), - add_size(mul_size(e->number_of_keys, sizeof(shm_toc_entry)), - e->space_for_chunks)); + Size sz; + + sz = offsetof(shm_toc, toc_entry); + sz += add_size(sz, mul_size(e->number_of_keys, sizeof(shm_toc_entry))); + sz += add_size(sz, e->space_for_chunks); + + return BUFFERALIGN(sz); } diff --git a/src/include/c.h b/src/include/c.h index 9066e3c5783..af799dc1dfb 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -598,6 +598,7 @@ typedef NameData *Name; #define LONGALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_LONG, (LEN)) #define DOUBLEALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_DOUBLE, (LEN)) #define MAXALIGN_DOWN(LEN) TYPEALIGN_DOWN(MAXIMUM_ALIGNOF, (LEN)) +#define BUFFERALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_BUFFER, (LEN)) /* * The above macros will not work with types wider than uintptr_t, like with [parent: 4395f7daf3b4]