github.com/afumu/libc@v0.0.6/musl/src/malloc/calloc.c (about)

     1  #include <stdlib.h>
     2  #include <stdint.h>
     3  #include <string.h>
     4  #include <errno.h>
     5  #include "dynlink.h"
     6  
     7  static 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  
    27  static int allzerop(void *p)
    28  {
    29  	return 0;
    30  }
    31  weak_alias(allzerop, __malloc_allzerop);
    32  
    33  void *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  }