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);
+}

Reply via email to