xref: /third_party/musl/src/malloc/calloc.c (revision 570af302)
1#include <stdlib.h>
2#include <stdint.h>
3#include <string.h>
4#include <errno.h>
5#include "dynlink.h"
6
7static size_t mal0_clear(char *p, size_t n)
8{
9	const size_t pagesz = 4096; /* arbitrary */
10	if (n < pagesz) return n;
11#ifdef __GNUC__
12	typedef uint64_t __attribute__((__may_alias__)) T;
13#else
14	typedef unsigned char T;
15#endif
16	char *pp = p + n;
17	size_t i = (uintptr_t)pp & (pagesz - 1);
18	for (;;) {
19		pp = memset(pp - i, 0, i);
20		if (pp - p < pagesz) return pp - p;
21		for (i = pagesz; i; i -= 2*sizeof(T), pp -= 2*sizeof(T))
22		        if (((T *)pp)[-1] | ((T *)pp)[-2])
23				break;
24	}
25}
26
27static int allzerop(void *p)
28{
29	return 0;
30}
31weak_alias(allzerop, __malloc_allzerop);
32
33void *calloc(size_t m, size_t n)
34{
35	if (n && m > (size_t)-1/n) {
36		errno = ENOMEM;
37		return 0;
38	}
39	n *= m;
40	void *p = malloc(n);
41	if (!p || (!__malloc_replaced && __malloc_allzerop(p)))
42		return p;
43	n = mal0_clear(p, n);
44	return memset(p, 0, n);
45}
46