Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libbsdmalloc libbsdmalloc: Provide all allocator front e...



details:   https://anonhg.NetBSD.org/src/rev/ed701daeb618
branches:  trunk
changeset: 377260:ed701daeb618
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Tue Jul 04 15:08:55 2023 +0000

description:
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

diffstat:

 lib/libbsdmalloc/Makefile |    9 ++-
 lib/libbsdmalloc/malloc.c |  124 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 129 insertions(+), 4 deletions(-)

diffs (185 lines):

diff -r 280760d67bad -r ed701daeb618 lib/libbsdmalloc/Makefile
--- a/lib/libbsdmalloc/Makefile Tue Jul 04 15:06:36 2023 +0000
+++ b/lib/libbsdmalloc/Makefile Tue Jul 04 15:08:55 2023 +0000
@@ -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 -r 280760d67bad -r ed701daeb618 lib/libbsdmalloc/malloc.c
--- a/lib/libbsdmalloc/malloc.c Tue Jul 04 15:06:36 2023 +0000
+++ b/lib/libbsdmalloc/malloc.c Tue Jul 04 15:08:55 2023 +0000
@@ -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 @@ static char sccsid[] = "@(#)malloc.c        8.1
 #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);
+}



Home | Main Index | Thread Index | Old Index