summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlexander Monakov <amonakov@ispras.ru>2017-12-16 14:27:25 +0300
committerRich Felker <dalias@aerifal.cx>2018-04-11 15:37:44 -0400
commit424eab2225ff3f8e3ae9f9eec9dacf2f68b71a2f (patch)
tree892438e5ca17e4bb4c990593a47357dd467cb553 /src
parent10e4bd3780050e75b72aac5d85c31816419bb17d (diff)
downloadmusl-424eab2225ff3f8e3ae9f9eec9dacf2f68b71a2f.tar.gz
optimize malloc0
Implementation of __malloc0 in malloc.c takes care to preserve zero pages by overwriting only non-zero data. However, malloc must have already modified auxiliary heap data just before and beyond the allocated region, so we know that edge pages need not be preserved. For allocations smaller than one page, pass them immediately to memset. Otherwise, use memset to handle partial pages at the head and tail of the allocation, and scan complete pages in the interior. Optimize the scanning loop by processing 16 bytes per iteration and handling rest of page via memset as soon as a non-zero byte is found.
Diffstat (limited to 'src')
-rw-r--r--src/malloc/malloc.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/src/malloc/malloc.c b/src/malloc/malloc.c
index 9e05e1d6..0a7d5d85 100644
--- a/src/malloc/malloc.c
+++ b/src/malloc/malloc.c
@@ -366,15 +366,32 @@ void *malloc(size_t n)
return CHUNK_TO_MEM(c);
}
+static size_t mal0_clear(char *p, size_t pagesz, size_t n)
+{
+#ifdef __GNUC__
+ typedef uint64_t __attribute__((__may_alias__)) T;
+#else
+ typedef unsigned char T;
+#endif
+ char *pp = p + n;
+ size_t i = (uintptr_t)pp & (pagesz - 1);
+ for (;;) {
+ pp = memset(pp - i, 0, i);
+ if (pp - p < pagesz) return pp - p;
+ for (i = pagesz; i; i -= 2*sizeof(T), pp -= 2*sizeof(T))
+ if (((T *)pp)[-1] | ((T *)pp)[-2])
+ break;
+ }
+}
+
void *__malloc0(size_t n)
{
void *p = malloc(n);
- if (p && !IS_MMAPPED(MEM_TO_CHUNK(p))) {
- size_t *z;
- n = (n + sizeof *z - 1)/sizeof *z;
- for (z=p; n; n--, z++) if (*z) *z=0;
- }
- return p;
+ if (!p || IS_MMAPPED(MEM_TO_CHUNK(p)))
+ return p;
+ if (n >= PAGE_SIZE)
+ n = mal0_clear(p, PAGE_SIZE, n);
+ return memset(p, 0, n);
}
void *realloc(void *p, size_t n)