xref: /aosp_15_r20/external/musl/src/malloc/calloc.c (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
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