分类: LINUX
2011-10-08 15:57:40
MmapSysAllocator
void* MmapSysAllocator::Alloc(size_t size, size_t *actual_size,
size_t alignment) {
#ifndef HAVE_MMAP
failed_ = true;
return NULL;
#else
// Check if we should use mmap allocation.
// FLAGS_malloc_skip_mmap starts out as false (its uninitialized
// state) and eventually gets initialized to the specified value. Note
// that this code runs for a while before the flags are initialized.
// Chances are we never get here before the flags are initialized since
// sbrk is used until the heap is exhausted (before mmap is used).
if (FLAGS_malloc_skip_mmap) {
return NULL;
}
//上面的处理和前面brk的处理一样,都是根据参数判断是否采用mmap分配内存
// Enforce page alignment
if (pagesize == 0) pagesize = getpagesize();//获取page size的大小
if (alignment < pagesize) alignment = pagesize;
size_t aligned_size = ((size + alignment - 1) / alignment) * alignment;
//以pagesize进行对齐
if (aligned_size < size) {
return NULL;
}
size = aligned_size;
// "actual_size" indicates that the bytes from the returned pointer
// p up to and including (p + actual_size - 1) have been allocated.
if (actual_size) {
*actual_size = size;
}
// Ask for extra memory if alignment > pagesize
size_t extra = 0;
if (alignment > pagesize) {
extra = alignment - pagesize;
}
//判断alignment是否大于pagesize,如果大于那么需要一个额外的size来进行补充,以满足页对齐
// Note: size + extra does not overflow since:
// size + alignment < (1<
// and extra <= alignment
// therefore size + extra < (1<
void* result = mmap(NULL, size + extra,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0);
if (result == reinterpret_cast
failed_ = true;
return NULL;
}
//调用mmap进行vma分配,如果分配失败,设置failed_为true
// Adjust the return memory so it is aligned
uintptr_t ptr = reinterpret_cast
size_t adjust = 0;
if ((ptr & (alignment - 1)) != 0) {
adjust = alignment - (ptr & (alignment - 1));
}
// Return the unused memory to the system
if (adjust > 0) {
munmap(reinterpret_cast
}
首先判断adjust是否大于0,如果大于0代表着在map的是否为了迎合alignment进行了调整,那么把这部分内存返还给系统,不过返回的位置是在mmap出来空间的头上
if (adjust < extra) {
munmap(reinterpret_cast
}
//然后判断是不是为了页对齐申请了额外的空间如果是,那么也将此空间返还给系统
ptr += adjust;
return reinterpret_cast
#endif // HAVE_MMAP
}
DevMemSysAllocator
void* DevMemSysAllocator::Alloc(size_t size, size_t *actual_size,
size_t alignment) {
#ifndef HAVE_MMAP
failed_ = true;
return NULL;
#else
static bool initialized = false;
static off_t physmem_base; // next physical memory address to allocate
static off_t physmem_limit; // maximum physical address allowed
static int physmem_fd; // file descriptor for /dev/mem
// Check if we should use /dev/mem allocation. Note that it may take
// a while to get this flag initialized, so meanwhile we fall back to
// the next allocator. (It looks like 7MB gets allocated before
// this flag gets initialized -khr.)
if (FLAGS_malloc_devmem_start == 0) {
// NOTE: not a devmem_failure - we'd like TCMalloc_SystemAlloc to
// try us again next time.
return NULL;
}
//同样的进行check相关的flag是否置位
if (!initialized) {
physmem_fd = open("/dev/mem", O_RDWR);
if (physmem_fd < 0) {
failed_ = true;
return NULL;
}
physmem_base = FLAGS_malloc_devmem_start*1024LL*1024LL;
physmem_limit = FLAGS_malloc_devmem_limit*1024LL*1024LL;
initialized = true;
}
//如果尚未初始化physmem_fd,那么进行初始化,通过open打开相应的mem设备”/dev/mm”,并设置相关的参数physmem_base和physmem_limit。
// Enforce page alignment
if (pagesize == 0) pagesize = getpagesize();
if (alignment < pagesize) alignment = pagesize;
size_t aligned_size = ((size + alignment - 1) / alignment) * alignment;//调整size的大小,根据alignment对齐。
if (aligned_size < size) {
return NULL;
}
size = aligned_size;
// "actual_size" indicates that the bytes from the returned pointer
// p up to and including (p + actual_size - 1) have been allocated.
if (actual_size) {
*actual_size = size;
}
// Ask for extra memory if alignment > pagesize
size_t extra = 0;
if (alignment > pagesize) {
extra = alignment - pagesize;
}
//判断alignment是否大于pagesize,如果大于那么需要一个额外的size来进行补充,以满足页对齐
// check to see if we have any memory left
if (physmem_limit != 0 &&
((size + extra) > (physmem_limit - physmem_base))) {
failed_ = true;
return NULL;
}
//判断申请的内存有没有超过限制Physical memory limit
// Note: size + extra does not overflow since:
// size + alignment < (1<
// and extra <= alignment
// therefore size + extra < (1<
void *result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
MAP_SHARED, physmem_fd, physmem_base);
//通过mmap在设备/dev/mem上面进行分配
if (result == reinterpret_cast
failed_ = true;
return NULL;
}
uintptr_t ptr = reinterpret_cast
// Adjust the return memory so it is aligned
size_t adjust = 0;
if ((ptr & (alignment - 1)) != 0) {
adjust = alignment - (ptr & (alignment - 1));
}
// Return the unused virtual memory to the system
if (adjust > 0) {
munmap(reinterpret_cast
}
if (adjust < extra) {
munmap(reinterpret_cast
}
ptr += adjust;
physmem_base += adjust + size;
return reinterpret_cast
#endif // HAVE_MMAP
}
//和mmap分配一样进行动态调整。