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