Index: share/man/man9/malloc.9 =================================================================== --- share/man/man9/malloc.9 +++ share/man/man9/malloc.9 @@ -29,7 +29,7 @@ .\" $NetBSD: malloc.9,v 1.3 1996/11/11 00:05:11 lukem Exp $ .\" $FreeBSD$ .\" -.Dd June 13, 2018 +.Dd September 28, 2018 .Dt MALLOC 9 .Os .Sh NAME @@ -71,11 +71,15 @@ .Pp The .Fn malloc_domain -variant allocates the object from the specified memory domain. Memory allocated -with this function should be returned with +variant permit allocations from a specific +.Xr numa 9 +domain. +.Fn malloc_domain +will attempt to allocate memory from the specified domain, and will fall +back to other domains if the specified domain does not contain sufficient +free memory. +Memory allocated with this function should be freed with .Fn free_domain . -See -.Xr numa 9 for more details. .Pp The .Fn mallocarray @@ -312,5 +316,7 @@ .Sh SEE ALSO .Xr vmstat 8 , .Xr contigmalloc 9 , +.Xr domainset 9 , .Xr memguard 9 , +.Xr numa 9 , .Xr vnode 9 Index: sys/kern/kern_malloc.c =================================================================== --- sys/kern/kern_malloc.c +++ sys/kern/kern_malloc.c @@ -68,6 +68,7 @@ #include #include +#include #include #include #include @@ -457,9 +458,25 @@ int domain, int flags, vm_paddr_t low, vm_paddr_t high, unsigned long alignment, vm_paddr_t boundary) { + + return (contigmalloc_domainset(size, type, DOMAINSET_PREF(domain), + flags, low, high, alignment, boundary)); +} + +/* + * contigmalloc_domainset: + * + * Allocate a block of physically contiguous memory, using the specified + * policy to select a domain. + */ +void * +contigmalloc_domainset(unsigned long size, struct malloc_type *type, + struct domainset *ds, int flags, vm_paddr_t low, vm_paddr_t high, + unsigned long alignment, vm_paddr_t boundary) +{ void *ret; - ret = (void *)kmem_alloc_contig_domain(domain, size, flags, low, high, + ret = (void *)kmem_alloc_contig_domainset(ds, size, flags, low, high, alignment, boundary, VM_MEMATTR_DEFAULT); if (ret != NULL) malloc_type_allocated(type, round_page(size)); @@ -595,9 +612,8 @@ return ((void *) va); } -void * -malloc_domain(size_t size, struct malloc_type *mtp, int domain, - int flags) +static void * +_malloc_domain(size_t size, struct malloc_type *mtp, int domain, int flags) { int indx; caddr_t va; @@ -640,6 +656,31 @@ return ((void *) va); } +void * +malloc_domain(size_t size, struct malloc_type *mtp, int domain, int flags) +{ + + return (malloc_domainset(size, mtp, DOMAINSET_PREF(domain), flags)); +} + +void * +malloc_domainset(size_t size, struct malloc_type *mtp, struct domainset *ds, + int flags) +{ + struct vm_domainset_iter di; + void *ret; + int domain; + + vm_domainset_iter_policy_init(&di, ds, &domain, &flags); + do { + ret = _malloc_domain(size, mtp, domain, flags); + if (ret != NULL) + break; + } while (vm_domainset_iter_policy(&di, &domain) == 0); + + return (ret); +} + void * mallocarray(size_t nmemb, size_t size, struct malloc_type *type, int flags) { Index: sys/sys/malloc.h =================================================================== --- sys/sys/malloc.h +++ sys/sys/malloc.h @@ -160,6 +160,7 @@ */ MALLOC_DECLARE(M_IOV); +struct domainset; extern struct mtx malloc_mtx; /* @@ -176,10 +177,15 @@ int domain, int flags, vm_paddr_t low, vm_paddr_t high, unsigned long alignment, vm_paddr_t boundary) __malloc_like __result_use_check __alloc_size(1) __alloc_align(6); +void *contigmalloc_domainset(unsigned long size, struct malloc_type *type, + struct domainset *ds, int flags, vm_paddr_t low, vm_paddr_t high, + unsigned long alignment, vm_paddr_t boundary) + __malloc_like __result_use_check __alloc_size(1) __alloc_align(6); void free(void *addr, struct malloc_type *type); void free_domain(void *addr, struct malloc_type *type); void *malloc(size_t size, struct malloc_type *type, int flags) __malloc_like __result_use_check __alloc_size(1); + /* * Try to optimize malloc(..., ..., M_ZERO) allocations by doing zeroing in * place if the size is known at compilation time. @@ -232,6 +238,9 @@ void *malloc_domain(size_t size, struct malloc_type *type, int domain, int flags) __malloc_like __result_use_check __alloc_size(1); +void *malloc_domainset(size_t size, struct malloc_type *type, + struct domainset *ds, int flags) __malloc_like __result_use_check + __alloc_size(1); void *mallocarray(size_t nmemb, size_t size, struct malloc_type *type, int flags) __malloc_like __result_use_check __alloc_size2(1, 2); Index: sys/vm/vm_extern.h =================================================================== --- sys/vm/vm_extern.h +++ sys/vm/vm_extern.h @@ -44,6 +44,7 @@ #ifdef _KERNEL struct cdev; struct cdevsw; +struct domainset; /* These operate on kernel virtual addresses only. */ vm_offset_t kva_alloc(vm_size_t); @@ -58,14 +59,21 @@ vm_paddr_t low, vm_paddr_t high, vm_memattr_t memattr); vm_offset_t kmem_alloc_attr_domain(int domain, vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, vm_memattr_t memattr); +vm_offset_t kmem_alloc_attr_domainset(struct domainset *ds, vm_size_t size, + int flags, vm_paddr_t low, vm_paddr_t high, vm_memattr_t memattr); vm_offset_t kmem_alloc_contig(vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary, vm_memattr_t memattr); vm_offset_t kmem_alloc_contig_domain(int domain, vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary, vm_memattr_t memattr); +vm_offset_t kmem_alloc_contig_domainset(struct domainset *ds, vm_size_t size, + int flags, vm_paddr_t low, vm_paddr_t high, u_long alignment, + vm_paddr_t boundary, vm_memattr_t memattr); vm_offset_t kmem_malloc(vm_size_t size, int flags); vm_offset_t kmem_malloc_domain(int domain, vm_size_t size, int flags); +vm_offset_t kmem_malloc_domainset(struct domainset *ds, vm_size_t size, + int flags); void kmem_free(vm_offset_t addr, vm_size_t size); /* This provides memory for previously allocated address space. */ Index: sys/vm/vm_kern.c =================================================================== --- sys/vm/vm_kern.c +++ sys/vm/vm_kern.c @@ -175,8 +175,8 @@ * necessarily physically contiguous. If M_ZERO is specified through the * given flags, then the pages are zeroed before they are mapped. */ -vm_offset_t -kmem_alloc_attr_domain(int domain, vm_size_t size, int flags, vm_paddr_t low, +static vm_offset_t +_kmem_alloc_attr_domain(int domain, vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, vm_memattr_t memattr) { vmem_t *vmem; @@ -228,16 +228,16 @@ } vm_offset_t -kmem_alloc_attr(vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, - vm_memattr_t memattr) +kmem_alloc_attr_domainset(struct domainset *ds, vm_size_t size, int flags, + vm_paddr_t low, vm_paddr_t high, vm_memattr_t memattr) { struct vm_domainset_iter di; vm_offset_t addr; int domain; - vm_domainset_iter_policy_init(&di, DOMAINSET_RR(), &domain, &flags); + vm_domainset_iter_policy_init(&di, ds, &domain, &flags); do { - addr = kmem_alloc_attr_domain(domain, size, flags, low, high, + addr = _kmem_alloc_attr_domain(domain, size, flags, low, high, memattr); if (addr != 0) break; @@ -246,6 +246,24 @@ return (addr); } +vm_offset_t +kmem_alloc_attr_domain(int domain, vm_size_t size, int flags, vm_paddr_t low, + vm_paddr_t high, vm_memattr_t memattr) +{ + + return (kmem_alloc_attr_domainset(DOMAINSET_PREF(domain), size, flags, + low, high, memattr)); +} + +vm_offset_t +kmem_alloc_attr(vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, + vm_memattr_t memattr) +{ + + return (kmem_alloc_attr_domainset(DOMAINSET_RR(), size, flags, low, + high, memattr)); +} + /* * Allocates a region from the kernel address map and physically * contiguous pages within the specified address range to the kernel @@ -254,8 +272,8 @@ * through the given flags, then the pages are zeroed before they are * mapped. */ -vm_offset_t -kmem_alloc_contig_domain(int domain, vm_size_t size, int flags, vm_paddr_t low, +static vm_offset_t +_kmem_alloc_contig_domain(int domain, vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary, vm_memattr_t memattr) { @@ -312,16 +330,17 @@ } vm_offset_t -kmem_alloc_contig(vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, - u_long alignment, vm_paddr_t boundary, vm_memattr_t memattr) +kmem_alloc_contig_domainset(struct domainset *ds, vm_size_t size, int flags, + vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary, + vm_memattr_t memattr) { struct vm_domainset_iter di; vm_offset_t addr; int domain; - vm_domainset_iter_policy_init(&di, DOMAINSET_RR(), &domain, &flags); + vm_domainset_iter_policy_init(&di, ds, &domain, &flags); do { - addr = kmem_alloc_contig_domain(domain, size, flags, low, high, + addr = _kmem_alloc_contig_domain(domain, size, flags, low, high, alignment, boundary, memattr); if (addr != 0) break; @@ -330,6 +349,25 @@ return (addr); } +vm_offset_t +kmem_alloc_contig_domain(int domain, vm_size_t size, int flags, + vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary, + vm_memattr_t memattr) +{ + + return (kmem_alloc_contig_domainset(DOMAINSET_PREF(domain), size, flags, + low, high, alignment, boundary, memattr)); +} + +vm_offset_t +kmem_alloc_contig(vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, + u_long alignment, vm_paddr_t boundary, vm_memattr_t memattr) +{ + + return (kmem_alloc_contig_domainset(DOMAINSET_RR(), size, flags, low, + high, alignment, boundary, memattr)); +} + /* * kmem_suballoc: * @@ -368,12 +406,12 @@ } /* - * kmem_malloc: + * _kmem_malloc_domain: * * Allocate wired-down pages in the kernel's address space. */ -vm_offset_t -kmem_malloc_domain(int domain, vm_size_t size, int flags) +static vm_offset_t +_kmem_malloc_domain(int domain, vm_size_t size, int flags) { vmem_t *arena; vm_offset_t addr; @@ -400,15 +438,15 @@ } vm_offset_t -kmem_malloc(vm_size_t size, int flags) +kmem_malloc_domainset(struct domainset *ds, vm_size_t size, int flags) { struct vm_domainset_iter di; vm_offset_t addr; int domain; - vm_domainset_iter_policy_init(&di, DOMAINSET_RR(), &domain, &flags); + vm_domainset_iter_policy_init(&di, ds, &domain, &flags); do { - addr = kmem_malloc_domain(domain, size, flags); + addr = _kmem_malloc_domain(domain, size, flags); if (addr != 0) break; } while (vm_domainset_iter_policy(&di, &domain) == 0); @@ -416,6 +454,20 @@ return (addr); } +vm_offset_t +kmem_malloc_domain(int domain, vm_size_t size, int flags) +{ + + return (kmem_malloc_domainset(DOMAINSET_PREF(domain), size, flags)); +} + +vm_offset_t +kmem_malloc(vm_size_t size, int flags) +{ + + return (kmem_malloc_domainset(DOMAINSET_RR(), size, flags)); +} + /* * kmem_back_domain: *