aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2017-08-16 21:52:38 +0300
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2017-08-16 21:52:38 +0300
commitac883ac453e9c479f397780918f235c440b7a02f (patch)
treeaaaccbaee521dd6e67d055c1654d26f3fdea9c07 /src
parent4395f7daf3b40ecbd316bd2a68c253a56013a538 (diff)
downloadpostgresql-ac883ac453e9c479f397780918f235c440b7a02f.tar.gz
postgresql-ac883ac453e9c479f397780918f235c440b7a02f.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/ipc/shm_toc.c24
-rw-r--r--src/include/c.h1
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