1570af302Sopenharmony_ci#include <stdlib.h>
2570af302Sopenharmony_ci#include <stdint.h>
3570af302Sopenharmony_ci#include <string.h>
4570af302Sopenharmony_ci#include <errno.h>
5570af302Sopenharmony_ci#include "dynlink.h"
6570af302Sopenharmony_ci
7570af302Sopenharmony_cistatic size_t mal0_clear(char *p, size_t n)
8570af302Sopenharmony_ci{
9570af302Sopenharmony_ci	const size_t pagesz = 4096; /* arbitrary */
10570af302Sopenharmony_ci	if (n < pagesz) return n;
11570af302Sopenharmony_ci#ifdef __GNUC__
12570af302Sopenharmony_ci	typedef uint64_t __attribute__((__may_alias__)) T;
13570af302Sopenharmony_ci#else
14570af302Sopenharmony_ci	typedef unsigned char T;
15570af302Sopenharmony_ci#endif
16570af302Sopenharmony_ci	char *pp = p + n;
17570af302Sopenharmony_ci	size_t i = (uintptr_t)pp & (pagesz - 1);
18570af302Sopenharmony_ci	for (;;) {
19570af302Sopenharmony_ci		pp = memset(pp - i, 0, i);
20570af302Sopenharmony_ci		if (pp - p < pagesz) return pp - p;
21570af302Sopenharmony_ci		for (i = pagesz; i; i -= 2*sizeof(T), pp -= 2*sizeof(T))
22570af302Sopenharmony_ci		        if (((T *)pp)[-1] | ((T *)pp)[-2])
23570af302Sopenharmony_ci				break;
24570af302Sopenharmony_ci	}
25570af302Sopenharmony_ci}
26570af302Sopenharmony_ci
27570af302Sopenharmony_cistatic int allzerop(void *p)
28570af302Sopenharmony_ci{
29570af302Sopenharmony_ci	return 0;
30570af302Sopenharmony_ci}
31570af302Sopenharmony_ciweak_alias(allzerop, __malloc_allzerop);
32570af302Sopenharmony_ci
33570af302Sopenharmony_civoid *calloc(size_t m, size_t n)
34570af302Sopenharmony_ci{
35570af302Sopenharmony_ci	if (n && m > (size_t)-1/n) {
36570af302Sopenharmony_ci		errno = ENOMEM;
37570af302Sopenharmony_ci		return 0;
38570af302Sopenharmony_ci	}
39570af302Sopenharmony_ci	n *= m;
40570af302Sopenharmony_ci	void *p = malloc(n);
41570af302Sopenharmony_ci	if (!p || (!__malloc_replaced && __malloc_allzerop(p)))
42570af302Sopenharmony_ci		return p;
43570af302Sopenharmony_ci	n = mal0_clear(p, n);
44570af302Sopenharmony_ci	return memset(p, 0, n);
45570af302Sopenharmony_ci}
46