summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorriastradh <riastradh@NetBSD.org>2023-07-04 15:08:55 +0000
committerriastradh <riastradh@NetBSD.org>2023-07-04 15:08:55 +0000
commit662bbd80ce679691a3e98258b36e17e2db9c37db (patch)
treef43ecef07c339c2da11028c69f95059316eb5e35
parent53c5a21bc488abf07268f188acb1ca2d7659cec7 (diff)
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
-rw-r--r--lib/libbsdmalloc/Makefile9
-rw-r--r--lib/libbsdmalloc/malloc.c124
2 files changed, 129 insertions, 4 deletions
diff --git a/lib/libbsdmalloc/Makefile b/lib/libbsdmalloc/Makefile
index 03384670b2b..990eb406867 100644
--- a/lib/libbsdmalloc/Makefile
+++ b/lib/libbsdmalloc/Makefile
@@ -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>
diff --git a/lib/libbsdmalloc/malloc.c b/lib/libbsdmalloc/malloc.c
index 7e49b55e72b..130bb890df9 100644
--- a/lib/libbsdmalloc/malloc.c
+++ b/lib/libbsdmalloc/malloc.c
@@ -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/07 16:42:01 agc Exp $");
#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);
+}