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