Hi,
On 2022-11-02 00:28:46 +1300, David Rowley wrote:
> Part of the work that Thomas mentions in [1], regarding Direct I/O,
> diff --git a/src/backend/utils/mmgr/alignedalloc.c
> b/src/backend/utils/mmgr/alignedalloc.c
> new file mode 100644
> index 0000000000..e581772758
> --- /dev/null
> +++ b/src/backend/utils/mmgr/alignedalloc.c
> @@ -0,0 +1,93 @@
> +/*-------------------------------------------------------------------------
> + *
> + * alignedalloc.c
> + * Allocator functions to implement palloc_aligned
FWIW, to me this is really more part of mcxt.c than its own
allocator... Particularly because MemoryContextAllocAligned() et al are
implemented there.
> +void *
> +AlignedAllocRealloc(void *pointer, Size size)
I doubtthere's ever a need to realloc such a pointer? Perhaps we could just
elog(ERROR)?
> +/*
> + * MemoryContextAllocAligned
> + * Allocate 'size' bytes of memory in 'context' aligned to
> 'alignto'
> + * bytes.
> + *
> + * 'flags' may be 0 or set the same as MemoryContextAllocExtended().
> + * 'alignto' must be a power of 2.
> + */
> +void *
> +MemoryContextAllocAligned(MemoryContext context,
> + Size size, Size alignto, int
> flags)
> +{
> + Size alloc_size;
> + void *unaligned;
> + void *aligned;
> +
> + /* wouldn't make much sense to waste that much space */
> + Assert(alignto < (128 * 1024 * 1024));
> +
> + /* ensure alignto is a power of 2 */
> + Assert((alignto & (alignto - 1)) == 0);
Hm, not that I can see a case for ever not using a power of two
alignment... There's not really a "need" for the restriction, right? Perhaps
we should note that?
> + /*
> + * We implement aligned pointers by simply allocating enough memory for
> + * the requested size plus the alignment and an additional MemoryChunk.
> + * This additional MemoryChunk is required for operations such as pfree
> + * when used on the pointer returned by this function. We use this
> + * "redirection" MemoryChunk in order to find the pointer to the memory
> + * that was returned by the MemoryContextAllocExtended call below. We do
> + * that by "borrowing" the block offset field and instead of using that
> to
> + * find the offset into the owning block, we use it to find the original
> + * allocated address.
> + *
> + * Here we must allocate enough extra memory so that we can still align
> + * the pointer returned by MemoryContextAllocExtended and also have
> enough
> + * space for the redirection MemoryChunk.
> + */
> + alloc_size = size + alignto + sizeof(MemoryChunk);
> +
> + /* perform the actual allocation */
> + unaligned = MemoryContextAllocExtended(context, alloc_size, flags);
Should we handle the case where we get a suitably aligned pointer from
MemoryContextAllocExtended() differently?
> + /* XXX: should we adjust valgrind state here? */
Probably still need to do this... Kinda hard to get right without the code
getting exercised. Wonder if there's some minimal case we could actually use
it for?
Thanks,
Andres