分类: LINUX
2011-10-08 15:54:16
New中的MetaDataAlloc函数定义在common.cc中,通过调用TCMalloc_SystemAlloc来分配内存,维护一个全局变量metadata_system_bytes用来存储已经分配的内存数。TCMalloc_SystemAlloc首先通过变量system_alloc_inited判断SystemAlloc是否已经初始化,如果没有将调用InitSystemAllocators进行初始化。Allocators是一个包含5个Allocator的数组,allocators[2]被定义为DevMemSysAllocator,DevMemSysAlloctor通过mmap /dev/mem的方式来分配内存(后面会详细分析)。而如果开启的是debug模式(kDebugMode)且在64-bits模式下(sizeof(void*) > 4)那么还将初始化allocators[3]为MmapSysAllocator和allocators[4]为SbrkSysAllocator,让mmap在sbr前被调用,而如果以上条件不符合那么sbrk将在mmap前被调用。allocators [0]在函数InitSystemAllocator中被初始化为HugetlbSysAllocator,而allocators[1]没有发现在何处初始化。
void InitSystemAllocators(void) {
// This determines the order in which system allocators are called
int i = kMaxDynamicAllocators;
allocators[i++] = new (devmem_space) DevMemSysAllocator();
// In 64-bit debug mode, place the mmap allocator first since it
// allocates pointers that do not fit in 32 bits and therefore gives
// us better testing of code's 64-bit correctness. It also leads to
// less false negatives in heap-checking code. (Numbers are less
// likely to look like pointers and therefore the conservative gc in
// the heap-checker is less likely to misinterpret a number as a
// pointer).
if (kDebugMode && sizeof(void*) > 4) {
allocators[i++] = new (mmap_space) MmapSysAllocator();
allocators[i++] = new (sbrk_space) SbrkSysAllocator();
} else {
allocators[i++] = new (sbrk_space) SbrkSysAllocator();
allocators[i++] = new (mmap_space) MmapSysAllocator();
}
}
TCMalloc_SystemAlloc在初始化完毕后,判断alignment是否符合最小对齐,如果不符合那么设置alignment sizeof(MemoryAligner);MemoryAligner是一个union最大应该是64bytes。
void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size,
size_t alignment) {
// Discard requests that overflow
if (size + alignment < size) return NULL;
SpinLockHolder lock_holder(&spinlock);
if (!system_alloc_inited) {
InitSystemAllocators();
system_alloc_inited = true;
}
// Enforce minimum alignment
if (alignment < sizeof(MemoryAligner)) alignment = sizeof(MemoryAligner);
从此处开始,CMalloc_SystemAlloc开始尝试Alloc内存,它会尝试两次,每次都是从allcator[0]开始,到allcator[kMaxAllocators -1]。每个SysAllocator有两个参数分别是usable_ &&failed_,分别用来表示此alloc是否可用以及是否上次分配是已经失败。
// Try twice, once avoiding allocators that failed before, and once
// more trying all allocators even if they failed before.
for (int i = 0; i < 2; i++) {
for (int j = 0; j < kMaxAllocators; j++) {
SysAllocator *a = allocators[j];
if (a == NULL) continue;
if (a->usable_ && !a->failed_) {
void* result = a->Alloc(size, actual_size, alignment);
if (result != NULL) return result;
}
}
// nothing worked - reset failed_ flags and try again
for (int j = 0; j < kMaxAllocators; j++) {
SysAllocator *a = allocators[j];
if (a == NULL) continue;
a->failed_ = false;
}
}
return NULL;
}