diff --git a/share/man/man9/malloc.9 b/share/man/man9/malloc.9 index 020b729028de..7a5e36e6243c 100644 --- a/share/man/man9/malloc.9 +++ b/share/man/man9/malloc.9 @@ -49,6 +49,8 @@ .Fn mallocarray "size_t nmemb" "size_t size" "struct malloc_type *type" "int flags" .Ft void .Fn free "void *addr" "struct malloc_type *type" +.Ft void +.Fn zfree "void *addr" "struct malloc_type *type" .Ft void * .Fn realloc "void *addr" "size_t size" "struct malloc_type *type" "int flags" .Ft void * @@ -106,6 +108,19 @@ then .Fn free does nothing. .Pp +Like +.Fn free , +the +.Fn zfree +function releases memory at address +.Fa addr +that was previously allocated by +.Fn malloc +for re-use. +However, +.Fn zfree +will zero the memory before it is released. +.Pp The .Fn realloc function changes the size of the previously allocated memory referenced by diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index 3ecac176ac02..7ab6bd8b1910 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -820,6 +820,48 @@ free(void *addr, struct malloc_type *mtp) malloc_type_freed(mtp, size); } +/* + * zfree: + * + * Zero then free a block of memory allocated by malloc. + * + * This routine may not block. + */ +void +zfree(void *addr, struct malloc_type *mtp) +{ + uma_zone_t zone; + uma_slab_t slab; + u_long size; + +#ifdef MALLOC_DEBUG + if (free_dbg(&addr, mtp) != 0) + return; +#endif + /* free(NULL, ...) does nothing */ + if (addr == NULL) + return; + + vtozoneslab((vm_offset_t)addr & (~UMA_SLAB_MASK), &zone, &slab); + if (slab == NULL) + panic("free: address %p(%p) has not been allocated.\n", + addr, (void *)((u_long)addr & (~UMA_SLAB_MASK))); + + if (__predict_true(!malloc_large_slab(slab))) { + size = zone->uz_size; +#ifdef INVARIANTS + free_save_type(addr, mtp, size); +#endif + explicit_bzero(addr, size); + uma_zfree_arg(zone, addr, slab); + } else { + size = malloc_large_size(slab); + explicit_bzero(addr, size); + free_large(addr, size); + } + malloc_type_freed(mtp, size); +} + void free_domain(void *addr, struct malloc_type *mtp) { diff --git a/sys/sys/malloc.h b/sys/sys/malloc.h index 4d213c2f0364..5714e9b73db8 100644 --- a/sys/sys/malloc.h +++ b/sys/sys/malloc.h @@ -179,6 +179,7 @@ void *contigmalloc_domainset(unsigned long size, struct malloc_type *type, unsigned long alignment, vm_paddr_t boundary) __malloc_like __result_use_check __alloc_size(1) __alloc_align(7); void free(void *addr, struct malloc_type *type); +void zfree(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);