Tcmalloc源码简单分析(8)

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<<NBITS).

  // and        extra <= alignment

  // therefore  size + extra < (1<<NBITS)

  void* result = mmap(NULL, size + extra,

                      PROT_READ|PROT_WRITE,

                      MAP_PRIVATE|MAP_ANONYMOUS,

                      -1, 0);

  if (result == reinterpret_cast<void*>(MAP_FAILED)) {

    failed_ = true;

    return NULL;

  }

//调用mmap进行vma分配,如果分配失败,设置failed_true

  // Adjust the return memory so it is aligned

  uintptr_t ptr = reinterpret_cast<uintptr_t>(result);

  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<void*>(ptr), adjust);

  }

  首先判断adjust是否大于0,如果大于0代表着在map的是否为了迎合alignment进行了调整,那么把这部分内存返还给系统,不过返回的位置是在mmap出来空间的头上

  if (adjust < extra) {

    munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust);

  }

//然后判断是不是为了页对齐申请了额外的空间如果是,那么也将此空间返还给系统

  ptr += adjust;

  return reinterpret_cast<void*>(ptr);//返回经过调整后的指针

#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_basephysmem_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<<NBITS).

  // and        extra <= alignment

  // therefore  size + extra < (1<<NBITS)

  void *result = mmap(0, size + extra, PROT_WRITE|PROT_READ,

                      MAP_SHARED, physmem_fd, physmem_base);

//通过mmap在设备/dev/mem上面进行分配

  if (result == reinterpret_cast<void*>(MAP_FAILED)) {

    failed_ = true;

    return NULL;

  }

  uintptr_t ptr = reinterpret_cast<uintptr_t>(result);

 

  // 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<void*>(ptr), adjust);

  }

  if (adjust < extra) {

    munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust);

  }

 

  ptr += adjust;

  physmem_base += adjust + size;

 

  return reinterpret_cast<void*>(ptr);

#endif  // HAVE_MMAP

}

//mmap分配一样进行动态调整。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值