Module Name: src Committed By: riastradh Date: Tue Jul 4 15:08:55 UTC 2023
Modified Files: src/lib/libbsdmalloc: Makefile malloc.c Log Message: libbsdmalloc: Provide all allocator front ends and fork hooks. Front ends: - aligned_alloc - calloc - posix_memalign Fork hooks: - _malloc_prefork - _malloc_postfork - _malloc_postfork_child Otherwise these will pull in the jemalloc definitions from libc, which (a) defeats the purpose, and (b) won't work correctly with fork and threads. Thanks to kre@ and the thread on tech-userlevel for pointing me in the right direction to making this actually work to override jemalloc: https://mail-index.netbsd.org/tech-userlevel/2023/06/30/msg013957.html Note: libbsdmalloc doesn't set errno=ENOMEM on malloc failure, but these front ends do (even aligned_alloc, which is from C11, which doesn't define ENOMEM at all, but this pacifies our aligned_alloc tests in t_posix_memalign.c). Might want to fix that. XXX pullup-10 To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.5 src/lib/libbsdmalloc/Makefile cvs rdiff -u -r1.2 -r1.3 src/lib/libbsdmalloc/malloc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libbsdmalloc/Makefile diff -u src/lib/libbsdmalloc/Makefile:1.4 src/lib/libbsdmalloc/Makefile:1.5 --- src/lib/libbsdmalloc/Makefile:1.4 Wed Mar 21 10:08:30 2012 +++ src/lib/libbsdmalloc/Makefile Tue Jul 4 15:08:55 2023 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.4 2012/03/21 10:08:30 matt Exp $ +# $NetBSD: Makefile,v 1.5 2023/07/04 15:08:55 riastradh Exp $ NOMAN=1 @@ -9,6 +9,13 @@ WARNS= 2 LIB= bsdmalloc SRCS= malloc.c +CFLAGS+= -fno-builtin-aligned_alloc +CFLAGS+= -fno-builtin-calloc +CFLAGS+= -fno-builtin-free +CFLAGS+= -fno-builtin-malloc +CFLAGS+= -fno-builtin-posix_memalign +CFLAGS+= -fno-builtin-realloc + CPPFLAGS+= -D_REENT -D_REENTRANT -I${.CURDIR}/../libc/include/ .include <bsd.lib.mk> Index: src/lib/libbsdmalloc/malloc.c diff -u src/lib/libbsdmalloc/malloc.c:1.2 src/lib/libbsdmalloc/malloc.c:1.3 --- src/lib/libbsdmalloc/malloc.c:1.2 Thu Aug 7 16:42:01 2003 +++ src/lib/libbsdmalloc/malloc.c Tue Jul 4 15:08:55 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: malloc.c,v 1.2 2003/08/07 16:42:01 agc Exp $ */ +/* $NetBSD: malloc.c,v 1.3 2023/07/04 15:08:55 riastradh Exp $ */ /* * Copyright (c) 1983, 1993 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)malloc.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: malloc.c,v 1.2 2003/08/07 16:42:01 agc Exp $"); +__RCSID("$NetBSD: malloc.c,v 1.3 2023/07/04 15:08:55 riastradh Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -53,12 +53,18 @@ __RCSID("$NetBSD: malloc.c,v 1.2 2003/08 #if defined(DEBUG) || defined(RCHECK) #include <sys/uio.h> #endif + +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <stdint.h> #if defined(RCHECK) || defined(MSTATS) #include <stdio.h> #endif #include <stdlib.h> #include <string.h> #include <unistd.h> + #include "reentrant.h" @@ -166,7 +172,7 @@ botch(s) abort(); } #else -#define ASSERT(p) +#define ASSERT(p) ((void)sizeof((long)(p))) #endif void * @@ -493,3 +499,115 @@ mstats(s) totused, totfree); } #endif + +/* + * Additional front ends: + * - aligned_alloc (C11) + * - calloc(n,m) = malloc(n*m) without overflow + * - posix_memalign (POSIX) + * + * These must all be in the same compilation unit as malloc, realloc, + * and free (or -lbsdmalloc must be surrounded by -Wl,--whole-archive + * -lbsdmalloc -Wl,--no-whole-archive) in order to override the libc + * built-in malloc implementation. + * + * Allocations of size n, up to and including the page size, are + * already aligned by malloc on multiples of n. Larger alignment is + * not supported. + */ + +static long __constfunc +cachedpagesize(void) +{ + long n; + + /* XXX atomic_load_relaxed, but that's not defined in userland atm */ + if (__predict_false((n = pagesz) == 0)) { + mutex_lock(&malloc_mutex); + if ((n = pagesz) == 0) + n = pagesz = getpagesize(); + mutex_unlock(&malloc_mutex); + } + + return n; +} + +void * +aligned_alloc(size_t alignment, size_t size) +{ + char *p; + + if (alignment == 0 || + (alignment & (alignment - 1)) != 0 || + alignment > cachedpagesize() || + (size & (alignment - 1)) != 0) { + errno = EINVAL; + return NULL; + } + p = malloc(size); + if (__predict_false(p == NULL)) + ASSERT((uintptr_t)p % alignment == 0); + return p; +} + +void * +calloc(size_t nmemb, size_t size) +{ + void *p; + size_t n; + + if (__builtin_mul_overflow_p(nmemb, size, (size_t)0)) { + errno = ENOMEM; + return NULL; + } + n = nmemb * size; + p = malloc(n); + if (__predict_false(p == NULL)) + return NULL; + memset(p, 0, n); + return p; +} + +int +posix_memalign(void **memptr, size_t alignment, size_t size) +{ + char *p; + + if (alignment < sizeof(void *) || + (alignment & (alignment - 1)) != 0 || + alignment > cachedpagesize()) + return EINVAL; + p = malloc(size < alignment ? alignment : size); + if (__predict_false(p == NULL)) + return ENOMEM; + ASSERT((uintptr_t)p % alignment == 0); + *memptr = p; + return 0; +} + +/* + * libc hooks required by fork + */ + +#include "../libc/include/extern.h" + +void +_malloc_prefork(void) +{ + + mutex_lock(&malloc_mutex); +} + +void +_malloc_postfork(void) +{ + + mutex_unlock(&malloc_mutex); +} + +void +_malloc_postfork_child(void) +{ + + mutex_unlock(&malloc_mutex); +}