void * calloc(size_t n, size_t lb) { if ((lb | n) > GC_SQRT_SIZE_MAX /* fast initial test */ && lb && n > GC_SIZE_MAX / lb) return NULL; # if defined(GC_LINUX_THREADS) /* && !defined(USE_PROC_FOR_LIBRARIES) */ /* libpthread allocated some memory that is only pointed to by */ /* mmapped thread stacks. Make sure it's not collectable. */ { static GC_bool lib_bounds_set = FALSE; ptr_t caller = (ptr_t)__builtin_return_address(0); /* This test does not need to ensure memory visibility, since */ /* the bounds will be set when/if we create another thread. */ if (!lib_bounds_set) { GC_init_lib_bounds(); lib_bounds_set = TRUE; } if ((caller >= GC_libpthread_start && caller < GC_libpthread_end) || (caller >= GC_libld_start && caller < GC_libld_end)) return GC_malloc_uncollectable(n*lb); /* The two ranges are actually usually adjacent, so there may */ /* be a way to speed this up. */ } # endif return((void *)REDIRECT_MALLOC(n*lb)); }
char *strdup(const char *s) { size_t lb = strlen(s) + 1; char *result = (char *)REDIRECT_MALLOC(lb); if (result == 0) { errno = ENOMEM; return 0; } BCOPY(s, result, lb); return result; }
void * malloc(size_t lb) { /* It might help to manually inline the GC_malloc call here. */ /* But any decent compiler should reduce the extra procedure call */ /* to at most a jump instruction in this case. */ # if defined(I386) && defined(GC_SOLARIS_THREADS) /* Thread initialization can call malloc before we're ready for. */ /* It's not clear that this is enough to help matters. */ /* The thread implementation may well call malloc at other */ /* inopportune times. */ if (!GC_is_initialized) return sbrk(lb); # endif /* I386 && GC_SOLARIS_THREADS */ return((void *)REDIRECT_MALLOC(lb)); }
/* This is similar to strdup(). */ char *strndup(const char *str, size_t size) { char *copy; size_t len = strlen(str); if (len > size) len = size; copy = (char *)REDIRECT_MALLOC(len + 1); if (copy == NULL) { errno = ENOMEM; return NULL; } BCOPY(str, copy, len); copy[len] = '\0'; return copy; }