about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2020-06-10 20:44:51 -0400
committerRich Felker <dalias@aerifal.cx>2020-06-10 20:51:17 -0400
commit25cef5c591fbee755a53f0d7920f4f554f343a53 (patch)
tree13b38ac1a7522dcc2f988407187a98bc0612a888
parent501a92660ca2ed6469a0a01474574ce9930356cd (diff)
downloadmusl-25cef5c591fbee755a53f0d7920f4f554f343a53.tar.gz
musl-25cef5c591fbee755a53f0d7920f4f554f343a53.tar.xz
musl-25cef5c591fbee755a53f0d7920f4f554f343a53.zip
reintroduce calloc elison of memset for direct-mmapped allocations
a new weak predicate function replacable by the malloc implementation,
__malloc_allzerop, is introduced. by default it's always false; the
default version will be used when static linking if the bump allocator
was used (in which case performance doesn't matter) or if malloc was
replaced by the application. only if the real internal malloc is
linked (always the case with dynamic linking) does the real version
get used.

if malloc was replaced dynamically, as indicated by __malloc_replaced,
the predicate function is ignored and conditional-memset is always
performed.
-rw-r--r--src/internal/dynlink.h1
-rw-r--r--src/malloc/calloc.c10
-rw-r--r--src/malloc/oldmalloc/malloc.c5
3 files changed, 15 insertions, 1 deletions
diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h
index b739add2..78baa080 100644
--- a/src/internal/dynlink.h
+++ b/src/internal/dynlink.h
@@ -107,5 +107,6 @@ hidden ptrdiff_t __tlsdesc_static(), __tlsdesc_dynamic();
 
 hidden extern int __malloc_replaced;
 hidden void __malloc_donate(char *, char *);
+hidden int __malloc_allzerop(void *);
 
 #endif
diff --git a/src/malloc/calloc.c b/src/malloc/calloc.c
index 322193ca..bf6bddca 100644
--- a/src/malloc/calloc.c
+++ b/src/malloc/calloc.c
@@ -2,6 +2,7 @@
 #include <stdint.h>
 #include <string.h>
 #include <errno.h>
+#include "dynlink.h"
 
 static size_t mal0_clear(char *p, size_t n)
 {
@@ -23,6 +24,12 @@ static size_t mal0_clear(char *p, size_t n)
 	}
 }
 
+static int allzerop(void *p)
+{
+	return 0;
+}
+weak_alias(allzerop, __malloc_allzerop);
+
 void *calloc(size_t m, size_t n)
 {
 	if (n && m > (size_t)-1/n) {
@@ -31,7 +38,8 @@ void *calloc(size_t m, size_t n)
 	}
 	n *= m;
 	void *p = malloc(n);
-	if (!p) return p;
+	if (!p || (!__malloc_replaced && __malloc_allzerop(p)))
+		return p;
 	n = mal0_clear(p, n);
 	return memset(p, 0, n);
 }
diff --git a/src/malloc/oldmalloc/malloc.c b/src/malloc/oldmalloc/malloc.c
index 1c6b07ec..0a38690c 100644
--- a/src/malloc/oldmalloc/malloc.c
+++ b/src/malloc/oldmalloc/malloc.c
@@ -339,6 +339,11 @@ void *malloc(size_t n)
 	return CHUNK_TO_MEM(c);
 }
 
+int __malloc_allzerop(void *p)
+{
+	return IS_MMAPPED(MEM_TO_CHUNK(p));
+}
+
 void *realloc(void *p, size_t n)
 {
 	struct chunk *self, *next;