if (SINGLE_THREAD_P) av = &main_arena; else arena_get (av, sz);
if (av) { /* Check if we hand out the top chunk, in which case there may be no need to clear. */ #if MORECORE_CLEARS oldtop = top (av); oldtopsize = chunksize (top (av)); # if MORECORE_CLEARS < 2 /* Only newly allocated memory is guaranteed to be cleared. */ if (av == &main_arena && oldtopsize < mp_.sbrk_base + av->max_system_mem - (char *) oldtop) oldtopsize = (mp_.sbrk_base + av->max_system_mem - (char *) oldtop); # endif if (av != &main_arena) { heap_info *heap = heap_for_ptr (oldtop); if (oldtopsize < (char *) heap + heap->mprotect_size - (char *) oldtop) oldtopsize = (char *) heap + heap->mprotect_size - (char *) oldtop; } #endif } else { /* No usable arenas. */ oldtop = 0; oldtopsize = 0; }
if (!SINGLE_THREAD_P) { if (mem == 0 && av != NULL) { LIBC_PROBE (memory_calloc_retry, 1, sz); av = arena_get_retry (av, sz); mem = _int_malloc (av, sz); }
if (av != NULL) __libc_lock_unlock (av->mutex); }
分配失败
1 2 3
/* Allocation failed even after a retry. */ if (mem == 0) return0;
成功之后,如果是mmap
1 2 3 4 5 6 7 8 9 10
p = mem2chunk (mem);
/* Two optional cases in which clearing not necessary */ if (chunk_is_mmapped (p)) { if (__builtin_expect (perturb_byte, 0)) returnmemset (mem, 0, sz);
#if MORECORE_CLEARS if (perturb_byte == 0 && (p == oldtop && csz > oldtopsize)) { /* clear only the bytes from non-freshly-sbrked memory */ csz = oldtopsize; } #endif
/* Unroll clear of <= 36 bytes (72 if 8byte sizes). We know that contents have an odd number of INTERNAL_SIZE_T-sized words; minimally 3. */ d = (INTERNAL_SIZE_T *) mem; clearsize = csz - SIZE_SZ; nclears = clearsize / sizeof (INTERNAL_SIZE_T); assert (nclears >= 3);
#if HAVE_MREMAP newp = mremap_chunk (oldp, nb); if (newp) { void *newmem = chunk2mem_tag (newp); /* Give the new block a different tag. This helps to ensure that stale handles to the previous mapping are not reused. There's a performance hit for both us and the caller for doing this, so we might want to reconsider. */ return tag_new_usable (newmem); } #endif /* Note the extra SIZE_SZ overhead. */ if (oldsize - SIZE_SZ >= nb) return oldmem; /* do nothing */
/* Must alloc, copy, free. */ newmem = __libc_malloc (bytes); if (newmem == 0) return0; /* propagate failure */