Changeset View
Standalone View
sys/kern/kern_malloc.c
Show First 20 Lines • Show All 758 Lines • ▼ Show 20 Lines | #ifdef MALLOC_DEBUG | ||||
if (malloc_dbg(&va, &size, mtp, flags) != 0) | if (malloc_dbg(&va, &size, mtp, flags) != 0) | ||||
return (va); | return (va); | ||||
#endif | #endif | ||||
return (malloc_large(&size, mtp, ds, flags DEBUG_REDZONE_ARG)); | return (malloc_large(&size, mtp, ds, flags DEBUG_REDZONE_ARG)); | ||||
} | } | ||||
void * | void * | ||||
malloc_domainset_aligned(size_t size, size_t align, struct malloc_type *mtp, | |||||
struct domainset *ds, int flags) | |||||
{ | |||||
char *mem, *res; | |||||
size_t addend; | |||||
uintptr_t x; | |||||
MPASS(align > 0 && (align & (align - 1)) == 0); | |||||
if (align < sizeof(void *)) | |||||
align = sizeof(void *); | |||||
jah: I'm probably just missing something here, but why does the padding need to be '3 * align'… | |||||
addend = sizeof(void *) + align; | |||||
#ifdef INVARIANTS | |||||
addend += sizeof(size_t); | |||||
#endif | |||||
Done Inline ActionsThis could be roundup2(). markj: This could be roundup2(). | |||||
mem = malloc_domainset(size + addend, mtp, ds, flags); | |||||
if (mem == NULL) | |||||
return (NULL); | |||||
Not Done Inline ActionsNit: could a simple store be used here instead of memcpy()? Since align must be at least sizeof(void*) , I don't think you'll end up with unaligned access (for the architectures that care about that sort of thing). jah: Nit: could a simple store be used here instead of memcpy()? Since align must be at least… | |||||
Done Inline ActionsI remember from the rtld patch that a compiler does not know about alignment of the pointer. kib: I remember from the rtld patch that a compiler does not know about alignment of the pointer. | |||||
Not Done Inline Actions
To clarify, are you saying that a compiler might choose to emit the store as something like a series of 1-byte stores (or maybe even a call to memcpy() since compilers these days can do that), because the pointer arithmetic here will make it believe that it can't guarantee natural alignment of the access? jah: > I remember from the rtld patch that a compiler does not know about alignment of the pointer. | |||||
Done Inline ActionsNo, I mean that compiler might issue a warning that the alignment of the casted pointer cannot be known. kib: No, I mean that compiler might issue a warning that the alignment of the casted pointer cannot… | |||||
x = roundup((uintptr_t)mem + sizeof(void *), align); | |||||
Done Inline Actionsfor the INVARIANTS case, should this be '(uintptr_t)mem + sizeof(void*) + sizeof(size_t)' ? jah: for the INVARIANTS case, should this be '(uintptr_t)mem + sizeof(void*) + sizeof(size_t)' ? | |||||
res = (void *)x; | |||||
x -= sizeof(void *); | |||||
memcpy((void *)x, &mem, sizeof(mem)); | |||||
#ifdef INVARIANTS | |||||
x -= sizeof(size_t); | |||||
memcpy((void *)x, &align, sizeof(size_t)); | |||||
#endif | |||||
return (res); | |||||
} | |||||
void | |||||
free_aligned(void *addr, struct malloc_type *mtp) | |||||
{ | |||||
Not Done Inline ActionsIs there any meaningful assertion that could be made here that 'mem' is within a certain range below 'addr', to catch corruption? jah: Is there any meaningful assertion that could be made here that 'mem' is within a certain range… | |||||
void *mem; | |||||
uintptr_t x; | |||||
if (addr == NULL) | |||||
return; | |||||
x = (uintptr_t)addr; | |||||
x -= sizeof(void *); | |||||
memcpy(&mem, (void *)x, sizeof(mem)); | |||||
#ifdef INVARIANTS | |||||
{ | |||||
size_t align; | |||||
x -= sizeof(size_t); | |||||
memcpy(&align, (void *)x, sizeof(size_t)); | |||||
if (align == 0 || (align & (align - 1)) != 0) | |||||
panic("free_aligned: bad align " | |||||
"addr %p alloc %p align %#zx", addr, mem, align); | |||||
if ((uintptr_t)addr - (uintptr_t)mem > sizeof(void *) + | |||||
sizeof(size_t) + align) | |||||
panic("free_aligned: addresses too far " | |||||
"addr %p alloc %p align %#zx", addr, mem, align); | |||||
} | |||||
#endif | |||||
free(mem, mtp); | |||||
} | |||||
void * | |||||
mallocarray(size_t nmemb, size_t size, struct malloc_type *type, int flags) | mallocarray(size_t nmemb, size_t size, struct malloc_type *type, int flags) | ||||
{ | { | ||||
if (WOULD_OVERFLOW(nmemb, size)) | if (WOULD_OVERFLOW(nmemb, size)) | ||||
panic("mallocarray: %zu * %zu overflowed", nmemb, size); | panic("mallocarray: %zu * %zu overflowed", nmemb, size); | ||||
return (malloc(size * nmemb, type, flags)); | return (malloc(size * nmemb, type, flags)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 703 Lines • Show Last 20 Lines |
I'm probably just missing something here, but why does the padding need to be '3 * align' instead of 'sizeof(void*) + align'?