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
This commit is contained in:
parent
4395f7daf3
commit
ac883ac453
|
@ -44,7 +44,12 @@ shm_toc_create(uint64 magic, void *address, Size nbytes)
|
||||||
Assert(nbytes > offsetof(shm_toc, toc_entry));
|
Assert(nbytes > offsetof(shm_toc, toc_entry));
|
||||||
toc->toc_magic = magic;
|
toc->toc_magic = magic;
|
||||||
SpinLockInit(&toc->toc_mutex);
|
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_allocated_bytes = 0;
|
||||||
toc->toc_nentry = 0;
|
toc->toc_nentry = 0;
|
||||||
|
|
||||||
|
@ -88,7 +93,12 @@ shm_toc_allocate(shm_toc *toc, Size nbytes)
|
||||||
Size nentry;
|
Size nentry;
|
||||||
Size toc_bytes;
|
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);
|
nbytes = BUFFERALIGN(nbytes);
|
||||||
|
|
||||||
SpinLockAcquire(&toc->toc_mutex);
|
SpinLockAcquire(&toc->toc_mutex);
|
||||||
|
@ -252,7 +262,11 @@ shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
|
||||||
Size
|
Size
|
||||||
shm_toc_estimate(shm_toc_estimator *e)
|
shm_toc_estimate(shm_toc_estimator *e)
|
||||||
{
|
{
|
||||||
return add_size(offsetof(shm_toc, toc_entry),
|
Size sz;
|
||||||
add_size(mul_size(e->number_of_keys, sizeof(shm_toc_entry)),
|
|
||||||
e->space_for_chunks));
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -598,6 +598,7 @@ typedef NameData *Name;
|
||||||
#define LONGALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_LONG, (LEN))
|
#define LONGALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_LONG, (LEN))
|
||||||
#define DOUBLEALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_DOUBLE, (LEN))
|
#define DOUBLEALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_DOUBLE, (LEN))
|
||||||
#define MAXALIGN_DOWN(LEN) TYPEALIGN_DOWN(MAXIMUM_ALIGNOF, (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
|
* The above macros will not work with types wider than uintptr_t, like with
|
||||||
|
|
Loading…
Reference in New Issue