malloc_aligned: roundup allocation size up to next power of two

to make it use the right aligned zone.

Reported by:	melifaro
Reviewed by:	alc, markj (previous version)
Discussed with:	jrtc27
Tested by:	pho (previous version)
MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D28219
This commit is contained in:
Konstantin Belousov 2021-01-18 23:17:21 +02:00
parent 0781c79d48
commit 1ac7c34486

View File

@ -768,6 +768,7 @@ malloc_domainset_aligned(size_t size, size_t align,
struct malloc_type *mtp, struct domainset *ds, int flags)
{
void *res;
size_t asize;
KASSERT(align != 0 && powerof2(align),
("malloc_domainset_aligned: wrong align %#zx size %#zx",
@ -776,12 +777,20 @@ malloc_domainset_aligned(size_t size, size_t align,
("malloc_domainset_aligned: align %#zx (size %#zx) too large",
align, size));
if (size < align)
size = align;
res = malloc_domainset(size, mtp, ds, flags);
/*
* Round the allocation size up to the next power of 2,
* because we can only guarantee alignment for
* power-of-2-sized allocations. Further increase the
* allocation size to align if the rounded size is less than
* align, since malloc zones provide alignment equal to their
* size.
*/
asize = size <= align ? align : 1UL << flsl(size - 1);
res = malloc_domainset(asize, mtp, ds, flags);
KASSERT(res == NULL || ((uintptr_t)res & (align - 1)) == 0,
("malloc_domainset_aligned: result not aligned %p size %#zx "
"align %#zx", res, size, align));
"allocsize %#zx align %#zx", res, size, asize, align));
return (res);
}