From 89deca0a3361f59635abad8fbd2f8af3ab6aab2d Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Mon, 16 Nov 2020 17:56:58 +0000 Subject: [PATCH] malloc: make malloc_large closer to standalone This moves entire large alloc handling out of all consumers, apart from deciding to go there. This is a step towards creating a fast path. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D27198 --- sys/kern/kern_malloc.c | 132 +++++++++++++++++++---------------------- 1 file changed, 62 insertions(+), 70 deletions(-) diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index 739ebe65850e..f79352f2fbfd 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -110,6 +110,14 @@ dtrace_malloc_probe_func_t __read_mostly dtrace_malloc_probe; #define MALLOC_DEBUG 1 #endif +#ifdef DEBUG_REDZONE +#define DEBUG_REDZONE_ARG_DEF , unsigned long osize +#define DEBUG_REDZONE_ARG , osize +#else +#define DEBUG_REDZONE_ARG_DEF +#define DEBUG_REDZONE_ARG +#endif + /* * When realloc() is called, if the new size is sufficiently smaller than * the old size, realloc() will allocate a new, smaller block to avoid @@ -574,21 +582,33 @@ malloc_large_size(uma_slab_t slab) return (va >> 1); } -static caddr_t -malloc_large(size_t *size, struct domainset *policy, int flags) +static caddr_t __noinline +malloc_large(size_t *size, struct malloc_type *mtp, struct domainset *policy, + int flags DEBUG_REDZONE_ARG_DEF) { - vm_offset_t va; + vm_offset_t kva; + caddr_t va; size_t sz; sz = roundup(*size, PAGE_SIZE); - va = kmem_malloc_domainset(policy, sz, flags); - if (va != 0) { + kva = kmem_malloc_domainset(policy, sz, flags); + if (kva != 0) { /* The low bit is unused for slab pointers. */ - vsetzoneslab(va, NULL, (void *)((sz << 1) | 1)); + vsetzoneslab(kva, NULL, (void *)((sz << 1) | 1)); uma_total_inc(sz); *size = sz; } - return ((caddr_t)va); + va = (caddr_t)kva; + malloc_type_allocated(mtp, va == NULL ? 0 : sz); + if (__predict_false(va == NULL)) { + KASSERT((flags & M_WAITOK) == 0, + ("malloc(M_WAITOK) returned NULL")); + } +#ifdef DEBUG_REDZONE + if (va != NULL) + va = redzone_setup(va, osize); +#endif + return (va); } static void @@ -613,30 +633,30 @@ void * int indx; caddr_t va; uma_zone_t zone; -#if defined(DEBUG_REDZONE) +#ifdef DEBUG_REDZONE unsigned long osize = size; #endif MPASS((flags & M_EXEC) == 0); + #ifdef MALLOC_DEBUG va = NULL; if (malloc_dbg(&va, &size, mtp, flags) != 0) return (va); #endif - if (size <= kmem_zmax) { - if (size & KMEM_ZMASK) - size = (size & ~KMEM_ZMASK) + KMEM_ZBASE; - indx = kmemsize[size >> KMEM_ZSHIFT]; - zone = kmemzones[indx].kz_zone[mtp_get_subzone(mtp)]; - va = uma_zalloc(zone, flags); - if (va != NULL) - size = zone->uz_size; - malloc_type_zone_allocated(mtp, va == NULL ? 0 : size, indx); - } else { - va = malloc_large(&size, DOMAINSET_RR(), flags); - malloc_type_allocated(mtp, va == NULL ? 0 : size); - } + if (__predict_false(size > kmem_zmax)) + return (malloc_large(&size, mtp, DOMAINSET_RR(), flags + DEBUG_REDZONE_ARG)); + + if (size & KMEM_ZMASK) + size = (size & ~KMEM_ZMASK) + KMEM_ZBASE; + indx = kmemsize[size >> KMEM_ZSHIFT]; + zone = kmemzones[indx].kz_zone[mtp_get_subzone(mtp)]; + va = uma_zalloc(zone, flags); + if (va != NULL) + size = zone->uz_size; + malloc_type_zone_allocated(mtp, va == NULL ? 0 : size, indx); if (__predict_false(va == NULL)) { KASSERT((flags & M_WAITOK) == 0, ("malloc(M_WAITOK) returned NULL")); @@ -679,28 +699,27 @@ malloc_domainset(size_t size, struct malloc_type *mtp, struct domainset *ds, caddr_t va; int domain; int indx; - -#if defined(DEBUG_REDZONE) +#ifdef DEBUG_REDZONE unsigned long osize = size; #endif + MPASS((flags & M_EXEC) == 0); + #ifdef MALLOC_DEBUG va = NULL; if (malloc_dbg(&va, &size, mtp, flags) != 0) return (va); #endif - if (size <= kmem_zmax) { - vm_domainset_iter_policy_init(&di, ds, &domain, &flags); - do { - va = malloc_domain(&size, &indx, mtp, domain, flags); - } while (va == NULL && - vm_domainset_iter_policy(&di, &domain) == 0); - malloc_type_zone_allocated(mtp, va == NULL ? 0 : size, indx); - } else { - /* Policy is handled by kmem. */ - va = malloc_large(&size, ds, flags); - malloc_type_allocated(mtp, va == NULL ? 0 : size); - } + + if (__predict_false(size > kmem_zmax)) + return (malloc_large(&size, mtp, DOMAINSET_RR(), flags + DEBUG_REDZONE_ARG)); + + vm_domainset_iter_policy_init(&di, ds, &domain, &flags); + do { + va = malloc_domain(&size, &indx, mtp, domain, flags); + } while (va == NULL && vm_domainset_iter_policy(&di, &domain) == 0); + malloc_type_zone_allocated(mtp, va == NULL ? 0 : size, indx); if (__predict_false(va == NULL)) { KASSERT((flags & M_WAITOK) == 0, ("malloc(M_WAITOK) returned NULL")); @@ -718,57 +737,30 @@ malloc_domainset(size_t size, struct malloc_type *mtp, struct domainset *ds, void * malloc_exec(size_t size, struct malloc_type *mtp, int flags) { - caddr_t va; -#if defined(DEBUG_REDZONE) - unsigned long osize = size; -#endif - flags |= M_EXEC; -#ifdef MALLOC_DEBUG - va = NULL; - if (malloc_dbg(&va, &size, mtp, flags) != 0) - return (va); -#endif - va = malloc_large(&size, DOMAINSET_RR(), flags); - malloc_type_allocated(mtp, va == NULL ? 0 : size); - if (__predict_false(va == NULL)) { - KASSERT((flags & M_WAITOK) == 0, - ("malloc(M_WAITOK) returned NULL")); - } -#ifdef DEBUG_REDZONE - if (va != NULL) - va = redzone_setup(va, osize); -#endif - return ((void *) va); + return (malloc_domainset_exec(size, mtp, DOMAINSET_RR(), flags)); } void * malloc_domainset_exec(size_t size, struct malloc_type *mtp, struct domainset *ds, int flags) { - caddr_t va; -#if defined(DEBUG_REDZONE) +#ifdef DEBUG_REDZONE unsigned long osize = size; #endif +#ifdef MALLOC_DEBUG + caddr_t va; +#endif flags |= M_EXEC; + #ifdef MALLOC_DEBUG va = NULL; if (malloc_dbg(&va, &size, mtp, flags) != 0) return (va); #endif - /* Policy is handled by kmem. */ - va = malloc_large(&size, ds, flags); - malloc_type_allocated(mtp, va == NULL ? 0 : size); - if (__predict_false(va == NULL)) { - KASSERT((flags & M_WAITOK) == 0, - ("malloc(M_WAITOK) returned NULL")); - } -#ifdef DEBUG_REDZONE - if (va != NULL) - va = redzone_setup(va, osize); -#endif - return (va); + + return (malloc_large(&size, mtp, ds, flags DEBUG_REDZONE_ARG)); } void *